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

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

martin

···

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.

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

···

--

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

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.serabe.com

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

···

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

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