A local variable has a name starting with a lower case letter or an
underscore character (_). Local variables do
not, like globals and instance variables, have the value
nil before initialization:
ruby> $foo nil
ruby> @foo nil
ruby> fooERR: (eval):1: undefined local variable or method `foo' for main(Object)
The first assignment you make to a local variable acts something
like a declaration. If you refer to an uninitialized local
variable, the ruby interpreter thinks of it as an attempt to invoke a
method of that name; hence the error message you see above.
Generally, the scope of a local variable is one of
proc{ ... }
loop{ ... }
def ... end
class ... end
module ... end
the entire program (unless one of the above applies)
In the next example, defined? is an operator which checks
whether an identifier is defined. It returns a description of the
identifier if it is defined, or nil otherwise. As you see,
bar's scope is local to the loop; when the loop exits, bar
is undefined.
Procedure objects that live in the same scope share whatever local
variables also belong to that scope. Here, the local variable
bar is shared by main and the procedure objects
p1 and p2:
Note that the "bar=0" at the beginning cannot be omitted;
that assignment ensures that the scope of bar will encompass
p1 and p2. Otherwise p1 and
p2 would each end up with its own local variable
bar, and calling p2 would have resulted in that
"undefined local variable or method" error.
A powerful feature of procedure objects follows from their ability
to be passed as arguments: shared local variables remain valid even
when they are passed out of the original scope.
Ruby is particularly smart about scope. It is evident in our
example that the contents variable is being shared between the
reader and writer. But we can also manufacture
multiple reader-writer pairs using box as defined above; each
pair shares a contents variable, and the pairs do not interfere
with each other.