-
Notifications
You must be signed in to change notification settings - Fork 55
/
Copy pathrecursion_guard.rb
49 lines (40 loc) · 1.14 KB
/
recursion_guard.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
require 'set'
module SuperDiff
module RecursionGuard
RECURSION_GUARD_KEY = "super_diff_recursion_guard_key".freeze
PLACEHOLDER = "∙∙∙".freeze
def self.guarding_recursion_of(*objects, &block)
already_seen_objects, first_seen_objects = objects.partition do |object|
!SuperDiff.primitive?(object) && already_seen?(object)
end
first_seen_objects.each do |object|
already_seen_object_ids.add(object.object_id)
end
result =
if block.arity > 0
block.call(already_seen_objects.any?)
else
block.call
end
first_seen_objects.each do |object|
already_seen_object_ids.delete(object.object_id)
end
result
end
def self.substituting_recursion_of(*objects)
guarding_recursion_of(*objects) do |already_seen|
if already_seen
PLACEHOLDER
else
yield
end
end
end
def self.already_seen?(object)
already_seen_object_ids.include?(object.object_id)
end
def self.already_seen_object_ids
Thread.current[RECURSION_GUARD_KEY] ||= Set.new
end
end
end