Yield/block question

This is something I know how to do in Python, but it’s got me
flummoxed in Ruby–I still haven’t fully gotten my head around the
Ruby way. (“yield” means something very different in Python and in Ruby.

Let’s say I have a data structure consisting of nested Arrays and
numbers, for example [[1,2], 3, [[4]]]. I want to write an extension
to Array, “each_leaf”, which takes a block that will be applied to
each number sequentially in that nested array. For example, if arr is
the given array, then

result = 0
arr.each_leaf {|n| result += n}

would end with result being equal to 1+2+3+4

Could anyone help out? Much appreciated.

Thanks,
Ken

On Tue, Sep 9, 2008 at 5:04 PM, Kenneth McDonald
[email protected] wrote:

result = 0
arr.each_leaf {|n| result += n}

would end with result being equal to 1+2+3+4

Could anyone help out? Much appreciated.

array.flatten.each {|i| yield i}

martin

What about this?

class Array
def each_leaf(&block)
each do |x|
case x
when Array: x.each_leaf &block
else block.call x
end
end
end
end

arr = [[1,2], 3, [[4]]]
result = 0
arr.each_leaf{|n| result += n}

puts result

Kind regards,

Serabe

P.D. Sorry for no more explanation, but I’m really tired (2:23 am right
now).

Perfect, just what I was looking for. Thanks,
Ken

Very elegant, with the drawback that it requires flattening a
potentially large array structure.
But that was carelessness in my lack of specifications. A nice
solution, thank you.

Ken

2008/9/10 Kenneth McDonald [email protected]:

end

end
end
end

This can be generalized to Enumerable. Still a handicap is that this
does not gracefully deal with structures which are not cycle free.

Just some toying around:

module Enumerable
def each_leaf(cl = Object, &b)
each do |el|
case el
when String
yield el if cl === el
when Enumerable
el.each_leaf(cl, &b)
when cl
yield el
else
# ignore
end
end
end
end

Kind regards

robert