“Set” class has meaning close to “Range” class. If we will define
Set#=== as
class Set
def ===( arg )
self.any?{|template| template === arg }
end
end
we will be able to write case/when code in haskell-like pattern-matching
style. here is an example of simple s-expression evaluator from my page:
Sexp = Set[Array, Numeric] # means - array or number
Boolean = Set[true, false]
Sexpbool = Set[Array] | Boolean # means - array or true or false
def evale(e) # function which will evaluate S-Expression
case e
when Numeric, Boolean then e
when [:-, Sexp] then - evale(e[1])
when [:-, Sexp, Sexp] then evale(e[1]) - evale(e[2])
when [:+, Sexp, Sexp] then evale(e[1]) + evale(e[2])
when [:*, Sexp, Sexp] then evale(e[1]) * evale(e[2])
when [:**, Sexp, Sexp] then evale(e[1]) ** evale(e[2])
when [:>, Sexp, Sexp] then evale(e[1]) > evale(e[2])
when [:if, Sexpbool, Sexp, Sexp] then evale(e[1]) ?evale(e[2]) :
evale(e[3])
when Object then fail(“something went wrong”)
end
end
def test_exp_eval
exp = [:*, [:-, 9, 2], [:+, 8, [:-, 2]]] # → (9 - 2) * (2 + 4) = 42
assert_equal 42, evale(exp)
exp2 = [:if, true, 10, 20]
assert_equal 10, evale(exp2)
exp3 = [:if, [:>, [:, 5, 5], 4000], 1, 2] # → 2 , because 4000 >
55
assert_equal 2, evale(exp3)
end
Dmitry V. wrote:
Hello,
We already have :=== operator defined in Module, Range, Regexp and Proc
which is great for case/when statement. For all other objects :=== mean
:==.
My suggestion is to extend Array with === method:
Original behaviour:
[1,2,3] === [1,2,3] #=> true
[1,2,3] === [1,2,4] #=> false
[1,2,3] === 2 #=> false
Adding code: – this code is similar to Array#== , but uses :=== for
comparing each element
class Array
def ===( arg )
arg.is_a?(Array) && self.size == arg.size && (0…size).all?{|i|
self[i] === arg[i] }
end
end
After adding code:
[1,2,3] === [1,2,3] #=> true
[1,2,3] === 2 #=> false
[1,2,Object] === [1,2,3] #=> true
[1,2,/^some/] === [1,2,“some string”] #=> true
[1,2,[Symbol, Array]] === [1,2,[:key, []]] #=> true <---- this
is an example of deep structure matching
You can see other examples at
http://github.com/dmitryelastic/dumb-patterns-matching/blob/master/patterns_matching.rb
and http://github.com/dmitryelastic/dumb-patterns-matching