Can a lambda or Proc object yield a value to a block?

M

Mick Macamhlaoibh

I've searched quite a bit on the web and through "Programming Ruby - the
Pragmatic Programmer's Guide" and I can't find a satisfactory answer to
the question:

Can a lambda or Proc object yield a value to a block?

For example when I try this
yieldArg = lambda {|arg| yield arg}
yieldArg.call(23) {|y| puts("y="+y.to_s)}
in Interactive Ruby I get
"LocalJumpError: no block given"

So I try
yieldArg = lambda {|arg| puts "no block given" unless block_given? ;
yield arg}
to print some indication of whether the block really has been "given"
and I get
no block given
LocalJumpError: no block given

So then I try to wrap the block in a lambda and pass it as a param
putsY = lambda {|y| puts("y="+y.to_s)}
yieldArg.call(23) {|y| puts("y="+y.to_s)}
yieldArg.call(23, &putsY)
but with the same negative result.

So can a lambda or Proc object yield a value to a block? If so, how is
it done?

Thanks in advance.

Interactive Ruby session shown below.

irb(main):001:0> yieldArg = lambda {|arg| yield arg}
=> #<Proc:0x02dfebf0@(irb):1>
irb(main):002:0> yieldArg.call(23) {|y| puts("y="+y.to_s)}
LocalJumpError: no block given
from (irb):1
from (irb):2:in `call'
from (irb):2
irb(main):003:0> yieldArg = lambda {|arg| puts "no block given" unless
block_given? ; yield arg}
=> #<Proc:0x02df58e8@(irb):3>
irb(main):004:0> yieldArg.call(23) {|y| puts("y="+y.to_s)}
no block given
LocalJumpError: no block given
from (irb):3
from (irb):4:in `call'
from (irb):4
irb(main):005:0> putsY = lambda {|y| puts("y="+y.to_s)}
=> #<Proc:0x02dede2c@(irb):5>
irb(main):006:0> yieldArg.call(23, &putsY)
no block given
LocalJumpError: no block given
from (irb):3
from (irb):6:in `call'
from (irb):6
irb(main):007:0>
 
C

Cleasai Beag

Logan said:
You actually can use yield in a block, you just need to realize it's the
yield of the enclosing scope:

def example
a_proc = lambda { yield "Hi" }

if block_given?
a_proc.call
end
end

example { |x| puts x }

Thanks for the reply Logan. Obviously I'll have to study Ruby's scope
rules a bit more. I notice that I can't modify your example as follows
to pass in a lambda object because I get the "LocalJumpError: no block
given" error again.

a_proc = lambda { yield "Hi" }

def example2(proc)

if block_given?
proc.call
end
end

example2(a_proc) { |x| puts x }

Presumably the enclosing scope for the lambda object in my example is
outside the scope of the example2 method. It's scope is the scope in
which it was defined which is "nowhere" really i.e. it's outside a
class, module and method.
Presumably because of this it just can't yield a value. Does this sound
plausible at all?

P.S. What I'm really trying to do is emulate some of things that I've
done before in Scheme.

For example a generic "each" maker which doesn't work 'cos of the whole
LocalJumpError thing.

def makeEach(nextValue, start, stop)
lambda do
x = start
while x <= stop
yield x
x = nextValue.call(x)
end
end
end

from11to20 = makeEach(lambda {|x| x+1}, 11, 20)

from11to20 {|x| puts x*x}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top