Devin Mullins wrote:
Well, you could do this:
class B < Array
def initialize(i,v)
self[0] = @i = i
self[1] = @v = v
end
end
But I think your best bet is define your own Collection object with
its own #each.
I though so, too, but it doesn't help:
13:13:33 [~]: irbs
A = Struct.new(:i, :v)
=> A
A.ancestors
=> [A, Struct, Enumerable, Object, Kernel]
A.new(1,2).each {|x| p x}
1
2
=> #<struct A i=1, v=2>
arr = [A.new(1,2), A.new(3,4)]
=> [#<struct A i=1, v=2>, #<struct A i=3, v=4>]
arr.each {|a,b| puts a,b}
#<struct A i=1, v=2>
nil
#<struct A i=3, v=4>
nil
=> [#<struct A i=1, v=2>, #<struct A i=3, v=4>]
arr.each {|(a,b)| puts a,b}
#<struct A i=1, v=2>
nil
#<struct A i=3, v=4>
nil
=> [#<struct A i=1, v=2>, #<struct A i=3, v=4>]
arr.each {|*a| p a}
[#<struct A i=1, v=2>]
[#<struct A i=3, v=4>]
=> [#<struct A i=1, v=2>, #<struct A i=3, v=4>]
I guess this is the reason:
x,y=A.new(1,2)
=> [#<struct A i=1, v=2>]
x
=> #<struct A i=1, v=2>
y
=> nil
x,y=*A.new(1,2)
=> [1, 2]
x
=> 1
y
=> 2
x,y=[1,2]
=> [1, 2]
x
=> 1
y
=> 2
In other words, it's not sufficient to be Enumerable to automatically be
assigned to individual variables in this scenario. You must have an
Array. Maybe to change this is worth an RCR?
While I would find this convenient it's really not too hard to access
members explicitely.
Interesting sidenote (endnote?): Operator precedence causes this:
self[0], self[1] = @i, @v = i, v
To set self[1] = @i, and @v = i, and to return the Array containing
self[0], self[1], @v, and v. If you want to do a silly thing like
chain parallel assignments, you have to add parens:
self[0], self[1] = (@i, @v = i, v)
But then again, that's what you get for trying to write code that's
painful to read.
Kind regards
robert