Home  >  Q&A  >  body text

ruby block问题

做七周七语言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中文网2710 days ago545

reply all(2)I'll reply

  • 高洛峰

    高洛峰2017-04-24 09:13:17

    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.

    reply
    0
  • PHP中文网

    PHP中文网2017-04-24 09:13:17

    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.

    reply
    0
  • Cancelreply