PATM: PATtern Matcher for Ruby
Usage
require 'patm'
# With case(simple but slow)
def match(obj)
p = Patm
_xs = Patm._xs
case obj
when m = Patm.match([:x, p._1, p._2])
[m._2, m._1]
when m = Patm.match([1, _xs&p._1])
m._1
end
end
match([1, 2, 3])
# => [2, 3]
match([:x, :y, :z])
# => [:z, :y]
match([])
# => nil
# With DSL
class A
extend ::Patm::DSL
define_matcher :match1 do|r|
p = Patm
r.on [:x, p._1, p._2] do|m|
[m._1, m._2]
end
end
define_matcher :match2 do|r|
r.on [:a, Patm._xs & Patm._1] do|m, _self|
_self.match1(m._1)
end
# ...
end
end
A.new.match1([:x, 1, 2])
# => [1, 2]
# With pre-built Rule
rule = Patm::Rule.new do|r|
p = Patm
_xs = Patm._xs
r.on [:x, p._1, p._2] do|m|
[m._2, m._1]
end
r.on [1, _xs&p._1] do|m|
m._1
end
end
rule.apply([1,2,3])
# => [2, 3]
rule.apply([:x, :y, :z])
# => [:z, :y]
rule.apply([])
# => nil
# With cached rules
class A
def initialize
@rules = Patm::RuleCache.new
end
def match1(obj)
@rules.match(:match1, obj) do|r|
p = Patm
r.on [:x, p._1, p._2] do|m|
[m._1, m._2]
end
end
end
def match2(obj)
@rules.match(:match2, obj) do|r|
# ...
end
end
end
Patterns
1
, :x
, String, ...
Normal pattern matches if pattern === value
is true.
Array
[1, 2, _xs]
matches [1, 2]
, [1, 2, 3]
, [1, 2, 3, 4]
, etc.
[1, _xs, 2]
matches [1, 2]
, [1, 10, 2]
, etc.
Note: More than one _xs
in same array is invalid.
Capture
_1
, _2
, etc matches any value, and capture the value as correspond match group.
Compose
_1&[_any, _any]
matches any two element array, and capture the array as _1.
Patm.or(1, 2)
matches 1 or 2.
Changes
1.0.0
- DSL
- Compile is enabled by default
- Change interface
0.1.0
- Faster matching with pattern compilation
- Fix StackOverflow bug for
[Patm.or()]
0.0.1
- Initial release