while
, until
, and for
are control structures and
the scope is shared with the outside of these structures.
loop
is a method and the appended block introduces a new scope.
Ruby
interpreter first reads in a script and analyzes it into a
parsed tree. If parsing goes well according to the syntax, the parsed
tree is interpreted to get the desired result.
for i in 1..2
if i == 2
print a
else
a = 1
end
end
Putting this script into a file named test.rb
, we get
test.rb:3: undefined local variable or method `a' for
#<Object:0x40101f4c> (NameError)
from test.rb:1:in `each'
from test.rb:1
When i
is 1, there occurs no error, and when i
becomes
2, an error occurs. In the first phase of syntax analysis, the
interpreter does not know that print a
appears after a is
assigned 1, and in the statement print a
the interpreter
does not know the local variable a
. When executed, it
searches for a method named a
but fails and an error is
reported.
a = 1 if false; print a
# ->nil
You are recommended to put an assignment statement like a = nil
before accessing a local variable not to be bothered by such behaviour of
local variables. There is an additional goodie of speeding up the
access time to local variables if defined outside a block.
::
operator, designating the class/module name on the left
hand side.
*
prepended to an argument?
def foo(*all)
for e in all
print e, " "
end
end
foo(1, 2, 3)
# -> 1 2 3
In a method call context *
denotes to expand an array to pass
the elements as arguments.
a = [1, 2, 3]
foo(*a)
You can prepend *
to the last argument of
when
clause of case
structure.
x, *y = [7, 8, 9]
and the result is x = 7
, y = [8, 9]
.
x
is 7.
x, = [7, 8, 9]
Next returns x = [7, 8, 9]
.
x = [7, 8, 9]
&
prepended to an argument?
||
.
These arguments are local variables and, when an argument is already
used outside the block, the scope is shared.
A = a = b = "abc"; b << "d"; print a, " ", A
# ->abcd abcd
Assignment to a variable or a constant is used to refer later the
object assigned to that variable or constant. The assigned
is not the object itself but its reference. A variable can contain
another reference later but the reference contained by a constant
will never be changed.