From: Andy Bogdanov on
Hello

I was trying to make an iterator that goes through a simple tree
structure something like that:

class Node
...
def each_child(&block)
@children.each { |child| yield(child) { child.each_child(&block) } }
end
...
end

so i could generate a simple html menu:

puts "<ul>"
root_node.each_child { |node|
puts "<li><a href=\"#{child.link}\">#{child.title}</a></li>"
unless node.children.empty?
puts "<ul>"
yield
puts "</ul>"
end
}
puts "</ul>"

But it turns out that Ruby syntax prohibits passing blocks to yield. A
simple workaround is to use block.call instead of yield everywhere.

Is there any good reason for that limitation?
--
Posted via http://www.ruby-forum.com/.

From: Robert Klemme on
On 28.06.2010 14:52, Andy Bogdanov wrote:
> I was trying to make an iterator that goes through a simple tree
> structure something like that:
>
> class Node
> ..
> def each_child(&block)
> @children.each { |child| yield(child) { child.each_child(&block) } }
> end
> ..
> end
>
> so i could generate a simple html menu:
>
> puts "<ul>"
> root_node.each_child { |node|
> puts "<li><a href=\"#{child.link}\">#{child.title}</a></li>"
> unless node.children.empty?
> puts "<ul>"
> yield
> puts "</ul>"
> end
> }
> puts "</ul>"
>
> But it turns out that Ruby syntax prohibits passing blocks to yield. A
> simple workaround is to use block.call instead of yield everywhere.
>
> Is there any good reason for that limitation?

There is no point in passing a block to yield because yield implicitly
calls the block passed to the current method.

I think what you really want is this:

def each_child(&b)
b[self] # or b.call(self) or simply yield self
@children.each {|ch| ch.each_child(&b)}
self
end

Kind regards

robert

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
From: Andy Bogdanov on
> There is no point in passing a block to yield

Maybe there always is a way to avoid using procs and lambdas, but i
don't see other easy way in my case (see below).
Proc#call accepts blocks, why does yield not? It's almost the same
thing.

> yield implicitly calls the block
> passed to the current method.

Thanks for the tip. Forgot that yield belongs to method context only.

> def each_child(&b)
> b[self] # or b.call(self) or simply yield self
> @children.each {|ch| ch.each_child(&b)}
> self
> end

This code will just pass all the elements to a block, there's no way to
wrap lower levels into <ul> tag. I need to control what happens before
and after each_child so i have use a number of procs as arguments or do
this trick with a block.
--
Posted via http://www.ruby-forum.com/.

From: Josh Cheek on
[Note: parts of this message were removed to make it a legal post.]

On Mon, Jun 28, 2010 at 7:52 AM, Andy Bogdanov <andy.bogdanov(a)gmail.com>wrote:

> Hello
>
> I was trying to make an iterator that goes through a simple tree
> structure something like that:
>
> class Node
> ...
> def each_child(&block)
> @children.each { |child| yield(child) { child.each_child(&block) } }
> end
> ...
> end
>
> so i could generate a simple html menu:
>
> puts "<ul>"
> root_node.each_child { |node|
> puts "<li><a href=\"#{child.link}\">#{child.title}</a></li>"
> unless node.children.empty?
> puts "<ul>"
> yield
> puts "</ul>"
> end
> }
> puts "</ul>"
>
> But it turns out that Ruby syntax prohibits passing blocks to yield. A
> simple workaround is to use block.call instead of yield everywhere.
>
> Is there any good reason for that limitation?
> --
> Posted via http://www.ruby-forum.com/.
>
>
Looks like you can get it to work by explicitly taking the block, rather
than trying to yield.

def foo(&block)
block.call 1 do
2
end
end

foo do |param,&block|
puts "The param is #{param}"
puts "The block is #{block.call}"
end


I checked it on 1.8.7 - 1.9.2, it does not work on 1.8.6, though.

 | 
Pages: 1
Prev: gem rake error
Next: pretty inspecting objects?