使用仅阻止范围阻止参数

时间:2014-09-11 02:00:27

标签: ruby

一本书说,即使程序中的其他位置存在另一个具有相同名称的变量,您也可以拥有一个范围仅限于块的变量。你可以在垂直管道内的这个块变量之前使用;来完成它。

但是我在下面有和没有块变量x的情况下得到相同的结果:

def block_local_variable
    x = "Original x!"
    3.times do |i;x|
        x = i
        puts "x in the block is now #{x}"
    end
    puts "x after the block ended is #{x}"
end
block_local_variable

def block_local_variable
    x = "Original x!"
    3.times do |x|
        puts "x in the block is now #{x}"
    end
    puts "x after the block ended is #{x}"
end
block_local_variable

据我所知,没有区别。

x in the block is now 0
x in the block is now 1
x in the block is now 2
x after the block ended is Original x!

原始x仍受到保护,不会发生变化。

我错了吗?这个特定的代码片段可以有相同的结果,但从更广泛的角度看,东西真的不同,对吗?

1 个答案:

答案 0 :(得分:1)

这是一种更简单的方法来解释您的图书试图告诉您的内容。

1)块可以看到周围范围内的所有变量 - 在创建块时。这是一个例子:

y = 'hello world' #<-+  <--- Everything outside the block is part of the surrounding scope
                  #  |
func = lambda do  #<-|---- Block created now!
  puts y   #---------+
end

func.call   #=>hello world

以下没有必要知道你的问题,但在任何情况下都很好知道:一个块无法看到周围范围内的变量 - 在执行时。这是一个例子:

y = 'hello world'# <-+
                 #   |
func = lambda do # <-|------Block created now!
  puts y  #----------+
end

def do_stuff(f)  #<--- The def keyword creates a new scope.
#----------------------+ <-- The scope surrounding the block.
  y = 10    #          |
  f.call  #=>puts y   <---Block executed now!
#----------------------+
end

do_stuff(func)  #=>hello world

2)在一个区块内,您可以更改周围范围内的变量:

y = 'hello world'# <-----+
                 #       |
func = lambda do #       | 
  y = 'goodbye'  #-------+
end

func.call
puts y   #=>goodbye

3)现在,如果您想在块中使用名为“y”的变量,但是您不想更改已命名为“y”的块之外的变量,该怎么办?换句话说,您不希望搜索所有代码以查看是否已存在可能无意中更改的名为“y”的现有变量,这可能会导致错误?

y = 'hello world'

func = lambda do |;y|   #New y variable created, which 'hides' the outer y.
  y = 'goodbye'     #Assignment to the 'local' (or block) y.
end  #Block y is destroyed--'unhiding' the outer y.

func.call
puts y  #=>hello world

请注意,分号后面列出的变量不是参数变量 - func需要0个参数。分号只是告诉ruby创建分号后指定的变量。

如果将这些规则应用于您的示例,您应该意识到为了测试分号是如何工作的,在两个示例中的块内部,您必须分配给存在于块外部的变量。你的第二个例子不这样做。此外,第二个示例指定块参数变量x。块参数变量ALWAYS隐藏了一个具有相同名称的外部变量(好吧,不在ruby 1.8.7中),所以你通过这样做立即搞砸了这个例子:在块内部,对x的赋值将是对x参数变量的赋值

记住两件事:

  1. 块参数变量隐藏具有相同名称的外部变量(Ruby 1.8.7除外)。

  2. '分号变量'隐藏具有相同名称的外部变量。