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.