【问题标题】:Recursive lambdas in RubyRuby 中的递归 lambda
【发布时间】:2011-10-26 15:09:33
【问题描述】:

我有以下代码可以正确生成大小为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>'

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

【问题讨论】:

  • 感谢戴夫的编辑!永远无法完全正确地拼写 lambdas……
  • 你应该为 Tree 类发布一些最少的代码,这样我们就可以轻松地测试这个函数的新版本。
  • @DavidGrayson 我已按要求发布了更多 Tree 类(虽然不是全部,但如果我的最小化有任何错误,请告诉我)。

标签: ruby recursion lambda


【解决方案1】:

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

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

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

【讨论】:

  • 我发誓我已经改变了那个(至少在某些时候我可能这样做了,但其他一些事情都错了)。此外,这指出了第 66 行我应该使用括号而不是大括号。谢谢!
猜你喜欢
  • 2010-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多