-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcoercible.rb
More file actions
88 lines (73 loc) · 1.7 KB
/
coercible.rb
File metadata and controls
88 lines (73 loc) · 1.7 KB
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
require 'active_support/concern'
module Coercible
extend ActiveSupport::Concern
def coerce(a)
return Wrapper.new(a), self
end
PREDICATES = {
:divides? => :divides?,
:associated? => :associated?,
}
ARITHMETIC = {
:** => :pow,
:* => :mul,
:/ => :div,
:divmod => :divmod,
:gcd => :gcd,
:lcm => :lcm,
:% => :mod,
:+ => :add,
:- => :sub,
:>> => :shr,
:<< => :shl,
}
LOGIC = {
:& => :and,
:| => :or,
:^ => :xor,
}
OPS = {**PREDICATES, **ARITHMETIC, **LOGIC}
OPS.each do |op, meth|
define_method op do |b|
self.class.__send__(meth, self, b)
end
define_method :"__r#{meth}" do |a|
self.class.__send__(meth, a, self)
end
end
class Wrapper
include Comparable
def initialize(value)
@value = value
end
def ==(b)
b == @value
end
def eql?(b)
b.eql?(@value)
end
def <=>(b)
-(b <=> @value)
end
OPS.each do |op, meth|
define_method op do |b|
b.__send__(:"__r#{meth}", @value)
end
end
end
module Macros
def right(op, &block)
op = op.to_sym
meth = OPS[op] or raise ArgumentError, "Unknown binary operator '#{op}'"
define_method(:"__r#{meth}", &block)
end
def commutative(*ops)
ops.each do |op|
right op do |a|
__send__(op, a)
end
end
end
end
ClassMethods = Macros
end