Agreed. I find it quite a bit more elegant overall, and I decided to just jump in and do my throwaway scripts in Lua and see how much of a difference that makes. If I like it enough to write a few small libraries along the way, everybody wins.
Lua has tail-call elimination, coroutines, closures, and lambdas. I'm pretty sure Python has none of these, except for (possibly) a limited form of coroutines. (The Python lambda is too crippled, its closures are broken.) Lua is also one of the most deliberately portable languages I've seen, too. I have a hunch it would be a great language for bootstrapping a Lisp or Scheme compiler, though I haven't tried this yet.
>>> def makeAdder(x):
def inc(y):
return y+x
return inc
>>> f = makeAdder(3)
>>> f(4)
7
So far, so good. >>> def makeAdder2(x):
v = x
def inc(y):
v += y
return v
return inc
>>> f2 = makeAdder2(3)
>>> f2(4)
Traceback (most recent call last):
File "<pyshell#15>", line 1, in <module>
f2(4)
File "<pyshell#13>", line 4, in inc
v += y
UnboundLocalError: local variable 'v' referenced before assignment
>>>
It looks like you can't mutate variables in a closure. Am I doing it wrong? If you really can't, that seriously limits their power.--
In Lua:
> function adder(x)
local v = x
function inc(y)
v = v + y
return v
end
return inc
end
>> >> >> >> >> >> >> > f = adder(3)
> =f(4)
7
> =f(4)
11
> =f(4)
15
>
Works fine. (Also, the syntax is really clean.)def makeAdder2(x):
v = [x,]
def inc(y):
v[0] += y
return v[0]
return inc
works just fine in all pythons with closures (2.0 and above?)def makeAdder2(x):
def inc(y, v=[x,]):
v[0] += y
return v[0]
return inc
Also works and provides a mechanism for resetting the state.Good to know it's possible, though I'd rather it handle closures / lexical scoping directly.
Generally I do not mutate variables as far as possible, so I have not hit this problem myself, yet. Perhaps there is someone more knowledgeable about Python to step in.
Ironically, I may be switching from Python to Lua now, for the same reason.