ruby block问题
PHP中文网
PHP中文网 2017-04-24 09:11:17
0
2
611

做七周七语言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

PHP中文网
PHP中文网

认证高级PHP讲师

reply all(2)
小葫芦

Correction

The program given by the questioner has a slight error. The corrected version is as follows. Pay attention to the order of the two lines: visit &blockprint ' ' * n

#!/usr/bin/ruby
class Tree
  attr_accessor :node_name, :children

  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 = 0, &block)
    print '  ' * n
    visit &block
    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' => {
    'dad' => { 'child 1' => {},'child 2' => {} },
    'uncle' => { 'child 3' => {},'child 4' => {} }
  }
})

ruby_tree.visit_all { |node| puts "-#{node.node_name}" }
Answer

Report line 15 according to the topic

    children.each { |c| c.visit_all(n+1) { |node| puts "-#{node.node_name}" } }
changed to

    children.each { |c| c.visit_all(n+1, &block) }
After , the program output results are consistent.

Conclusion

The problem does not exist.

Ty80

Each line of code has a context when it is executed, and some variables that can be accessed by this line of code are stored in the context. Blocks can access the context when they are defined. In your example, this block is defined globally, so you can access global variables. However, the only global variables here are ruby_tree (there are also built-in ones in some languages, which I won’t mention). However, there is no block variable, so it cannot be accessed within the block, and errors similar to the existence of invariants or methods will be reported.

Another interpretation, if we use a similar example from the ancient C language, the variable block is an actual parameter, and you have to use the formal parameter node variable to treat it in the block.

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template