In ruby, module
, class
, and def
keywords define a new scope. I'm confused as to why local variables defined in a block do not exist outside of the block. Is a block argument another scope gate? For example:
(1..2).each { |n| numer = 'czesc' }
numer # => NameError: undefined local variable or method `czesc' for main:Object
Or more simply:
def kon; end
kon { kot = 3 }
kot # => NameError: undefined local variable or method `kot' for main:Object
I thought, maybe it's not persisted because it's defined in the method's arguments, but the following works for the normal arguments:
def pokaz(cos)
p cos
end
pokaz(co = "to")
co # => "to"
There are six scope constructs in Ruby: module bodies, class bodies, method bodies and script bodies create new scopes, block bodies and "stabby lambda" literal bodies create new nested scopes.
Because a block body has its own lexical scope. The scope is nested, which means that it has access to local variables from the outer scope, but variables from an inner scope never leak into the outer scope.
You might think about codeblocks as of lazy instances of
Proc
class.Your second example with
kon
/kot
does actually not what you were expecting from it. You supply a codeblock to a functionkon
. This codeblock is not evaluated unless requested. In your snippet it is never evaluated. Look:You passed a codeblock. Fine. Now
kon
should invoke it, if needed:When you passed a codeblock to, say,
each
method ofEnumerator
instance:The codeblock is being evaluated in context of this
Enumerator
. The default receiver,self
, is still the main thread, though. That makes codeblocks to act mostly like closures (they have an access to the caller bindings):Hope it sheds some light.