yield vs. call? 
Author Message
 yield vs. call?

I'm a bit puzzled whether there is any semantic difference between the
two code fragments, below:

# Example from Programming Ruby
def fibUpTo(max)
  i1, i2 = 1, 1        # parallel assignment
  while i1 <= max
    yield i1
    i1, i2 = i2, i1+i2
  end
end

fibUpTo(1000) { |f| print f, " " }
puts

VS.

# Modified example from Programming Ruby
def fibUpTo(max, blk)
  i1, i2 = 1, 1        # parallel assignment
  while i1 <= max
    blk.call i1
    i1, i2 = i2, i1+i2
  end
end

fibUpTo(1000, proc { |f| print f, " " })
puts

These seem to be equivalent as far as I can tell. Is the original
example just syntactic sugar for the other version, or are there
subtle reasons why a yield statement and magic associated block (I'm
not sure what you call that) is necessary?

Just curious!

Bob Sidebotham



Thu, 22 Apr 2004 06:05:37 GMT  
 yield vs. call?

Quote:

> I'm a bit puzzled whether there is any semantic difference between the
> two code fragments, below:
...
>     yield i1
...
> fibUpTo(1000) { |f| print f, " " }
> VS.
>     blk.call i1
...
> fibUpTo(1000, proc { |f| print f, " " })
> These seem to be equivalent as far as I can tell. Is the original
> example just syntactic sugar for the other version,

AFAIK, the second creates an object (of type Proc), something the first
version doesn't do. I tend to use the
        def fibUpTo( max, &blk )
version to remove the need for the caller to know that its an explicit
Proc object, unless I need several of them.

Quote:
> or are there
> subtle reasons why a yield statement and magic associated block (I'm
> not sure what you call that) is necessary?

It's a) more elegant, b) probably more efficient and c) the "real" way
to do it.
Just like the normal ("real") way to call a method is :
        object.methodname(arguments)
but you can also do dynamic tricks with:
        method = object.method(:methodname)
        method.call( arguments )

--
<[ Kent Dahl ]>================<[ http://www.stud.ntnu.no/~kentda/ ]>
  )____(stud.techn.;ind.?k.data)||(softwareDeveloper.at(Trustix))_(
 /"Opinions expressed are mine and not those of my Employer,      "\
( "the University, my girlfriend, stray cats, banana fruitflies,  " )
 \"nor the frontal lobe of my left cerebral hemisphere.           "/



Thu, 22 Apr 2004 12:36:39 GMT  
 yield vs. call?

Quote:


> > I'm a bit puzzled whether there is any semantic difference between the
> > two code fragments, below:
> ...
> >     yield i1
> ...
> > fibUpTo(1000) { |f| print f, " " }

> > VS.
> AFAIK, the second creates an object (of type Proc), something the first
> version doesn't do.

So a Proc object is a little extra wrapping around a bare block in order
to make the block more generally available? And the method-with-block
syntax plus yield is really intended to make things more efficient by
restricting the ability to call the block to just the invoked method? So
we're really talking the difference between static vs. dynamic blocks?

Quote:
> I tend to use the
>         def fibUpTo( max, &blk )
> version to remove the need for the caller to know that its an explicit
> Proc object, unless I need several of them.

I hadn't understood that section of Programming Ruby. I see now that the
example from PR:

  bStart = JukeboxButton.new("Start") { songList.start }

is exactly the same (I think) as:

  bStart = JukeboxButton.new("Start", proc { songList.start })

but lets you write what (I'm assuming) is a less efficient call using
the same syntax as the more efficient block-only.

And this implies a third variant of the fibonacci function:

  # Another modified example from Programming Ruby
  def fibUpTo(max, &blk)
    i1, i2 = 1, 1        # parallel assignment
    while i1 <= max
      blk.call i1
      i1, i2 = i2, i1+i2
    end
  end

  fibUpTo(1000) { |f| print f, " " }

Assuming that my understanding of all of this is correct, I think it
would make it easier if the documentation (eg. Programming Ruby) could
define yield in terms of call and closure (or at least discuss this). If
it's really the same thing, then it makes it easier (for me, anyway) to
understand flow-of-control, scoping, returning results, parameters,
etc., simply because it makes it less magical.

It's also clear (if all of the above is correct!) that the original
example from PR should be the most efficient implementation of the
three.

Thanks,
Bob



Thu, 22 Apr 2004 07:35:19 GMT  
 yield vs. call?
Hello --

Quote:

> I hadn't understood that section of Programming Ruby. I see now that the
> example from PR:

>   bStart = JukeboxButton.new("Start") { songList.start }

> is exactly the same (I think) as:

>   bStart = JukeboxButton.new("Start", proc { songList.start })

> but lets you write what (I'm assuming) is a less efficient call using
> the same syntax as the more efficient block-only.

The important thing to remember, though, is that you can associate a
non-argument block with any method call.  So if you send a block as a
regular argument, you can still also associate a block:

  def thing(a,b,c)
    puts yield c.call(a, b)
  end

  thing(1,2, proc { |x,y| x + y }) { |n| "result is #{n}" }

  # =>  result is 3

David

--
David Alan Black


Web:  http://pirate.shu.edu/~blackdav



Thu, 22 Apr 2004 20:56:30 GMT  
 yield vs. call?

Quote:

> Hello --



> The important thing to remember, though, is that you can associate a
> non-argument block with any method call.  So if you send a block as a
> regular argument, you can still also associate a block:

>   def thing(a,b,c)
>     puts yield c.call(a, b)
>   end

>   thing(1,2, proc { |x,y| x + y }) { |n| "result is #{n}" }

>   # =>  result is 3

Why is this important? This still seems to be sugar for:

  def thing(a,b,c,d)
    puts d.call(c.call(a, b))
  end

  thing(1,2, proc { |x,y| x + y }, proc { |n| "result is #{n}" })

  # =>  result is 3

Does the first syntax somehow express the _intent_ of the code better?

Help me! I really have not seen the light yet.

Thanks,
Bob

P.S. I saw another post that made a reference to yield picking up blocks
up a level from the current frame. Is that a clue to some essential
behavior I'm missing, or a red herring, or what...?



Fri, 23 Apr 2004 04:11:39 GMT  
 
 [ 5 post ] 

 Relevant Pages 

1. block.call vs. yield

2. Proc.class vs yield

3. Difference between proc.call and yield?

4. "yield called out of block"

5. bug or feature: yield calling method object

6. Call-by-value vs. call-by-need/name

7. Call by reference vs. call by value

8. Call by reference vs. call by value

9. call sync_memory vs call sync_memory()

10. stdcall vs c vs cdecl vs pascal vs whosyerdaddy

11. 68K vs CFM68K vs Tk 8.0.3 vs AppearanceLib vs System 7

12. MASM vs TASM vs VC++ vs DJGPP vs A*^ vs PCC vs DEBUG,, "Hello World!"

 

 
Powered by phpBB® Forum Software