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
<src>
	...
         <column id="sourceadjacentaddress">
                 <type>string</type>
         </column>
         <column id="destadjacentaddress">
                 <type>string</type>
         </column>
	...
</src>	
<rslt>
	...
         <column id="link1">
           <test exp="@src_sourceadjacentaddress == '00-D0-41-68- 
CF-56' || @src_destadjacentaddress == '00-D0-41-68-CF-56'"> </test>
           <value exp= "+= @src_d_tooctets+src_d_fromoctets">  </value>
           <type>int</type>
           <scale exp="/@groupby_duration.megabyte"> </scale>
           <format>%d</format>
         </column>
	...
</rslt>

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
	<value exp= "+= [@src_d_tooctets, @src_d_fromoctets]">  </value>
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
>
>