« Big Numbers | Main | Thesis submitted »

Dept. of Wheel Reinvention

From the brief on Apple's new concurrency framework, Grand Central Dispatch:

Blocks are a simple extension to C (as well as Objective-C and C++) that make it easy for you to define self-contained units of work. A block in code is denoted by a caret at the beginning of a function. For example, you could declare a block and assign it to x by writing:

    x = ^{ printf("hello world\n"); }
This turns the variable x into a way of calling the function so that calling x( ); in the code would print the words hello world.

What’s really powerful about blocks is that they enable you to wrap much more complex functions—as well as their arguments and data—in a way that can be easily passed around in a program, much as a variable can be easily referenced and passed.

Underneath this is a diagram showing that a block is like a function with some associated data.

I think I've seen this idea before somewhere. :-)

Ah, but a closure by any other name would smell as sweet...


The 80s called, they'd like you to know that Obj-C's blocks are called blocks because they're lifted from Smalltalk which called these blocks (http://en.wikipedia.org/wiki/Smalltalk#Code_blocks).

Also, that blocks are not closures, they're lambdas and they form closures.



The name "block" is also used for much the same idea in Ruby.

It isn't a closure, just like how ruby blocks are not actually closures.

Best you review what a closure actually is before you go calling something a closure. For instance, python doesn't have closures (no lambdas in python are not closures). If you don't understand why not, then you don't understand closures.

This is fast becoming my most controversial post yet!

There is some distinction between the syntactic object (say a "block" or a "lambda") and the runtime value that it evaluates to, which additionally captures the values of the block's free variables.

Also, there are different semantic choices in defining closures. In some languages, closures capture the current value of some variables but not others—the others would be examined at invocation time.

In Ruby, which I don't speak well, it's not clear to me whether you can actually have a variable that holds a closure, or if you can only construct closures at the point of calling another function (method). The latter would restrict them quite a bit, and maybe you'd say that these aren't "real" closures.

Other than that, I'm not sure what distinction you guys are making! Please say more, if I've missed something.

derivative = lambda f, dx: lambda x: (f(x + dx) - f(x)) / dx

@Reddit Users: What would you call the above Python construct then?

It's only a closure if it captures a variable in an outer scope. Otherwise, it's just an anonymous function/method. Pseudocode example:

x = { print("Not inside a closure."); };

y = 42;

z = { print("The fact that I can print the value '" + y "' means that I'm inside a closure!"); };

The difference is subtle but supremely important. Closures are extremely good at simplifying some of the parameter-passing details of a callback- or event-driven API. Rather than the traditional C style of passing your function pointer and an opaque void*, you can pass a closure built from whatever local scope you want, essentially freezing and storing that particular stack frame until the function gets called. Definitely less verbose syntactically than packing all your parameters into a struct or something, passing a void*, then unpacking, dereferencing, etc. just to get right back to the same data that you had handy when you registered your callback or event handler in the first place. Also, it makes the whole thing much more flexible when you need to maintain code. No need to redefine structs, change method signatures, etc. when you need that inevitable one more piece of data in your callback function or event handler.

I know that Ruby's blocks capture free variables from the surrounding scope.

In the Objective C case, the picture in the Apple documentation (linked in the post) suggests that data is captured in the closure, but I haven't played around with it.

Python doesn't have lexical scope, you're not binding to that value of f or x you're simply using the variable name. It may mutate on you.

The lack of actual lexical scope in python means you can't have a real closure. python's late binding means that had you made a for loop where i made a new lambda, that i would not be captured. All those lambdas would have the same value for i.


(let ((yb))   ;; free variable                                                              
  (defun greater-than-last-num (x)                                                          
    (let ((res nil))                                                                        
      (if (and (numberp yb)      ;; referencing yb makes this a closure                                                                          
               (> x yb))               
          (setf res t))                                                                     
      (setf yb x)                                                                           

Justin, if your example is a closure then we'd have to say that every language with mutable global variables has closures. e.g. C, Java.

Most examples of closures involve closing over an environment provided by a function wrapping another function.

Python has closures, and has had closures since the first public release in the early 1990s. Of older versions of Python, some mistakenly said that Python did not have closures because some aspects of the closure's scope were not mutable by the closed-over function. But if that were true, then that would mean that Haskell does not have closures either. Because NO aspects of a Haskell function's environment are mutable, so Haskell is even more limited in this regard (by design, and with good reason). But I've never heard that claim made that Haskell does not have closures.

So Python has always had closures, but they were more limited in function than Scheme or Lisp closures (just as Haskell closures are -- by design -- more limited than Scheme or Lisp closures). Nevertheless, with Python 3.x, even that is not true. Python's closures are exactly the same as Lisp or Scheme closures.

I'll also point out that wikipedia claims that Python has closures. Wikipedia could be wrong, but it has had a lot more eyeballs on it, and thought put into it than the comments on this blog post. If it is wrong, it would be more effective to go fix it rather than argue about what it says here.

I'll adjust Justin's example to be a true closure and show how to do it in Python 2.x and Python 3.x. (apologies for the extra newlines: not sure where those are coming from)

Python 1.x-3.x

def create_greater_than_last_num():
    _yb = [None]    # free variable
    def greater_than_last_num(x):
        res = False
        yb = _yb[0]
        if isinstance(yb, int) and x > yb:
            res = True
        _yb[0] = x
        return res
    return greater_than_last_num

greater_than_last_num = create_greater_than_last_num()
print greater_than_last_num(5)
print greater_than_last_num(6)
print greater_than_last_num(7)
print greater_than_last_num(6)
print greater_than_last_num(5)
print greater_than_last_num(6)

Python 3.x:

def create_greater_than_last_num():
    yb = None    # free variable
    def greater_than_last_num(x):
        nonlocal yb
        res = False
        if isinstance(yb, int) and x > yb:
            res = True
        yb = x
        return res
    return greater_than_last_num

greater_than_last_num = create_greater_than_last_num()

As you can see, Python has always had closures, previously the closures had some limitations that were easy to work around, and now the closures are as full-featured as in any other language.

The new Objective-C/C blocks are closures, though somewhat hackily, as they definitely close over variables in outer scopes for read access.

However, if you need write access to a given variable in an outer scope, you have to declare the variable with a __block prefix.

The new Objective-C/C blocks are really closures (well, ok, lambdas), as they definitely close over variables in outer scopes for read access.

However, if you need write access to a given variable in an outer scope, you have to declare the variable with a __block prefix.

So they're somewhat hacky.

And, if the block (a real Objective-C object) is going to outlast its creating function, it has to be manually copied to the heap. (But that's done automatically by most of their uses in the whole Grand Central Dispatch scheme that Apple is using.)

"As you can see, Python has always had closures"

Always is a pretty long time -- Python hasn't *always* had the ability for users to define new classes!

I believe closure semantics were added to Python as an optional feature in 2.1, and always-on in 2.2, dating to 2001. Many years, yes, but not always.

Tim is right: closures were added to Python in 2001. Really old versions of Python ignored variables defined in scopes that were between local and "global" (i.e. module). I remembered that while I was commuting today.

I'll risk being wrong for a second time by challenging your claim that Python "originally" did not have user-defined classes. According to Guido, version 0.9.0 already had user-defined classes. Of course one could play with definitions of "always" to say that Python did not "always" have an "if" statement, but I think that by any reasonable definition, Python has always had user-defined classes.

That is a really good tip particularly to those fresh to the blogosphere.
Simple but very accurate information? Thank you for sharing this one.
A must read article!

It's great that you are getting ideas from this post as well as from our argument made at this place.

Nice download hyperlinks.

A few, like Royal prince, took in order to providing their particular
cds aside free of charge in an attempt to a minimum of oversee the actual distribution of the work.
The most famous strategy in order to combat the internet?

For hottest news you have to go to see world wide web and on
internet I found this website as a most excellent web site for latest

Post a comment