Christoph
10/14/2003 7:35:00 AM
"Phil Tomson" wrote:
....
> Sorry. I did think you tried it before you posted and found it didn't
> work. My answer was basically that you can't do what you're asking
> because it involves reassigning self. And since Numeric's are immediate
> values you can't change them because it would involve reassigning to self.
I think the term ``immediate value'' is used when talking about instances of
the Fixnum, Symbol, FalseClass, TrueClass or NilClass - it is basically an
implementation issue.
Anyway the argument used, that you cannot possibly implement a ``postAdd''
method (btw. you want an instances NOT a class method) in a true to the
spirit object-oriented language like Ruby, is the statelessness of numbers.
Meaning, that
sending 3 the message of adding 4 to itself (and returning the
previous state)
doesn't makes a whole lot of sense, since this the new state, 7,
is not an altered state of ``3'', but really a whole new object
(the number 7).
You can make the same argument for Arrays, Hashes or Strings however this
would make Ruby prohibitively inefficient. In this context it is interesting
to
note, that Python sports stateless strings and that Python's method
arguments
are a special kind of stateless Arrays (Tuples).
Also note that Ruby's ``stateless numbers'' really hinders Ruby's
algorithmic
efficiency when dealing with huge Bignums...
> I don't think it's too simple a question or too weird: I've had it myself.
Ditto ...
Just for the heck of it - Here is a Numeric Wrapper class whose
instances probably behave more in tune with your preconceptions ...
----
class Numeric
def rep
self
end
end
class Wrapper
include Comparable
attr_reader :rep
alias inspect rep
alias to_s rep
def initialize(num)
@rep = num.rep
end
op_mths =[:%,:&,:*,:**,:+,:+@,:-,:-@,:/,:abs,:remainder] # etc.
# Note to simplify things we explicitly left out examples
# of methods with negative arity.
op_mths.each {|mth|
arity = 42.method(mth).arity
mth = mth.to_s
sgn = Array.new(arity){|i| "_#{i}" }.join(',')
args = Array.new(arity){|i| "_#{i}.rep" }.join(',')
body = "def #{mth}(#{sgn}) Wrapper.new(@rep.#{mth}(#{args})) end"
class_eval body
}
bool_mths =[:zero?,:<,:<=,:<=>,:between? ] # etc.
bool_mths.each {|mth|
arity = 42.method(mth).arity
mth = mth.to_s
sgn = Array.new(arity){|i| "_#{i}" }.join(',')
args = Array.new(arity){|i| "_#{i}.rep" }.join(',')
body = "def #{mth}(#{sgn}) @rep.#{mth}(#{args}) end"
class_eval body
}
def coerce(other)
[other,rep]
end
def post_add(rhs)
tmp = clone
@rep = @rep + rhs.rep
tmp
end
end
p a = Wrapper.new(3) # 3
p 6.0 / a # 2.0
p a.post_add(4) # 3
p a # 7
p a < 3 # false
----
/Christoph