一本书说,即使程序中的其他位置存在另一个具有相同名称的变量,您也可以拥有一个范围仅限于块的变量。你可以在垂直管道内的这个块变量之前使用;
来完成它。
但是我在下面有和没有块变量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
仍受到保护,不会发生变化。
我错了吗?这个特定的代码片段可以有相同的结果,但从更广泛的角度看,东西真的不同,对吗?
答案 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参数变量的赋值
记住两件事:
块参数变量隐藏具有相同名称的外部变量(Ruby 1.8.7除外)。
'分号变量'隐藏具有相同名称的外部变量。