Of course it should change i after the closure was defined, since the closure doesn't copy but refer to that i.
Looks like a fully proper closure.
Which language does this differently?
Of course it should change i after the closure was defined, since the closure doesn't copy but refer to that i.
Looks like a fully proper closure.
Which language does this differently?
var f = {[i] in print("hello I'm a callback and i =", i)}I think some imperative languages still refer to those things as closures, which is unfortunate. Capturing a closure then having everything in there mutable kind of defeats the purpose in my opinion. But maybe I've been damaged/spoiled by functional programming and/or have spent to much time debugging issues related to concurrency and shared mutable state.
On the other hand, if your closure depends on global mutable state, than you have a piece of GLOBAL state that is VARIABLE. Sometimes known as the root of all evil.
But maybe I've been damaged/spoiled by scheme and/or not done enough concurrency programming to get your point.
An empirical observation says that the most important software in the world, including most of the internet infrastructure, OSes, databases, filesystems, office suites, embedded systems and such, powering 99% of the modern era is written in an imperative or OO language.
That's a fact. Whereas "there would be less issues if we had made them in a functional language" is mere conjecture, unless proven otherwise.
Note that common errors such as null pointer exceptions are not only avoided in functional languages for example, but in any imperative language with optionals, bounds checking etc too. So if one is gonna bring those up as something in favor of functional programming they're not giving the full picture.
I've found that in swift the things that should be values are and the things that should be references are, rather than taking an all or nothing approach.
dispatch_async(my_background_queue) {
do_some_io()
let result = do_expensive_computation()
dispatch_async(dispatch_get_main_queue()) {
self.value = result
update_ui()
}
} int x = 0;
void (^block)(void) = ^{ NSLog(@"%d", x); };
x++;
block();
This will log 0, not 1. If you want to capture by reference rather than by value, you add __block to the declaration of x.For a lot of people coming to Swift from Objective-C, this is a surprising change, especially if Objective-C was their first language with closures.
A closure is just a function that captures ("closes over") the surrounding scope.
Edit: strictly speaking, the construct here is an anonymous function. Objective-C calls them "blocks" and Swift calls them "unnamed closures" or "closure expressions." Both are, or at least can be, closures. (I'm not sure if the term "closure" can be used to refer to a function that could refer to variables in the enclosing scope but doesn't. Probably not.)
Blocks are in fact lambdas, or at least closures. I was wrong in the above. In some early versions of smalltalk, blocks had some odd semantics that made them different, but this is no longer true. However, judging by the Objective-C example above, Objective-C blocks don't create true closures, as a true closure would have the semantics of the Swift code from the article.
NSView *view = [NSButton new];
void (^block)(void) = ^{ NSLog(@"%@", view); };
view = [NSTextField new];
block();
In Objective-C, this will log an NSButton. Translate it to Swift and it will log an NSTextField.I don't think either behavior is more correct, it's just a fairly arbitrary choice. IMO it's surprising only if you've learned to expect one way because you worked in a language that does it that way, then encounter a language that does it the other way.
Languages with immutable bindings (the author is one of the original designers and implementers of Erlang)
Proper closures should only contain pointers into immutable data (which is the case in Erlang) - no pointers into mutable data. If a closure contains a pointer into mutable data and you change the data later you break the closure. This means you can’t parallelize your program and even sequential code can contain weird errors.
Haskell doesn't have mutable state; it still has closures.
Mutable or immutable is somewhat orthogonal; I admit, coming from Erlang to Javascript I was -shocked- and very facepalmy when I learned that closures close over variables that can still vary. That is, I couldn't just pass back a function and expect it to behave the same way depending when I called it. I had to add an additional scope in place and bind the values anew (i.e., a new function, passing the values being closed over into it as params). Immutable is much easier to reason about, much easier to write with, and despite being more limited in what you can do with them, I'd argue just as useful. Everything it prevents you from doing there is some other, safe way of achieving; the same as comparing mutable vs immutable in other contexts.
Well it should not allow it and make ia clone / copy-on-write thing /etc. Calling that a closure sounds broken. Just like Joe points out.
> Which language does this differently?
Haskell, Elixir, OCaml, Erlang
What I think a lot of people fail to understand is that a closure is not a special object, with magical powers, but a direct consequence of lexical scoping: closures just follow the lexical scope rules, even if their lexical scope isn't within the current dynamic scope. If a variable within the closure's lexical scope changes, the closure won't keep the value the same. Here's an example of these semantics in C:
int global = 4;
void oh_noes(){
printf("%d", global);
}
global++;
oh_noes(); //prints 5
If somebody complained that the function oh_noes should print 4 in this example, you'd think they were insane. Closures actually work in exactly the same way.That is how it is implemented. It doesn't have to be, I have a list of example languages where it is not the case.
> What I think a lot of people fail to understand is that a closure is not a special object, with magical powers,
Maybe that's why I like functional languages, it does seem like they have magical powers ;-) there.
No, you don't. Closures in those are also a direct consequence of lexical scoping. But those languages don't have mutable variables, regardless of closures.
Functions defined in modules in Erlang are different from closures. Here is a example:
-module(e).
-compile(export_all).
f()-> 1.
g()-> fun ()-> 1 end.
$ erl
> c(e).
> erlang:fun_info(fun e:f/0).
[{module,e},{name,f},{arity,0},{env,[]},{type,external}]
> erlang:fun_info(e:g()).
[{pid,<0.42.0>},
{module,e},
{new_index,0},
{new_uniq,<<136,230,191,77,132,145,66,52,216,215,111,24,
18,188,4,169>>},
{index,0},
{uniq,71775738},
{name,'-g/0-fun-0-'},
{arity,0},
{env,[]},
{type,local}]
To get info on e:f it has to be become a closure-like object, but if you see internally it is still represented differently than a closure.> Closures in those are also a direct consequence of lexical scoping.
Not sure what you mean a direct consequence. Are you saying that closures follow scoping rules? The point was that it doesn't necessarily follow that they have to be implemented as object instances in object oriented languages, or function pointers, or functions (say like in Erlang).
//foo.c
int global = 0;
int quuxify(){
return global++;
}
//bar.c
extern int quuxify();
printf("%d", quuxify());//prints "0"
printf("%d", quuxify());//prints "1"
even though quuxify() depends on global, which is out of scope in bar.c, the call still compiles. Why? because C is a lexically scoped language, and so variable references in functions refer to the scope the function was declared in, NOT the one it was called in.And you thought C didn't have closures ;-D
> Which language does this differently?
Rust does it this way but in a less error prone way due to its sophisticated ownership tracking. If you close over a variable in the environment, it gives the ownership to the closure and you can't then rebind it outside.