做七周七语言ruby第二天习题的时候要实现一个简单的Tree类,以下代码可以运行,但是把children.each {|c| c.visit_all(n+1) {|node| puts "-#{node.node_name}"}}
这行的{|node| puts "-#{node.node_name}"}改成&block
就跑不起来,请问是为什么?
#!/usr/bin/ruby
class Tree
attr_accessor :children,:node_name
def initialize(tree)
tree.each do |key,value|
@node_name = key
@children = value.map {|(key,value)| Tree.new(key => value)}
end
end
def visit_all(n,&block)
visit &block
print ' ' * n
children.each {|c| c.visit_all(n+1) {|node| puts "-#{node.node_name}"}}
end
def visit(&block)
block.call self
end
end
ruby_tree = Tree.new({
'grandpa' => {
'day' => {'child 1' => {},'child 2' => {}},'uncle' => {'child 3' => {},'child 4' => {}}
}
})
ruby_tree.visit_all(1) {|node| puts "-#{node.node_name}"}
ps: ruby环境是2.1.3
订正
题主给出的程序有点小错误,订正后如下,注意
visit &block
和print ' ' * n
两行的顺序:回答
将第15行按题主意思由
改为
后,程序输出结果是一致的。
结论
问题不存在。
每行代码执行的时候都有一个上下文,在上下文中存储着这行代码可以访问的一些变量。块可以访问定义时的上下文,在你的例子中这个块定义在全局,所以可以访问到全局变量,不过这里的全局变量只有ruby_tree(也有一些语言内置的就不说了)。但是没有block这个变量,所以在块内是不能访问的,会报类似不变量或方法存在的错误。
换一个解译,如果用远古的C语言类似的例子说的话,就是block这个变量是个实参,而你在块中要使用与其对待的形参node这个变量。