From: Dmitry Vazhov on 18 Dec 2009 01:51 "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 > 5**5 assert_equal 2, evale(exp3) end Dmitry Vazhov 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 -- Posted via http://www.ruby-forum.com/.
From: Dmitry Vazhov on 18 Dec 2009 04:28 So, my question is: Do you agree that Array#=== can be useful for us? My opinion is that it can be in ruby std library along with Proc#===(which is already in ruby 1.9 -- http://www.aimred.com/news/developers/2008/08/14/unlocking_the_power_of_case_equality_proc/) -- Posted via http://www.ruby-forum.com/.
From: Benoit Daloze on 18 Dec 2009 05:09 [Note: parts of this message were removed to make it a legal post.] Hi, It doesn't look too usefull to me like that. (I mean using classes to compare). For this purpose I wrote something like: # Analyse arguments given to a method(*args) # # Exemple: # def m(*args) # case args # when ARGS[Complex] # m(Complex.new(1,1)) # when ARGS[Integer, Boolean] # m(2, true) # when ARGS[[Numeric, Float], String] # m([1, 3.14], "Hello World!") # when ARGS[[[Integer, Integer],[Float, Rational ]]] # m( [[1 , 2 ],[3.0 , Rational(1,2)]]) # end # end module Boolean; end class FalseClass; include Boolean; end class TrueClass; include Boolean; end class ARGS def initialize(*constraints) @constraints = constraints end def ARGS.[](*constraints) ARGS.new(*constraints) end def match?(args) return false unless @constraints.length == args.length @constraints.each_with_index { |constraint, i| case constraint when Module unless args[i].is_a?(constraint) return false end when Array unless args[i].is_a?(Array) && ARGS[*constraint].match?(args[i]) return false end end } true end def ===(args) match?(args) end end ------- Some mails ago, I also thought Array#=== implemented a OR-related test like in: case 2 when -1,1,2 ... end But that seems to be more a feature of the "block" case. So, I think this trick can be useful in special "cases", but I don't see enough interest to do that for the Ruby core. Any exemples more attractive ? 2009/12/18 Dmitry Vazhov <dmitryelastic(a)gmail.com> > So, my question is: Do you agree that Array#=== can be useful for us? > > My opinion is that it can be in ruby std library along with > Proc#===(which is already in ruby 1.9 -- > > http://www.aimred.com/news/developers/2008/08/14/unlocking_the_power_of_case_equality_proc/ > ) > > -- > Posted via http://www.ruby-forum.com/. > >
From: Caleb Clausen on 18 Dec 2009 18:16 > Dmitry Vazhov 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: I long ago did something similar, but much more extensive; I created a large pattern-matching language/library for ruby data structures called Reg. Instead of changing the existing Array#===, I created a new class, Reg::Array, which has the functionality you want. A Reg::Array can be constructed by enclosing the patterns of interest between +[ and ]. You should have a look at Reg; you can install the gem: gem install reg or take a look at the github project, which contains newer (and buggier) code: http://github.com/coatl/reg On 12/17/09, Dmitry Vazhov <dmitryelastic(a)gmail.com> wrote: > "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 Personally, I would rather see Set#=== be an alias for include?. The alternation semantics that you want here are provided in Reg by Reg::Or, which is usually created by gluing together individual matchers that you want with the | operator. So it'd look like: Sexp = Array|Numeric instead of: Sexp = Set[Array, Numeric]
From: Tony Arcieri on 19 Dec 2009 02:30 [Note: parts of this message were removed to make it a legal post.] I would absolutely love if Array recursively performed #=== on its arguments. AFAICT Array#=== is practically identical to Array#== On Fri, Dec 18, 2009 at 4:16 PM, Caleb Clausen <vikkous(a)gmail.com> wrote: > > Dmitry Vazhov 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: > > I long ago did something similar, but much more extensive; I created a > large pattern-matching language/library for ruby data structures > called Reg. Instead of changing the existing Array#===, I created a > new class, Reg::Array, which has the functionality you want. A > Reg::Array can be constructed by enclosing the patterns of interest > between +[ and ]. > > You should have a look at Reg; you can install the gem: > gem install reg > or take a look at the github project, which contains newer (and buggier) > code: > http://github.com/coatl/reg > > > On 12/17/09, Dmitry Vazhov <dmitryelastic(a)gmail.com> wrote: > > "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 > > Personally, I would rather see Set#=== be an alias for include?. The > alternation semantics that you want here are provided in Reg by > Reg::Or, which is usually created by gluing together individual > matchers that you want with the | operator. So it'd look like: > Sexp = Array|Numeric > instead of: > Sexp = Set[Array, Numeric] > > -- Tony Arcieri Medioh! A Kudelski Brand
|
Next
|
Last
Pages: 1 2 3 Prev: how to alias keywords? Next: problem requiring gems under 1.9.1 mingw |