class M
class << self
def m *pat
pat.empty? ? @m || [] : @m = (new *pat)
end
alias [] m
def call b
@m || (@m.call b)
end
end
def initialize *pat
@pat = pat
end
def === rhs
@obj = rhs
to_a.all? { |k| rhs.respond_to? k } # can we go deeper?
end
def to_a
if Hash === @pat[-1]
*a, b = @pat
[*a, *b.keys]
else
@pat
end
end
def to_h
ret = {}
if Hash === @pat[-1]
@pat[-1].each { |k, v| ret[v] = @obj.send k }
end
ret
end
# def call b
# to_h.each { |k, v| b.local_variable_set k, v }
# self
# end
def call s
to_h.each { |k, v|
s.singleton_class.class_eval { attr_accessor k }
s.send :"#{k}=", v
}
self
end
end
def m(*a)
M[*a]
end
A = Struct.new :a
case A.new 42
when m(a: 'b')
m.(self)
p b
end