Assignment¶ ↑
In Ruby, assignment uses the =
(equals sign) character. This
example assigns the number five to the local variable v
:
v = 5
Assignment creates a local variable if the variable was not previously referenced.
Local Variable Names¶ ↑
A local variable name must start with a lowercase US-ASCII letter or a character with the eight bit set. Typically local variables are US-ASCII compatible since the keys to type them exist on all keyboards.
(Ruby programs must be written in a US-ASCII-compatible character set. In such character sets if the eight bit is set it indicates an extended character. Ruby allows local variables to contain such characters.)
A local variable name may contain letters, numbers, an _
(underscore or low line) or a character with the eighth bit set.
Local Variable Scope¶ ↑
Once a local variable name has been assigned-to all uses of the name for the rest of the scope are considered local variables.
Here is an example:
1.times do a = 1 puts "local variables in the block: #{local_variables.join ", "}" end puts "no local variables outside the block" if local_variables.empty?
This prints:
local variables in the block: a no local variables outside the block
Since the block creates a new scope, any local variables created inside it do not leak to the surrounding scope.
Variables defined in an outer scope appear inner scope:
a = 0 1.times do puts "local variables: #{local_variables.join ", "}" end
This prints:
local variables: a
You may isolate variables in a block from the outer scope by listing them
following a ;
in the block's arguments. See the
documentation for block local variables in the calling methods documentation for an
example.
See also Kernel#local_variables,
but note that a for
loop does not create a new scope like a
block does.
Local Variables and Methods¶ ↑
In Ruby local variable names and method names are nearly identical. If you have not assigned to one of these ambiguous names ruby will assume you wish to call a method. Once you have assigned to the name ruby will assume you wish to reference a local variable.
The local variable is created when the parser encounters the assignment, not when the assignment occurs:
a = 0 if false # does not assign to a p local_variables # prints [:a] p a # prints nil
The similarity between method and local variable names can lead to confusing code, for example:
def big_calculation 42 # pretend this takes a long time end big_calculation = big_calculation()
Now any reference to big_calculation
is considered a local
variable and will be cached. To call the method, use
self.big_calculation
.
You can force a method call by using empty argument parentheses as shown
above or by using an explicit receiver like self.
. Using an
explicit receiver may raise a NameError if
the method's visibility is not public.
Another commonly confusing case is when using a modifier if
:
p a if a = 0.zero?
Rather than printing “true” you receive a NameError, “undefined local variable or method
`a'”. Since ruby parses the bare a
left of the
if
first and has not yet seen an assignment to a
it assumes you wish to call a method. Ruby then sees the assignment to
a
and will assume you are referencing a local method.
The confusion comes from the out-of-order execution of the expression. First the local variable is assigned-to then you attempt to call a nonexistent method.
Instance Variables¶ ↑
Instance variables are shared across all methods for the same object.
An instance variable must start with a @
(“at” sign or
commercial at). Otherwise instance variable names follow the rules as
local variable names. Since the instance variable starts with an
@
the second character may be an upper-case letter.
Here is an example of instance variable usage:
class C def initialize(value) @instance_variable = value end def value @instance_variable end end object1 = C.new "some value" object2 = C.new "other value" p object1.value # prints "some value" p object2.value # prints "other value"
An uninitialized instance variable has a value of nil
. If you
run Ruby with warnings enabled, you will get a warning when accessing an
uninitialized instance variable.
The value
method has access to the value set by the
initialize
method, but only for the same object.
Class Variables¶ ↑
Class variables are shared between a class, its subclasses and its instances.
A class variable must start with a @@
(two “at” signs). The
rest of the name follows the same rules as instance variables.
Here is an example:
class A @@class_variable = 0 def value @@class_variable end def update @@class_variable = @@class_variable + 1 end end class B < A def update @@class_variable = @@class_variable + 2 end end a = A.new b = B.new puts "A value: #{a.value}" puts "B value: #{b.value}"
This prints:
A value: 0 B value: 0
Continuing with the same example, we can update using objects from either class and the value is shared:
puts "update A" a.update puts "A value: #{a.value}" puts "B value: #{b.value}" puts "update B" b.update puts "A value: #{a.value}" puts "B value: #{b.value}" puts "update A" a.update puts "A value: #{a.value}" puts "B value: #{b.value}"
This prints:
update A A value: 1 B value: 1 update B A value: 3 B value: 3 update A A value: 4 B value: 4
Accessing an uninitialized class variable will raise a NameError exception.
Note that classes have instance variables because classes are objects, so try not to confuse class and instance variables.
Global Variables¶ ↑
Global variables are accessible everywhere.
Global variables start with a $
(dollar sign). The rest of
the name follows the same rules as instance variables.
Here is an example:
$global = 0 class C puts "in a class: #{$global}" def my_method puts "in a method: #{$global}" $global = $global + 1 $other_global = 3 end end C.new.my_method puts "at top-level, $global: #{$global}, $other_global: #{$other_global}"
This prints:
in a class: 0 in a method: 0 at top-level, $global: 1, $other_global: 3
An uninitialized global variable has a value of nil
.
Ruby has some special globals that behave differently depending on context such as the regular expression match variables or that have a side-effect when assigned to. See the global variables documentation for details.
Assignment Methods¶ ↑
You can define methods that will behave like assignment, for example:
class C def value=(value) @value = value end end c = C.new c.value = 42
Using assignment methods allows your programs to look nicer. When assigning to an instance variable most people use Module#attr_accessor:
class C attr_accessor :value end
When using method assignment you must always have a receiver. If you do not have a receiver, Ruby assumes you are assigning to a local variable:
class C attr_accessor :value def my_method value = 42 puts "local_variables: #{local_variables.join ", "}" puts "@value: #{@value.inspect}" end end C.new.my_method
This prints:
local_variables: value @value: nil
To use the assignment method you must set the receiver:
class C attr_accessor :value def my_method self.value = 42 puts "local_variables: #{local_variables.join ", "}" puts "@value: #{@value.inspect}" end end C.new.my_method
This prints:
local_variables: @value: 42
Abbreviated Assignment¶ ↑
You can mix several of the operators and assignment. To add 1 to an object you can write:
a = 1 a += 2 p a # prints 3
This is equivalent to:
a = 1 a = a + 2 p a # prints 3
You can use the following operators this way: +
,
-
, *
, /
, %
,
**
, &
, |
, ^
,
<<
, >>
There are also ||=
and &&=
. The former
makes an assignment if the value was nil
or false
while the latter makes an assignment if the value was not nil
or false
.
Here is an example:
a ||= 0 a &&= 1 p a # prints 1
Note that these two operators behave more like a || a = 0
than
a = a || 0
.
Implicit Array Assignment¶ ↑
You can implicitly create an array by listing multiple values when assigning:
a = 1, 2, 3 p a # prints [1, 2, 3]
This implicitly creates an Array.
You can use *
or the “splat” operator or unpack an Array when
assigning. This is similar to multiple assignment:
a = *[1, 2, 3] p a # prints [1, 2, 3]
You can splat anywhere in the right-hand side of the assignment:
a = 1, *[2, 3] p a # prints [1, 2, 3]
Multiple Assignment¶ ↑
You can assign multiple values on the right-hand side to multiple variables:
a, b = 1, 2 p a: a, b: b # prints {:a=>1, :b=>2}
In the following sections any place “variable” is used an assignment method, instance, class or global will also work:
def value=(value) p assigned: value end self.value, $global = 1, 2 # prints {:assigned=>1} p $global # prints 2
You can use multiple assignment to swap two values in-place:
old_value = 1 new_value, old_value = old_value, 2 p new_value: new_value, old_value: old_value # prints {:new_value=>1, :old_value=>2}
If you have more values on the right hand side of the assignment than variables on the left hand side, the extra values are ignored:
a, b = 1, 2, 3 p a: a, b: b # prints {:a=>1, :b=>2}
You can use *
to gather extra values on the right-hand side of
the assignment.
a, *b = 1, 2, 3 p a: a, b: b # prints {:a=>1, :b=>[2, 3]}
The *
can appear anywhere on the left-hand side:
*a, b = 1, 2, 3 p a: a, b: b # prints {:a=>[1, 2], :b=>3}
But you may only use one *
in an assignment.
Array Decomposition¶ ↑
Like Array decomposition in method arguments you can decompose an Array during assignment using parenthesis:
(a, b) = [1, 2] p a: a, b: b # prints {:a=>1, :b=>2}
You can decompose an Array as part of a larger multiple assignment:
a, (b, c) = 1, [2, 3] p a: a, b: b, c: c # prints {:a=>1, :b=>2, :c=>3}
Since each decomposition is considered its own multiple assignment you can
use *
to gather arguments in the decomposition:
a, (b, *c), *d = 1, [2, 3, 4], 5, 6 p a: a, b: b, c: c, d: d # prints {:a=>1, :b=>2, :c=>[3, 4], :d=>[5, 6]}