-
-
Save graue/5079734 to your computer and use it in GitHub Desktop.
NOTE: Scroll down for explanation (the difference turns out to be scoping, not closures per se). | |
$ cat juices.lua | |
local fruits = {"apple", "orange", "grape"} | |
local juicers = {} | |
for i,v in ipairs(fruits) do | |
local fruit = v | |
juicers[i] = function() return fruit .. " juice" end | |
end | |
print(juicers[1]()); | |
print(juicers[2]()); | |
print(juicers[3]()); | |
$ lua juices.lua | |
apple juice | |
orange juice | |
grape juice | |
$ cat juices.js | |
var fruits = ["apple", "orange", "grape"]; | |
var juicers = []; | |
for (var i in fruits) { | |
var fruit = fruits[i]; | |
juicers[i] = function() { return fruit + " juice"; } | |
} | |
console.log(juicers[0]()); | |
console.log(juicers[1]()); | |
console.log(juicers[2]()); | |
$ node juices.js | |
grape juice | |
grape juice | |
grape juice |
So closures actually work the same way in Lua as in JavaScript and Python. If you write the loop like this in Lua:
local fruit = ""
for i,v in ipairs(fruits) do
fruit = v
juicers[i] = function() return fruit .. " juice" end
end
print(juicers[1]());
print(juicers[2]());
print(juicers[3]());
...you again get "grape juice" three times. None of the 3 languages are copying variables when they create a closure. In all three languages, the closure references the original variable, which can change.
But in Lua, a new variable called v
is created in each iteration of the loop; it doesn't update the old v
. Likewise in the code up top, a new local variable called fruit
was created on each iteration of the loop. In this version here we had to explicitly override that behavior. Closures are the same between Lua and JS/Python; scoping is not.
yeah, so long story short, block scoping makes the world sane and python and javascript are inferior for not having it. that's my conclusion to all this :)
OK, I'm starting to understand.
This JS code does what I want:
It seems the actual difference between JS and Lua is indeed one of scope, but it isn't lexical vs. dynamic scoping. In JavaScript, only a function creates its own scope. An
if
block, for example, doesn't:While in Lua, any block has its own scope:
Again, Python works like JavaScript in this respect. One might expect that
juiced_fruit
here is a local variable, only existing inside the for loop:But it's not:
Python needs a function to supply a more specific scope, like JS: