Ruby 具有仅块作用域的块参数

Ruby 具有仅块作用域的块参数,ruby,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

一本书说,即使程序中的其他地方存在另一个同名的变量,也可以有一个作用域仅限于一个块的变量。您可以使用
在垂直管道内此块变量之前

但我得到了相同的结果,无论是否使用块变量
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

就我所知,没有区别

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) 在创建块时,块可以看到周围范围中的所有变量。以下是一个例子:

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
请注意,分号后面列出的变量不是参数变量——func接受0个参数。分号只是告诉ruby创建分号后面指定的变量

如果您将这些规则应用到示例中,您应该意识到,为了测试分号是如何工作的,在这两个示例中的块内部,您必须指定一个存在于块外部的变量。你的第二个例子没有做到这一点。此外,第二个示例指定了块参数变量x。一个块参数变量总是隐藏一个同名的外部变量(在ruby 1.8.7中不是这样),所以你马上就搞错了这个例子:在块内部,对x的赋值就是对x参数变量的赋值

记住两件事:

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

  • “分号变量”隐藏具有相同名称的外部变量

  • 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
    
    y = 'hello world'# <-----+
                     #       |
    func = lambda do #       | 
      y = 'goodbye'  #-------+
    end
    
    func.call
    puts y   #=>goodbye
    
    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