how to use truly local variables in ruby proc/lambda

Sometimes it is the desired behavior:

total = 0
(1..10).each{|x| total += x}
puts total

But sometimes it's accidental and you don't want to mess with an outside variable which happens to have the same name. In that case, follow the list of parameters with a semicolon and a list of the block-local variables:

x = lambda{|v; x| x = 2; v}
p x.call(3) #3
p x #<Proc:[email protected]:2 (lambda)>

The reason for this is that the lambda is bound to its defining scope (NOT its calling scope), and is a full closure, which, among other things, includes the local variable x. What you really want here is an unbound proc to pass around and call without any particular binding. This isn't something that Ruby does very easily at all, by design (it's possible with eval, but that's less of a block and more just of a string statement). Procs, lambdas, and blocks are all bound to their defining scope. Lexical scope is only established on classes, modules, and methods; not on blocks/procs/lambdas/anything else.

It's worth noting that Python doesn't even permit assignment in lambdas in the first place.

Tags:

Ruby