From: Kent Dahl Date: 2001-08-02T02:17:44+09:00 Subject: [ruby-talk:18977] "Bang" versions of numerical methods on non-immediate values [was: Numbers classes.. Rational number? ] Since my previous rant about this seemed to go unnoticed (due to the Rational discussion I presume), I'm voicing it one more time. Summary: I want methods add!, sub!, div! and mul! for all numeric objects. Reason: Efficiency when dealing with non-immediate value types by reducing amount of generated objects. Rationale: Float, Bignum and similar numerical classes generate new objects that float (no pun intended) around bugging the GC. Having some way of doing aritmetic on these objects without generating a new object, would help on GC performance. I recall some talk about Float maybe becoming an immediate value due to these problems, but this seems easier to implement without breaking anything. (Not that I've actually opened the Ruby source :-) Example: Doing accumulation over floats: [kentda@v128a ruby]$ ruby --version ruby 1.6.2 (2001-01-23) [i586-linux-gnu] [kentda@v128a ruby]$ irb --version irb 0.6.1(99/09/16) [kentda@v128a ruby]$ irb irb(main):001:0> GC.disable false irb(main):002:0> count = 0; ObjectSpace.each_object(Float){|f| count+=1};count 2 irb(main):003:0> a=0; (1..1000).each{|i| a+=1.0 }; a 1000.0 irb(main):004:0> count = 0; ObjectSpace.each_object(Float){|f| count+=1};count 1003 Choice of methods names: While using the *=, /=, +=, -= family for something like this, that would break backward compatability and introduce confusion. The "bang" (!) in methodnames has standard meaning in Ruby; changing inplace. I also think that being more explicit when doing things for efficiency. Potential reasons against doing this: * If created numbers are to be considered final, frozen and/or immutable. * Potential "side-effects" causing confusion. a = b = 1.0 a.add!(0.25) # a==b==1.25 now, since they refer same object * Inconsistent behaviour between immediate values and object values (but we already have some of that) a = b = 1 a.add!(1) # a==2 and b==1, due to immediate values * Conceptual difference between Number and Value. "There can be only one..." instance of the number 25, but several values can denote 25. But as I understand it, this principle is not enforced anyway, since two floats with same value are different objects: irb(main):001:0> GC.disable false irb(main):002:0> count = 0; ObjectSpace.each_object(Float){|f| count+=1};count 2 irb(main):003:0> a = 1.0 1.0 irb(main):004:0> b = 1.0 1.0 irb(main):005:0> count = 0; ObjectSpace.each_object(Float){|f| count+=1};count 4 That's all I can think off. Is there something obvious I'm missing? Like why this is a terrible idea, or that something similar already exists in Ruby? I'm hoping to get some clarifying discussion on the matter, and perhaps add it as an RCR. For those who missed my previous rant, I quote it here: Kent Dahl wrote: > While I'm ranting about numbers: Is there any plans to have "bang" > versions of numeric operators? > > > irb(main):077:0> a = b = 5.0 > 5.0 > irb(main):078:0> > irb(main):079:0* a *=2 > 10.0 > irb(main):080:0> b > 5.0 > > > This seems to indicate that a*=b is just syntactic sugar for a=a+b, > which is probably the element of least surprise, atleast when converting > Java / C++ programmers more familiar with by-value semantics. But if I > put my OO-purist cap on and start chanting, I feel like the *= operator > violates the object-message paradigm: I would assume the object is > changed inplace. > > So, how about mul!, div!, plus! and minus! to complement (and imitate > for immediate types) the operators *=, /=, += and -= that yields this > functionality: > a = b = 5.0 #=> 5.0 > a.mul! 2 #=> 10.0 > b #=> 10.0 > > On numeric objects that are real (and bother the GC), I think this might > help on efficiency, avoiding the creation of an object. > > The only real problem I see, is the confusion it could lead to when > working with immediate values that _may_ turn into true objects due to a > call: > a = b = 5 #=> 5 > a.mul! 2 #=> 10 > b #=> 5 # immediate value, therefore not changed > versus > a = b = myLargeNumber # myLargeNumber could be Fixnum, Bignum, Float > etc > a.mul! 2 #=> myLargeNumber*2 > b # Just what is b now? > where b would be myLargeNumber if it was a Fixnum, but would be > myLargeNumber*2 if > it was a true object (Bignum, Float, etc) > > Have I gone completely mad, missed something obvious or? Comments? -- <[ Kent Dahl ]>================<[ http://www.stud.ntnu.no/~kentda/ ]> )____(stud.techn.;ind.�k.data)||(softwareDeveloper.at(Trustix))_( /"Opinions expressed are mine and not those of my Employer, "\ ( "the University, my girlfriend, stray cats, banana fruitflies, " ) \"nor the frontal lobe of my left cerebral hemisphere. "/