From: Rob Burrowes Date: 2006-05-20T12:46:44+09:00 Subject: Re: Cool: nil is a class that can have methods Probably total sacrilege, but I was using this to have "nil" as a valid value in arithmetic and to treat numbers as if they were arrays (in a limited sense). The latter is easy to fix, by storing all numbers as 1 element arrays. This solves the iterator on "nil" too. All nil values will be in an array, so I just need to iterate on the array. Using "nil" in arithmetic is to differentiate the no data state (nil), from having seen a data point, even a 0 value. Probably best to subclass Fixnum and build my own objects for arithmetic. Altering the numeric classes is definitely a tempting thing though. I have XML definitions of the source log file and the resulting summary I want to get. e.g. a ... string string ... ... int %d ... This gets turned into ruby code that parses the log. It uses modified column name as variables. The test expression determines if the output column is modified, and the value expression is used to set or alter the value. If the values start as nil, then adding a value, will initialise them. Meeting further values, will result in them being added on. If multiple results are required (e.g. for a histogram), then a value expression like results in the to and from traffic being added to an array result called @rslt_link1, rather than a simple numeric result. I did this by I adding "each" and "each_with_index" to every Object, thus allowing numbers and nil values to have an iterator. I replaced the Fixnum + with one that would add arrays to numbers, giving an array result or Fixnum result, depending on the value being added. Also the Arrays class was modified to add two arrays, by adding the elements at the same array index to each other, not concatenating the arrays. I then committed the ultimate sin, and added a plus method to nil. After all these hacks, I can add a number to an array, and the first element will get altered. add an array to a number, and get an Array with the first element altered add a number or Array to nil, and get that number or the Array i.e. class Object def each if self != nil then yield(self) end end def each_with_index if self != nil then yield(self,0) end end def length if self == nil then 0 else 1 end end end class Array def +(value) value.each_with_index { |x,i| self[i] += x } self end end class Fixnum alias oldPlus + def +(value) if(value.length == 1) self.oldPlus(value) else value.+(self) end end end class NilClass def +(value) value end end a = [1,3] a += [5,2] a.each {|b| puts b } puts a = 1 a += 2 a.each {|b| puts b } puts a += [5,2] a.each {|b| puts b } puts a = nil a += 10 a.each {|b| puts b } puts a = nil a += [3,8] a.each {|b| puts b } puts a = ["hello","I"] a += [" world"," repent"] a.each {|b| print b, " " } puts On 20/05/2006, at 2:18 PM, Sam Roberts wrote: > Quoting rob@cs.auckland.ac.nz, on Sat, May 20, 2006 at 09:50:49AM > +0900: >> In the nil case, I wanted it to iterate and be printed as in the same >> way as a non-nil value. In the plot data, a nil prints as '-'. I >> hadn't thought of other code expecting to fail when the value was nil >> or not an array. They probably wont want nil to have a to_s() >> returning '-' either, not that anything has failed doing this, in >> this instance. > > The temptation to change the core classes to work a little more > like you > want is almost overwhelming... at least I have found it so. I guess in > this case you could do: > > def gnuplot_each(v, &proc) > if v.respond_to? :each > v.each &proc > else > yield v > end > end > > then instead of doing > > data.each {..} > > you could do > > gnuplot_each(data) {...} > > > cheers, > Sam > >