From: MikkelFJ Date: 2002-12-01T05:19:29+09:00 Subject: Ruby ++, the one element and generators In algebraic theory, terms such as groups and rings are used to define what addition and multiplication mean. I'm here trying to use something I learned and forgot a long time ago, so bear with me, but I think the concepts may apply here. In Ruby += has been defined as a combination of assignment and the plus operation (i.e. addition). In other languages ++ has been defined as the addition with one. In algebra, the one element is a particularly important element (along with zero) because you can generate all values by systematically adding the one element to the previous result, starting with the zero element. It appears to me that all the talk about why ++ is not valid due to anti-shoe-box behaviour is beside the point, because the would also be true for += : a = 1 a += 2 # ==> 3 We are not redefining any integers here, we are replacing the reference with a reference to a new object. The following makes just as much sense as the above: a = 1 a++ # ==> 2 The point, is that whatever problems there are with ++ and object modifications applies equally to += and the next, next! method, and these problems have been solved. We can't, however, define ++ without help from the Ruby interpreter because ++ should be specially interpreted at the same level as += becuase assignment to self is not possible. In other words, ++ is an operator that replaces a reference to one object with a reference to the next object. This operation may or may not be an inplace operation. Thus we have ++ and ++!. In fact this is exactly the same as the next and next! methods, thus we just need the interpreter to go along with these synonyms. Note that integers do not have a next! operation and float do not have a next method at all - this makes perfect sense: In algebraic terms, there is no 'one' element for Real numbers, while natural numbers (integers) do have a one element. Furthermore it is not within the realms of Ruby to redefine the natural numbers, thus no next! method. The ++ operator is really a 'generator' in algebraic terms. It should generate the next element in the set of all elements of a given type, such as the natural numbers. When a one element is defined, the generator is the add one operator - it is not necessarily the only generator, but it works. (stray thought: generators are used on error correcting codes to generate valid values among all values - a very simple error correcting code would be to define 0, 4, 8, ..., i.e. generator is x += 4. correct(x) = x + 2 mod 4, thus if someone accidentally added 1 to x, it won't destroy the information). In Ruby we don't really care about exact algebraic generators. For example it is nice to have the next string: "helo".next ==> "help". This doesn't generate all valid strings, yet it is rather useful. Thus we can piggyback on the "next" method to define our generator - or we may define our generator as "generator" and define next in terms of the generator whatever... The default generator can be define based on the one element, whenever it is defined. As an example, let us define the one element for Float. Algebraically it doesn't make sense, except by doint so we actually define a new value type - which incidentally happens to be the natural numbers if we define one as an arbitrary non-zero float value, it just has a different representation: We can define a default generator and a default next method for Object: class Object def generator self + one end def next generator end end Or just ignore the generator stuff: class Object def next self + one end end We can define the one element for any class we like: class Float def one 1.0 end end a = 1.0 a.next # ==> 2.0 No we could equally well write a++ as a synonym for a = a.next and a++! as a synom for a.next! Note that we do not have a default definition of next!, but it may be referencing an object that does have next! defined, such as a string. Obviously iterators are obvious candiates for ++: In the following notice the importnat difference between ++ and ++! If I had used ++! I would not have been able to reference two values in the collection at the same time, yet I feel ++ does exactly what I expect in the following. This suggests there really is a difference between ++ and ++! and both are meaningful in their own terms. if my_collection.size > 1 begin c = 0 a = my_collection.first k = a ++a while a != my_collection.end b = a a++ if a.value > b.value a.swap_values b c++ end end while c > 0 end def unique x if not my_collection.exist(x) return x end x = x + "~a" while my_collection.exist(x) x++! next end Of course, the above examples could be written with next and next!. In particular, the ++! would probably be nicer using next! But the ++ operator makes the operation somewhat cleaner that a = a.next. Mikkel