Prev | Contents | Next

| Ruby user's guide | Local variables |

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> foo
    ERR: (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.

    ruby> foo = 44; print foo, "\n"; defined? foo
    44
       "local-variable"
    ruby> loop{bar=45; print bar, "\n"; break}; defined? bar
    45
       nil

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`:

    ruby> bar=0
       0
    ruby> p1 = proc{|n| bar=n}
       #<Proc:0x8deb0>
    ruby> p2 = proc{bar}
       #<Proc:0x8dce8>
    ruby> p1.call(5)
       5
    ruby> bar
       5
    ruby> p2.call
       5

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> def box
        |   contents = 15
        |   get = proc{contents}
        |   set = proc{|n| contents = n}
        |   return get, set
        | end
       nil
    ruby> reader, writer = box
       [#<Proc:0x40170fc0>, #<Proc:0x40170fac>]
    ruby> reader.call
       15
    ruby> writer.call(2)
       2
    ruby> reader.call
       2

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.

    ruby> reader_1, writer_1 = box
       [#<Proc:0x40172820>, #<Proc:0x4017280c>]
    ruby> reader_2, writer_2 = box
       [#<Proc:0x40172668>, #<Proc:0x40172654>]
    ruby> writer_1.call(99)
       99
    ruby> reader_1.call
       99
    ruby> reader_2.call
       15

Prev | Contents | Next