关于 ruby??:识别独特的块

Identify unique blocks

我有一个数组,我在不同的时间点不断向其中添加代码块。当特定事件发生时,迭代器会遍历此数组并一个接一个地产生块。

其中许多块是相同的,我想避免执行重复的块。

这是示例代码:

1
2
3
4
5
    @after_event_hooks = []

    def add_after_event_hook(&block)
      @after_event_hooks << block
    end

@after_event_hooks.uniq@after_event_hooks |= block 这样的东西不起作用。

有没有办法比较块或检查它们的唯一性?


无法检查块的唯一性,因为这意味着检查它们是否代表相同的功能,这是不可能的,并且已经在计算机科学中研究了很长时间。

您可能可以使用类似于"Ruby 块到字符串而不是执行"中讨论的函数,该函数接受块并返回块中代码的字符串表示,并比较输出您收到的字符串。

我不确定这是否足够快以值得比较它们,而不是多次执行它们。这也有一个缺点,您需要确保代码完全相同,即使一个具有不同名称的变量也会破坏它。


也许使用这样的东西:

1
2
3
4
5
6
7
8
9
10
11
class AfterEvents
  attr_reader :hooks

  def initialize
    @hooks = {}
  end

  def method_missing(hook_sym, &block)
    @hooks[hook_sym] = block
  end
end

这是一个示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
events = AfterEvents.new
events.foo { puts"Event Foo" }
events.bar { puts"Event Bar" }

# test
process = {:first => [:foo], :sec => [:bar], :all => [:foo, :bar]}

process.each { |event_sym, event_codes|
  puts"Processing event #{event_sym}"
  event_codes.each { |code| events.hooks[code].call }
}
# results:
# Processing event first
# Event Foo
# Processing event sec
# Event Bar
# Processing event all
# Event Foo
# Event Bar

正如@hakcho 所说,比较块并非易事。一个简单的解决方案可能是对命名挂钩的 API 请求,因此您可以比较名称:

1
2
3
4
5
6
7
8
9
@after_event_hooks = {}

def add_after_event_hook(name, &block)
  @after_event_hooks[name] = block
end

def after_event_hooks
  @after_event_hooks.values
end