局部变量

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:

不同于全局变量实例变量局部变量初始化之前并没有默认的nil值。

  1. ruby> $foo
  2. nil
  3. ruby> @foo
  4. nil
  5. ruby> foo
  6. 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 cannot be sure whether you are referencing a bogus variable; you might, for example, have misspelled a method name. Hence the rather nonspecific error message you see above.

如果你引用一个未初始化的局部变量Ruby解释器无法确定你是否引用了一个伪变量。例如,你可能会拼错一个方法名。因此,您可以看到上面所看到的非特定的错误消息。

Generally, the scope of a local variable is one of

一般来说,局部变量的范围是

  1. proc{ … }

  2. loop{ … }

  3. def … end
  4. class … end
  5. module … end
  6. 整个脚本 (除了上述情况之外)

In the next example, defined? is an operator which checks whether an identifier is defined.

接下来的示例中,defined?操作符用来检测标识符是否定义。

It returns a description of the identifier if it is defined, or nil otherwise.

如果标识符定义了,它将返回标识符,否则返回nil

As you see, bar’s scope is local to the loop; when the loop exits, bar is undefined.

如你所见,bar的作用域是loop,但loop退出,bar便成了未定义的。

  1. ruby> foo = 44; puts foo; defined?(foo)
  2. 44
  3. "local-variable"
  4. ruby> loop{bar=45; puts bar; break}; defined?(bar)
  5. 45
  6. 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:

在相同范围内的过程对象共享也属于该范围的任何局部变量。此处,局部变量barmain以及过程对象p1p2所共享。

  1. ruby> bar=nil
  2. nil
  3. ruby> p1 = proc{|n| bar=n}
  4. #<Proc:0x8deb0>
  5. ruby> p2 = proc{bar}
  6. #<Proc:0x8dce8>
  7. ruby> p1.call(5)
  8. 5
  9. ruby> bar
  10. 5
  11. ruby> p2.call
  12. 5

Note that the “bar=nil” at the beginning cannot be omitted; it ensures that the scope of bar will encompass p1 and p2.

注意最开始的bar=nil不能省略,它确保了bar的范围将包括p1p2

Otherwise p1 and p2 would each end up with its own local variable bar, and calling p2 would have resulted in an “undefined local variable or method” error.

否则,p1p2将各自使用其局部变量bar,而调用p2将导致”undefined local variable or method“错误。

We could have said bar=0 instead, but using nil is a courtesy to others who will read your code later.

我们也可以使用bar=0,但是使用nil显得对阅读你代码的人更友好。

It indicates fairly clearly that you are only establishing scope, because the value being assigned is not intended to be meaningful.

它很清楚地表明你只是在建立作用域,因为被分配的值并不是有意义的。

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.

过程对象的一个强大功能来自它们可以作为参数被传递的能力:即使在最初的作用域之外,共享的局部变量仍然有效。

  1. ruby> def box
  2. contents = nil
  3. get = proc{contents}
  4. set = proc{|n| contents = n}
  5. return get, set
  6. end
  7. nil
  8. ruby> reader, writer = box
  9. [#<Proc:0x40170fc0>, #<Proc:0x40170fac>]
  10. ruby> reader.call
  11. nil
  12. ruby> writer.call(2)
  13. 2
  14. ruby> reader.call
  15. 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.

Ruby在作用域方面特别聪明。在我们的示例中很明显,变量contents是在readerwriter之间共享的。

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.

但是,我们也可以使用如上所定义的box来制造多个reader-writer对。

  1. ruby> reader_1, writer_1 = box
  2. [#<Proc:0x40172820>, #<Proc:0x4017280c>]
  3. ruby> reader_2, writer_2 = box
  4. [#<Proc:0x40172668>, #<Proc:0x40172654>]
  5. ruby> writer_1.call(99)
  6. 99
  7. ruby> reader_1.call
  8. 99
  9. ruby> reader_2.call # nothing is in this box yet
  10. nil

This kind of programming could be considered a perverse little object-oriented framework.

这种编程可以被认为是一个不合理的面向对象的框架。

The box method acts something like a class, with get and set serving as methods (except those aren’t really the method names, which could vary with each box instance) and contents being the lone instance variable.

box方法的作用类似于一个类,getset作为方法(但是它们并不是真正的方法名,它们可能会随着每个box实例的不同而不同),而contents是唯一的实例变量。

Of course, using ruby’s legitimate class framework leads to much more readable code.

当然,使用Ruby的合法类框架会得到可读性更强的代码。

上一章 实例变量
下一章 类常量