From: "Chr. Rippel" Date: 2002-01-31T05:44:30+09:00 Subject: Re: (the diff) Re: TypeError verus NoMethodError > In message "(the diff) Re: TypeError verus NoMethodError" this did not make it to my news-server so I grabbed it from blade > > |I don't think of Fixnum and Symbols as singleton either however the > |fact is that disabling a method from a superclass is uniformly done > |undef_method raising a NoMethodError exception (which previously > |was a TypeError after all). > > The point is: when we agree Fixnums and Symbols are NOT singletons, > what is the rationale for removing dup and clone from them, instead of > raising TypeError? My rational would be, that it is generally good to have uniform error schemes. Form the (ab)user point of view, calling a undefined method or a method disabled raising a type Error basically has the same net effect - every calling attempt is flagged with an exception - since Ruby 1.7 has the NoMethodError exception why not use it then? I guess the main difference is that un defining a method is a more fool proof way disabling a method but it can be broken too - with something like class Module def rev_undef (sym) define_method (sym) {"dummy"} remove_method (sym) class_eval %{def #{sym}() super end} end end > Plus alternative point: It may be better to make singleton.rb to > raise TypeError for dup and clone. True ... > > |/OT It would be kind of neat to introduce singleton types for Fixnums > |and Symbols without compromising ``equal?" equality (see for example > |Bignum) . > > Could you tell me bit more about this? It would a bit more functional flavor to Ruby - for example we could write class Fixnum def fac() (self-1).fac end end def 0.fac() 1 end instead of class Fixnum def fac() return 1 if self == 0 (self-1).fac() end end The first form is faster and IMO more elegant than the latter. For example an old favorite of mine a RecInts toy class simulating the effect of these kind Fixnums easily beats the build in Fixnums in the Ackerman contest (its still not very fast). The disadvantage is that the singleton methods are never collected even if no particular symbol ``points'' at a given Fixnum or symbol - very similar to instance variables of "immutables" right now - for example 1.instance_eval { @var = "I'll never die" } The usefulness is however rather limited since ruby methods are ``only'' strongly typed on the receiver side and fancy multi-types(classes) etc. are nowhere inside, still it would be kind of cute to be able to write one variable recursive functions in a more functional style. > OK, I will examine, and merge them Thanks for merging it .. /Christoph ---- # RecInts simulating Fixnums with singletons ... class RecInts < Numeric class << self private :new,:allocate end attr_reader :succ,:pred,:to_i class << Null = new def + r; r end def - r; -r end def * r; self end def zero?; true end def positive?; false end def <=>(r) return -1 if r.is_a?(Plus) return 0 if r == self return 1 end end Null.instance_eval { @to_i = 0 } class Plus < self @max = Null class << self SUCC = proc {|| @succ = Plus.succ} # initialize creation class << Null define_method (:succ,SUCC) end def succ class << @max remove_method(:succ) end class << @max = new(@max) define_method (:succ,SUCC) end @max end end def initialize(prev_max) @pred = prev_max @to_i = prev_max.to_i + 1 end def to_i; @pred.to_i.succ end def positive?; true end def -@; (-@pred).pred end def + r; @pred + r.succ end def - r; @pred - (r.pred) end def * r; @pred*r + r end def <=> r return 1 unless r.is_a? Plus return @pred <=> r.pred end end class Minus < self @min = Null class << self PRED = proc {|| @pred = Minus.pred } class << Null define_method (:pred,PRED) end def pred class << @min remove_method(:pred) end class << @min = new(@min) define_method (:pred,PRED) end @min end end def initialize(prev_min) @succ = prev_min @to_i = prev_min.to_i - 1 end def to_i; @succ.to_i.pred end def positive?; false end def -@; (-@succ).succ end def + r; @succ + r.pred end def - r; @succ - r.succ end def * r; @succ*r - r end def <=> r return -1 unless r.is_a? Minus return @succ <=> r.succ end end def (Null.succ).* r; r end def (Null.pred).* r; -r end def to_s; to_i.to_s end alias inspect to_s def zero?; false end def to_s; to_i.to_s end def +@; self end def coerce(r) return r,to_i end end class RecInts def fib @pred.fib + @pred.pred.fib end One = Null.succ def ack(m) return pred.ack(One) if m.zero? return pred.ack(ack(m.pred)) end end class Fixnum def pred; self -1 end def to_rec if 0 < self res = RecInts::Null times {res = res.succ} res elsif self < 0 res = RecInts::Null (-self).times {res = res.pred} res else RecInts::Null end end end def (0.to_rec).fib; 0 end def (1.to_rec).fib; 1 end def (0.to_rec).ack(m); m.succ end p (2.to_rec * (-3.to_rec)).type p (2.to_rec * (-3.to_rec)) + (4.to_rec)* 50.to_rec p 2 <=> 3 p 3.to_rec.ack(4.to_rec) p 29.to_rec.fib