[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

yield/block question

Kenneth McDonald

9/10/2008 12:05:00 AM

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

5 Answers

Martin DeMello

9/10/2008 12:11:00 AM

0

On Tue, Sep 9, 2008 at 5:04 PM, Kenneth McDonald
<kenneth.m.mcdonald@sbcglobal.net> wrote:
> 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.

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

martin

Serabe

9/10/2008 12:18:00 AM

0

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).

--
http://www....

Kenneth McDonald

9/10/2008 12:37:00 AM

0

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


On Sep 9, 2008, at 7:11 PM, Martin DeMello wrote:

> On Tue, Sep 9, 2008 at 5:04 PM, Kenneth McDonald
> <kenneth.m.mcdonald@sbcglobal.net> wrote:
>> 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.
>
> array.flatten.each {|i| yield i}
>
> martin
>


Kenneth McDonald

9/10/2008 12:37:00 AM

0

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


On Sep 9, 2008, at 7:17 PM, Serabe wrote:

> 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).
>
> --
> http://www....
>


Robert Klemme

9/10/2008 9:40:00 AM

0

2008/9/10 Kenneth McDonald <kenneth.m.mcdonald@sbcglobal.net>:
> On Sep 9, 2008, at 7:17 PM, Serabe wrote:
>
>> 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

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

--
use.inject do |as, often| as.you_can - without end