From: Dave Burt Date: 2006-06-02T09:34:10+09:00 Subject: Re: Adding an Increment Operator? Dave Howell wrote: > So, how WOULD I create an .increment operator? I get why I can't put it > in class Fixnum (well, I think I know why); Fixnums are symbol-ish-ly > unalterable. 5.increment should fail, for sanity's sake. > > So I have to add .increment to class . . . hmm. I can't add it to > variables; they're just references. But I want my_var.increment to > change 'my_var' so that it references the next integer in line. > > Strings have methods that alter strings in place, but a String object is > a composite object, made up of characters, and !-type methods alter the > characters of the string without altering the variable's reference. > Numbers aren't composite objects. Maybe it can't be done? But people are > constantly amazing me with crazy magical Ruby tricks; it seems so > improbable that there isn't a way to do this as well . . . > > Somebody else pointed out I could just my_var += 1. Yes, but to me, that > implies that the "1" is deliberate, and at some other point I might add > 2 or 5 or something, whereas using "inc" or "++" or whatever says "it > really doesn't matter if I'm counting by ones, tens, Roman numerals, or > letters. This variable is just stepping upwards." > > But the main reason I'm asking is not to slightly improve the esthetics > of a couple lines of code. I'm certain that I'm going to learn something > interesting from the answer to the question. As has been pointed out, you can't modify a Fixnum, nor can you ever assign to self. I wasn't going to mention the kind of generic delegating container Ross just wrote about; have a look, but I don't think you'll find a place to use that where there isn't a better solution. Another approach might be to encapsulate a counter like so: class Counter attr_accessor :value def initialize(i = 0) @value = i end def inc @value = @value.succ end end i = Counter.new i.value #=> 0 i.inc #=> 1 i.inc #=> 2 i.value = "X" i.inc #=> "Y" Or you can do like this: def counter(i = 0) proc { i = i.succ } end i = counter i.call #=> 1 i.call #=> 2 i[] #=> 3 Cheers, Dave