Hacker News new | past | comments | ask | show | jobs | submit login

That word, closure. You keep using it, but I do not think it means what you think it means.

A closure is an runtime structure used to implement static scope of locally-defined first-class functions. Closures allow locally-defined functions to "remember" variable bindings in their enclosing scope.

Beside that you can implement this feature WITHOUT closures (e.g. source rewriting), none of the examples presented actually require static scope!!

It boggles my mind that programmers can have such strong opinions on language features without actually knowing what they're called.




Yes, this has been one of my pet peeves for a while too. Everybody: a closure, as the parent says, is an implementation construct. It is not something you can find in your source code. The syntactic construct -- the thing you write in your code -- is called a lambda expression. Not a "lambda function", and not a "closure"!

Lambda expressions are to closures as `new' expressions are to instances: a lambda expression evaluates to a closure, and a `new' expression evaluates to an instance. Since any expression can be evaluated multiple times, in general the relationship is one-to-many: a lambda expression can be evaluated N times to produce N closures, just as a `new' expression can be evaluated N times to produce N instances.

(Instances and closures are closely related: an instance is a piece of state with several operations that can be invoked on it, while a closure is a piece of state with one operation that can be invoked on it.)


Your insistence on a specific meaning for the words ignores how words are actually used: overloaded based on context. If I call these things 'closures', you understand I'm talking about the 'lambda expressions' and not the implementation construct.

  class Foo
  end
There, a class object. Oh sorry, an object is an implementation construct; what you have there is an expression that produces an object... <- that is unhelpful semantic squabbling. It's highly inconvenient to use such indirect language. This is the view of a class object that I have most of the time and a 'lambda expression' is the view I have of a closure most of the time.

If I see the Eiffel tower, I say: look, the Eiffel tower. Not: look, an image of the Eiffel tower, with some details obscured by clouds and smoke and without considering any of the construction details and history that are an essential part of the Eiffel tower. For all practical purposes of communication, it's the Eiffel tower.


That's not a fair example. There are languages that have lambda expressions but not the lexical scope that requires closures, whereas there are no languages that have class definition expressions but not classes.

Given there is a meaningful distinction to be made, insistence on accurate terminology becomes a lot more reasonable.


> Instances and closures are closely related: an instance is a piece of state with several operations that can be invoked on it, while a closure is a piece of state with one operation that can be invoked on it.

I would go further, and say that they're equivalent—that "one operation" can be a dispatch function:

    def make_object
      x = 5
      lambda do |m|
        case m
        when 'increment'
          x += 1
        when 'decrement'
          x -= 1
        when 'get'
          x
        end
      end
    end

    o = make_object
    o.call('get')       # => 5
    o.call('increment') # => 6
    o.call('decrement') # => 5


In fact, in SICP, they build their object system in this way, if my memory serves me correctly.


Of course. Closures are, after all, a poor man's objects[1].

[1] http://codermonk.blogspot.com/2007/01/venerable-master-qc-na...


That's a really good explanation.


I'm not the author, and I think this was kind of a cop out, but:

http://notes-on-haskell.blogspot.com/2007/02/whats-wrong-wit...

"A few people have commented that none of the examples use closures, but in Haskell closures are used not only to represent functions but also unevaluated values (i.e., thunks). For example, in the simple expression

total = sum array

the variable array is free and refers to some value, possibly unevaluated, in the enclosing environment. Until the value of total is evaluated it exists as a thunk that closes over array (and sum, for that matter).

So the examples do indeed use closures.

Cheers! ---Tom"


You know, he's totally correct (Haskell being lazy and all) but I think he missed the point entirely :P


I know I am repeating a previous comment but the author correctly explains it here

http://notes-on-haskell.blogspot.com/2007/02/whats-wrong-wit...

In Haskell all parameters are lazy by default, which effectively turns every parameter into a closure.

for e.g., consider the code

boost x = map (x) [1..10]

total = sum (boost 2)

On invocation of the sum function, the (boost 2) is not necessarily evaluated. Instead a reference to ((x -> map (x) [1..10]) 2) is passed in to sum. So sum will now end up actually accessing x which has been bound to the value 2. When written this way, the binding of x to 2 is more explicit, but this is the way Haskell evaluates expressions and function calls by default. So (boost 2) might not actually look like a closure, but it effectively is.

Thanks to Haskell's purity, GHC can actually turn this expression into a plain for loop with no lists being constructed. At least in the context of Haskell, this makes discussions of the "runtime structure that represents a closure" meaningless as there may be no run time structures at all, not even a list, much less a closure.

Any value, which doesn't even look like a function/closure could be referencing an unevaluated function with any kind of "variable"[1] bindings.

[1] - Haskell is pure and does not have variables, only constants and functions.




Consider applying for YC's W25 batch! Applications are open till Nov 12.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: