Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ruby-on-rails-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 覆盖#每个;我可以通过#map#select等传递参数吗?_Ruby_Enumerable - Fatal编程技术网

Ruby 覆盖#每个;我可以通过#map#select等传递参数吗?

Ruby 覆盖#每个;我可以通过#map#select等传递参数吗?,ruby,enumerable,Ruby,Enumerable,我已经编写了自己的树类,其中包括可枚举树然后提供一个#每个函数。因此,它能够自动获取所有可枚举的函数,如#map,#select,#find,等等。到目前为止,这些都在我的代码中起作用 问题出在这里。当我为我的树编写#each时,我给了#each一个参数,它是要使用的树遍历算法的名称,例如:pre_order或:width\u first。但是现在当我调用#map或#inject或#any?等时,它只能使用默认的遍历算法。是否有任何方法可以将此参数传递给其他可枚举函数?以下是我的标准 我需要能

我已经编写了自己的
类,其中包括
可枚举
<代码>树然后提供一个
#每个
函数。因此,它能够自动获取所有可枚举的
函数,如
#map
#select
#find
,等等。到目前为止,这些都在我的代码中起作用

问题出在这里。当我为我的
编写
#each
时,我给了
#each
一个参数,它是要使用的树遍历算法的名称,例如
:pre_order
:width\u first
。但是现在当我调用
#map
#inject
#any?
等时,它只能使用默认的遍历算法。是否有任何方法可以将此参数传递给其他
可枚举
函数?以下是我的标准

  • 我需要能够对任何
    可枚举
    函数使用任何遍历算法。这一点非常重要,因为对于不同的算法,树可能具有非常不同的性能
  • 我不想重写每个
    可枚举
    函数来将此参数传递给
    #每个
    ;这违背了模块的目的
这里是我的代码的缩写版本

class Tree
  include Enumerable
  ...

  # Overwrite #each, and give it the algorithm argument.
  def each(algorithm = :pre_order, &block)
    if TRAVERSAL_ALGORITHMS.include? algorithm
      self.send(algorithm, &block)
    else
      self.method_missing(algorithm)
    end
  end

  def pre_order(&block)
    yield self
    self.branches.each do |branch|
      branch.pre_order(&block)
    end
  end

  def post_order(&block)
    ...
  end

  def breadth_first(&block)
    ...
  end

end
我想称之为这样的事情

tree.find(13, :breadth_first)
tree.any?(:post_order) do |node|
  node.root >= 10
end
class Tree
  include Enumerable
  attr_accessor :traversal_algorithm

  def initialize(...)
    @traversal_algorithm = :pre_order
    ...
  end

  ...

  def each(&block)
    if TRAVERSAL_ALGORITHMS.include? @algorithm
      self.send(@algorithm, &block)
    else
      self.method_missing(@algorithm)
    end
  end

end
tree.traversal_algorithm = :breadth_first
tree.find(13)

tree.traversal_algorithm = :post_order
tree.any? do |node|
  node.root >= 10
end

可能的答案:设置要使用的算法的实例变量。然后代码将如下所示

tree.find(13, :breadth_first)
tree.any?(:post_order) do |node|
  node.root >= 10
end
class Tree
  include Enumerable
  attr_accessor :traversal_algorithm

  def initialize(...)
    @traversal_algorithm = :pre_order
    ...
  end

  ...

  def each(&block)
    if TRAVERSAL_ALGORITHMS.include? @algorithm
      self.send(@algorithm, &block)
    else
      self.method_missing(@algorithm)
    end
  end

end
tree.traversal_algorithm = :breadth_first
tree.find(13)

tree.traversal_algorithm = :post_order
tree.any? do |node|
  node.root >= 10
end
算法设置如下:

tree.find(13, :breadth_first)
tree.any?(:post_order) do |node|
  node.root >= 10
end
class Tree
  include Enumerable
  attr_accessor :traversal_algorithm

  def initialize(...)
    @traversal_algorithm = :pre_order
    ...
  end

  ...

  def each(&block)
    if TRAVERSAL_ALGORITHMS.include? @algorithm
      self.send(@algorithm, &block)
    else
      self.method_missing(@algorithm)
    end
  end

end
tree.traversal_algorithm = :breadth_first
tree.find(13)

tree.traversal_algorithm = :post_order
tree.any? do |node|
  node.root >= 10
end

这似乎是个很糟糕的主意。

我会按照Charlie的建议使用代理对象:

class Tree
  class PreOrderEnumerator
    include Enumerable

    attr_reader :tree

    def initialize(tree)
      @tree = tree
    end

    def each(&block)
      yield tree
      tree.branches.each do |branch|
        branch.pre_order(&block)
      end
    end
  end

  def pre_order
    PreOrderEnumerator.new(self)
  end
end
然后您可以这样使用:

tree.pre_order.any? {|node| node.root > 10 }
我真傻

#enum_for
的方法给了我这里所有的力量。我可以实现Charlie的语法

tree.breadth_first.find(13)
通过增加常规线路

return self.enum_for(__method__) unless block_given?

在我的每个遍历方法中。
树.width_first
将返回一个
枚举器
,该枚举器根据广度优先算法进行枚举;任何调用的将在内部使用该枚举的
Enumerable
方法。

如果您没有向每个方法传递参数,而是为每个算法返回原始树的可枚举包装的算法方法会怎么样?例如,
tree.width\u first.find(13)
或者目标是作为参数实现的?这是个好主意。你能把它写下来作为一个答案吗?如果你把问题的这一部分写下来,比如“我已经想到了这个问题,但它看起来很糟糕”,而不是把它作为你问题的答案贴出来,那就更有意义了。您可以编辑您的问题并删除此答案,仍然可以这样做。哈-完全忘记了enum_for。