Block.call vs. yield

I noticed that the use of block/yield differs slightly when a “break” is
called in the code. For example:

class Array
def myI()
self.each{ |aa| yield(aa) }
end
end

[0,1,2].myI { |xx| [10,20,30].myI { |yy| break if(yy==20 and xx==0); puts
"#{xx}:#{yy}" }}’

RESULT:
0:10
1:10
1:20
1:30
2:10
2:20
2:30

···

==============================================
class Array
def myI(&blk)
self.each{ |aa| blk.call(aa) }
end
end

[0,1,2].myI { |xx| [10,20,30].myI { |yy| break if(yy==20 and xx==0); puts
"#{xx}:#{yy}" }}’

RESULT:
0:10
0:30 # This result was not expected
1:10
1:20
1:30
2:10
2:20
2:30

My question is, why, when using the second method, does the “break” not seem
to break completely out of the loop, but rather acts like a “next” by
terminating the current unit of iteration. I would not expect to get the
"0:30" result. I was under the impression that block.call/yeild were
synonymous.


The new MSN 8: smart spam protection and 2 months FREE*
http://join.msn.com/?page=features/junkmail

Hi,

···

In message “block.call vs. yield” on 03/04/25, “Orion Hunter” orion2480@hotmail.com writes:

I noticed that the use of block/yield differs slightly when a “break” is
called in the code.

You’ve found something unnatural. Let me examine.

						matz.

Hi,

···

In message “Re: block.call vs. yield” on 03/04/25, Yukihiro Matsumoto matz@ruby-lang.org writes:

I noticed that the use of block/yield differs slightly when a “break” is
called in the code.

You’ve found something unnatural. Let me examine.

As a conclusion, you will have compatible behavior when you use
blk.yield (new method in 1.8) instead of blk.call. Fix will be
available soon on the CVS.

						matz.

As a conclusion, you will have compatible behavior when you use
blk.yield (new method in 1.8) instead of blk.call.

···

----- Original Message -----
From: “Yukihiro Matsumoto” matz@ruby-lang.org


I’m sorry… I don’t understand. Will blk.yield do the same thing that
yield did? Is blk.call going away, or will it still do something different
from yield? And finally, what is the difference between blk.call and
blk.yield?

Chris

Hi –

Hi,

I noticed that the use of block/yield differs slightly when a “break” is
called in the code.

You’ve found something unnatural. Let me examine.

As a conclusion, you will have compatible behavior when you use
blk.yield (new method in 1.8) instead of blk.call. Fix will be
available soon on the CVS.

Language comment:

‘yield’ as a method name for blocks strikes me as awkward. In the
past I’ve never thought of 'yield’ing as an action performed by
blocks, nor as something they’re asked to do; it’s more that they are
executed because they get control because a ‘yield’ has already
happened.

David

···

On Fri, 25 Apr 2003, Yukihiro Matsumoto wrote:

In message “Re: block.call vs. yield” > on 03/04/25, Yukihiro Matsumoto matz@ruby-lang.org writes:


David Alan Black
home: dblack@superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

Chris Pine wrote:

···

----- Original Message -----
From: “Yukihiro Matsumoto” matz@ruby-lang.org

As a conclusion, you will have compatible behavior when you use
blk.yield (new method in 1.8) instead of blk.call.

I’m sorry… I don’t understand. Will blk.yield do the same thing that
yield did? Is blk.call going away, or will it still do something different
from yield? And finally, what is the difference between blk.call and
blk.yield?

It’s documented in the new ri (basically parameter passing conventions)

-------------------------------------------------------------- Proc#call
prc.call( [params]* ) -> anObject

  Invokes the block, setting the block's parameters to the values in
  params using something close to method calling semantics. Returns
  the value of the last expression evaluated in the block. See also
  Proc#yield.
     a_proc = Proc.new {|a, *b| b.collect {|i| i*a }}
     a_proc.call(9, 1, 2, 3)   #=> [9, 18, 27]
     a_proc[9, 1, 2, 3]        #=> [9, 18, 27]
     a_proc = Proc.new {|a| a}
     a_proc.call(1,2,3)        #=> [1, 2, 3]
  call checks the number of parameters matches that in the call.
     a_proc = Proc.new {|a,b| a}
     a_proc.call(1,2,3)
  produces:
     prog.rb:1: wrong number of arguments (3 for 2) (ArgumentError)
             from prog.rb:1:in `call'
             from prog.rb:2

------------------------------------------------------------- Proc#yield
prc.yield( [params]* ) -> anObject

  Invokes the block, setting the block's parameters to the values in
  params using yield semantics (closer to those of parallel
  assignment). Returns the value of the last expression evaluated in
  the block. See also Proc#call.
     a_proc = Proc.new {|a, *b| b.collect {|i| i*a }}
     a_proc.yield(9, 1, 2, 3)   #=> [9, 18, 27]
     a_proc = Proc.new {|a| a}
     a_proc.yield(1,2,3)        #=> [1, 2, 3]
     a_proc = Proc.new {|a,b| a}
     a_proc.yield(1,2,3)        #=> 1

Hi,

···

In message “Re: block.call vs. yield” on 03/04/25, dblack@superlink.net dblack@superlink.net writes:

Language comment:

‘yield’ as a method name for blocks strikes me as awkward. In the
past I’ve never thought of 'yield’ing as an action performed by
blocks, nor as something they’re asked to do; it’s more that they are
executed because they get control because a ‘yield’ has already
happened.

Sorry I don’t understand. Do you mean you don’t want a method with
reserved word name?

Could you restate your statement?

						matz.

p.s.
Wish I were born in English speaking country.

I now see what David is saying. I had failed to
read all of the thread.

I agree, ‘yield’ as a method name is not ideal.
Perhaps ‘invoke’ – although that is not mentally
associated with ‘yield’ nor is it mentally
distant enough from ‘call’.

I think those are the two real difficulties in
naming this method: 1. We want people to know
it has the semantics of yield; 2. We want them
to know it is different from call.

Hal

···

----- Original Message -----
From: dblack@superlink.net
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Friday, April 25, 2003 5:51 AM
Subject: Re: block.call vs. yield

As a conclusion, you will have compatible behavior when you use
blk.yield (new method in 1.8) instead of blk.call. Fix will be
available soon on the CVS.

Language comment:

‘yield’ as a method name for blocks strikes me as awkward. In the
past I’ve never thought of 'yield’ing as an action performed by
blocks, nor as something they’re asked to do; it’s more that they are
executed because they get control because a ‘yield’ has already
happened.

Language comment:

‘yield’ as a method name for blocks strikes me as awkward. In the
past I’ve never thought of 'yield’ing as an action performed by
blocks, nor as something they’re asked to do; it’s more that they are
executed because they get control because a ‘yield’ has already
happened.

Sorry I don’t understand. Do you mean you don’t want a method with
reserved word name?

What I got from David’s comment, and what the word ‘yield’ suggests to me,
is that a block itself does not yield, but rather a block is executed because
some other process has opted to yield process control.

For example, when driving in the States (and I imagine there is something
similar elsewhere) there are signs that say, ‘Yield’, meaning one driver
must pause and allow other drivers to proceed. The pausing driver
is the one processing the ‘yield’ message, rather than those drivers given
the go-ahead.

Could you restate your statement?

  					matz.

p.s.
Wish I were born in English speaking country.

Oh, how different things would be …

James

···

In message “Re: block.call vs. yield” > on 03/04/25, dblack@superlink.net dblack@superlink.net writes:

In article 1051322601.749252.21002.nullmailer@picachu.netlab.jp,

···

Yukihiro Matsumoto matz@ruby-lang.org wrote:

Hi,

In message “Re: block.call vs. yield” > on 03/04/25, dblack@superlink.net dblack@superlink.net writes:

Language comment:

‘yield’ as a method name for blocks strikes me as awkward. In the
past I’ve never thought of 'yield’ing as an action performed by
blocks, nor as something they’re asked to do; it’s more that they are
executed because they get control because a ‘yield’ has already
happened.

Sorry I don’t understand. Do you mean you don’t want a method with
reserved word name?

Could you restate your statement?

  					matz.

p.s.
Wish I were born in English speaking country.

That’s OK. Sometimes we wish we were born in a Japanese speaking country
so we could read all those Ruby books & docs you have over there.

Phil

Hi –

Hi,

Language comment:

‘yield’ as a method name for blocks strikes me as awkward. In the
past I’ve never thought of 'yield’ing as an action performed by
blocks, nor as something they’re asked to do; it’s more that they are
executed because they get control because a ‘yield’ has already
happened.

Sorry I don’t understand. Do you mean you don’t want a method with
reserved word name?

Could you restate your statement?

The follow-ups captured most of my meaning, but I’ll follow up myself
anyway.

In a ‘yield’, the block is being yielded to – it is not, itself,
yielding control. Therefore, what you’d really need, to describe a
yield in terms of the block as a receiver, would be something like:

blk.be_yielded_to

which I’m not advocating, of course; it’s just that

blk.yield

suggests that the block is performing an action described as
’yield’ing, which I don’t think it is.

Also, the use of ‘yield’ as shorthand for ‘call with certain
semantics’ (if I’m understanding that correctly) seems very obscure
to me. This would be very hard to explain to someone learning Ruby
(“The block isn’t actually yielding control; the method is called
’yield’ because elsewhere in the language there’s something called
’yield’ that has the same calling semantics…”).

In that regard, to me it has a similar feel to:

proc { |a,*b| … } .def # call proc using arg semantics
# of a method definition

David

···

On Sat, 26 Apr 2003, Yukihiro Matsumoto wrote:

In message “Re: block.call vs. yield” > on 03/04/25, dblack@superlink.net dblack@superlink.net writes:


David Alan Black
home: dblack@superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

Hi –

From: dblack@superlink.net
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Friday, April 25, 2003 5:51 AM
Subject: Re: block.call vs. yield

As a conclusion, you will have compatible behavior when you use
blk.yield (new method in 1.8) instead of blk.call. Fix will be
available soon on the CVS.

Language comment:

‘yield’ as a method name for blocks strikes me as awkward. In the
past I’ve never thought of 'yield’ing as an action performed by
blocks, nor as something they’re asked to do; it’s more that they are
executed because they get control because a ‘yield’ has already
happened.

I now see what David is saying. I had failed to
read all of the thread.

I agree, ‘yield’ as a method name is not ideal.
Perhaps ‘invoke’ – although that is not mentally
associated with ‘yield’ nor is it mentally
distant enough from ‘call’.

I think those are the two real difficulties in
naming this method: 1. We want people to know
it has the semantics of yield; 2. We want them
to know it is different from call.

I think that if the semantics of yield are to be generalized, they
should be thought of as something other than the semantics of yield.
It seems to me that the situation is somewhat like this:

 type 1 semantics                     type 2 semantics

  >         >                          >              >
  >         >                          >              >

methods Proc#call yield Proc#whatever

in which case, yield and Proc#whatever share semantics, but there’s no
reason (except “historical reasons”) to define them as “yield
semantics”.

I agree that ‘invoke’ is problematic. It’s sort of arbitrary; it is a
different word, but there’s no reason to favor the idea that it
differs in a particular way from call.

Maybe something like call_with_… or call_as… ? (Not sure what the
… would be.)

David

···

On Sat, 26 Apr 2003, Hal E. Fulton wrote:

----- Original Message -----


David Alan Black
home: dblack@superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

Chris Pine wrote:

I’m sorry… I don’t understand. Will blk.yield do the same thing that
yield did? Is blk.call going away, or will it still do something
different
from yield? And finally, what is the difference between blk.call and
blk.yield?

It’s documented in the new ri (basically parameter passing conventions)

···

----- Original Message -----
From: “Dave Thomas” dave@pragprog.com

Maybe I’m just slower than usual… but I still don’t get it.

I understand the difference in parameter passing conventions between call
and yield. No problem there. My question is this: How were parameter
passing conventions causing the behavior in the original post?

?

Chris

‘yield’ as a method name for blocks strikes me as awkward. In the
past I’ve never thought of 'yield’ing as an action performed by
blocks, nor as something they’re asked to do; it’s more that they are
executed because they get control because a ‘yield’ has already
happened.

Sorry I don’t understand. Do you mean you don’t want a method with
reserved word name?

What I got from David’s comment, and what the word ‘yield’ suggests to me,
is that a block itself does not yield, but rather a block is executed
because
some other process has opted to yield process control.

For example, when driving in the States (and I imagine there is something
similar elsewhere) there are signs that say, ‘Yield’, meaning one driver
must pause and allow other drivers to proceed. The pausing driver
is the one processing the ‘yield’ message, rather than those drivers given
the go-ahead.

Just to throw in my opinion: I’m not sure this
is what David was saying, but the use of the
word ‘yield’ was counter-intuitive to me when
I was learning Ruby.

I thought it was used in the sense of “produce” –
yield a result, produce a result. So I expected
to be like a “return” statement. I would have
chosen a word like “invoke” instead.

But I think the rationale is that you "yield"
control to the block you are calling, which
then returns control. So it’s “yield” as in
a multiprocessing context. I would guess that
is how CLU came to use that term, and I guess
Ruby got it from CLU. (I’m only going by
hearsay.)

Hal

···

----- Original Message -----
From: james_b@neurogami.com
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Friday, April 25, 2003 11:08 PM
Subject: Re: block.call vs. yield

Hi,

In a ‘yield’, the block is being yielded to – it is not, itself,
yielding control. Therefore, what you’d really need, to describe a
yield in terms of the block as a receiver, would be something like:

blk.be_yielded_to

which I’m not advocating, of course; it’s just that

blk.yield

suggests that the block is performing an action described as
’yield’ing, which I don’t think it is.

Also, the use of ‘yield’ as shorthand for ‘call with certain
semantics’ (if I’m understanding that correctly) seems very obscure
to me. This would be very hard to explain to someone learning Ruby
(“The block isn’t actually yielding control; the method is called
’yield’ because elsewhere in the language there’s something called
’yield’ that has the same calling semantics…”).

Hmm, understandable. It’s not obscure for me at all though.
Actually, as a Japanese, I don’t use the word “yield” for any other
purpose, so that my feeling is far different from yours.

Anyway, what is your opinion to make them better?

Naming is the key of problem solving. If you choose good name, you
will succeed.

						matz.
···

In message “Re: block.call vs. yield” on 03/04/26, dblack@superlink.net dblack@superlink.net writes:

Hi,

···

In message “Re: block.call vs. yield” on 03/04/27, dblack@superlink.net dblack@superlink.net writes:

I think that if the semantics of yield are to be generalized, they
should be thought of as something other than the semantics of yield.
It seems to me that the situation is somewhat like this:

type 1 semantics                     type 2 semantics

 >         >                          >              >
 >         >                          >              >

methods Proc#call yield Proc#whatever

in which case, yield and Proc#whatever share semantics, but there’s no
reason (except “historical reasons”) to define them as “yield
semantics”.

Iff you can name it a good name.

The name “yield” tells you “how different from #call”. This is
important. Other names (e.g. invoke) tells you the fact it’s
different from #call, but not how.

But there still be possibility for the better name.

						matz.
  				matz.

p.s.
Wish I were born in English speaking country.

That’s OK. Sometimes we wish we were born in a Japanese speaking country
so we could read all those Ruby books & docs you have over there.

Phil

You know, I’ve often thought that Ruby would not be so good if there
were no language barrier: What better motivation for making it
completely understandable and have so few surprises? Names are well
chosen and not just defended in the documentation. Methods do what
you’d expect, so incomplete docs are less of a hindrance than it might
be otherwise.

I find this to hold particularly true in the ruby core, but the dRb
module is similarly elegant, as are others.

Ari

I understand the difference in parameter passing conventions between call
and yield. No problem there. My question is this: How were parameter
passing conventions causing the behavior in the original post?

Because there are 2 differences between #call and #yield : one affect
parameter passing, the other affect the break keyword

···

Sat Jun 23 22:28:52 2001 Yukihiro Matsumoto <matz@ruby-lang.org>

  * eval.c (proc_invoke): Proc#call gives avaules, whereas
    Proc#yield gives mvalues.

Fri Apr 25 02:03:25 2003 Yukihiro Matsumoto <matz@ruby-lang.org>

  * eval.c (proc_invoke): Proc#yield should pass through retry and
    break like keyword yield. [ruby-talk:70034]

Guy Decoux

call_as_block perhaps?? or just call_block ?

Hal

···

----- Original Message -----
From: dblack@superlink.net
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Saturday, April 26, 2003 10:13 AM
Subject: Re: block.call vs. yield

Maybe something like call_with_… or call_as… ? (Not sure what the
… would be.)

The method name :yield was immediately intuitive to me, as was the
concept of “yield semantics”. One thing every Ruby programmer must
learn fairly early is the special treatment of arguments to “yield”.

So yes, the only reason for the name is “historical reasons”, but I
can’t imagine a better name appearing.

If you want to take a step back and look for a unifying concept, which
I applaud, then I think the only choice is to abolish “yield
semantics”. The splat (*) operator allows you to achieve the same
result anyway - when you want to.

hash.each do |o|
# Array === o
end

is annoying to some people. They would rather have an error (wrong
number of parameters) than an unexpected value being assigned to the
parameter, and I sympathise. After all…

hash.each do |*o|
# Array === o
end

applies, so why not force intentions to be explicit?

I’m happy to keep “yield” the way it is.

Gavin

···

On Sunday, April 27, 2003, 1:13:40 AM, dblack wrote:

I think that if the semantics of yield are to be generalized, they
should be thought of as something other than the semantics of yield.
It seems to me that the situation is somewhat like this:

 type 1 semantics                     type 2 semantics

  >         >                          >              >
  >         >                          >              >

methods Proc#call yield Proc#whatever

in which case, yield and Proc#whatever share semantics, but there’s no
reason (except “historical reasons”) to define them as “yield
semantics”.