Ruby中的递归lambdas

时间:2011-10-26 02:49:13

标签: ruby recursion lambda

我有以下代码正确生成所有可能的大小为num的树:

class Tree
  attr_accessor :left, :right

  def initialize left = nil, right = nil
    @left = left
    @right = right
  end

  # Don't ever specify any arguments, it will make me very angry.
  # Tilt your head 90 degrees to the side to see the tree when viewing.
  def print level = 0
    @right.pretty_print(level + 1) if @right
    puts ('  ' * level) + to_s
    @left.pretty_print(level + 1) if @left
  end

  def self.generate num
    trees = []
    generate_subtrees(num) { |tree| trees << tree } if num > 0
    trees
  end

  private

  def self.generate_subtrees num, &block
    if num == 0
      yield nil
    else
      (1..num).each do |root_position|
        generate_subtrees(root_position - 1) do |left|
          generate_subtrees(num - root_position) do |right|
            yield Tree.new nil, left, right
          end
        end
      end
    end
  end
end

我正在尝试(为了它)将“压缩”成一个方法,利用lambda递归。我目前的尝试(几次迭代)如下:

def self.generate num
  trees = []

  gen = ->(num, &block) do
    if num == 0
      yield nil                                       # L61
    else
      (1..num).each do |root_position|                # L63
        gen.call(root_position - 1) do |left|         # L64
          gen.call(num - root_position) do |right|
            block.call { Tree.new nil, left, right }
          end
        end
      end
    end
  end

  gen.call(num) { |tree| trees << tree }              # L73

  trees
end

这导致错误(上面提到的参考线):

LocalJumpError: no block given (yield)
    from tree.rb:61:in `block in generate'
    from tree.rb:64:in `call'
    from tree.rb:64:in `block (2 levels) in generate'
    from tree.rb:63:in `each'
    from tree.rb:63:in `block in generate'
    from tree.rb:73:in `call'
    from tree.rb:73:in `generate'
    from (irb):4
    from /Users/amarshall/.rbenv/versions/1.9.2-p290/bin/irb:12:in `<main>'

我做错了什么?这个主要是学术问题的替代解决方案也是受欢迎的。

1 个答案:

答案 0 :(得分:3)

yield关键字在lambda中不起作用。另一种方法是使用&block,就像你在第64和65行所做的那样:

gen = ->(num, &block) do
if num == 0
  block.call(nil)
else
  # ...
end

gen.call(num) { |tree| trees << tree }