Forum: Ruby yield vs. return

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
klochner (Guest)
on 2009-01-28 22:11
(Received via mailing list)
I couldn't find any meaty discussions on this topic, so maybe it's
worth a post.

Does it make sense to use yield at the end of a function, where you're
essentially
using yield to replace a return value?  For example:

def returnfoo
  return foo
end

vs.

def yieldfoo
  yield foo
end

I see a lot of ruby programmers doing the latter, but consider the
former to
be more straightforward.  There are a lot of cases where yielding is
more elegant
than return, but I don't consider this to be one of them.  Anyone care
to weigh in?
Stefano C. (Guest)
on 2009-01-28 22:24
(Received via mailing list)
Alle mercoledì 28 gennaio 2009, klochner ha scritto:
>
> than return, but I don't consider this to be one of them.  Anyone care
> to weigh in?

yield and return do completely different things, and you can't use one
in
place of the other. return tells ruby to stop executing the method and
return
its argument to the caller. yield tells ruby to call the block passed to
the
method, giving it its argument. yield will produce an error if the
method
wasn't called with a block:

def test_yield
  yield 43
end
test_yield # notice that no block was passed to the method
=> LocalJumpError: no block given

In ruby, there's no need to put a return at the end of a method, as the
method
will always return the value of the last expression. This means that a
method
defined this way:

def test_return
  return 4
end

will give exactly the same result as a method defined this way:

def test_no_return
  4
end

Can you give an example of a situation where you think yield is used in
place
of return? This way, we'll be able to understand better what you're
referring
to and make more useful comments.

Stefano
klochner (Guest)
on 2009-01-28 22:40
(Received via mailing list)
On Jan 28, 3:21 pm, Stefano C. <stefano.cro...@ali
> Can you give an example of a situation where you think yield is used in place
> of return? This way, we'll be able to understand better what you're referring
> to and make more useful comments.
>
> Stefano

The calling code would need to be modified to work with yield vs.
return.

Here's a slightly different example, because I see this a lot with
multivariate return values:

##return style, with calling code below
def returnfoo
  return foo1,foo2
end
a,b = returnfoo
puts a; puts b

 vs.

##yield style, with calling code below
def yieldfoo
  yield foo1, foo2
end
yieldfoo {|a,b| puts a; puts b }


What I'm getting at is that I see ruby programmers use yield to
essentially return values to the caller, the distinction being whether
the block is executed by the caller or by the method (returnfoo/
yieldfoo).  It could be done either way because no operations are
performed by the method after the yield.
F. Senault (Guest)
on 2009-01-28 23:06
(Received via mailing list)
Le 28 janvier 2009 à 21:09, klochner a écrit :

> I see a lot of ruby programmers doing the latter, but consider the
> former to be more straightforward.  There are a lot of cases where
> yielding is more elegant than return, but I don't consider this to
> be one of them.  Anyone care to weigh in?

Depends on what you do with it.  I kinda like to use yield in "builder"
statements where the code will we nested.

For instance, something like (completely random example) :

box.contents do |c|
  c.title = "Blah"
  c.font = "Courier"
  c.color = "Blue"
  c.para do |t|
    t.text = "This is blahblah"
    t.color = "Black"
  end
end

While you could do something like :

c = box.contents
c.title = "Blah"
c.font = "Courier"
c.color = "Blue"
t = c.para
t.text = "This is blahblah"
t.color = "Black"

(The code behind the 'para' method would probably just be 'yield @para'
or 'yield Para.new(self)'.)

The best (IMHO) is, of course, the freedom of :

def funcfoo
  yield foo if block_given?
  foo
end

Where you can nest or assign.

Fred
klochner (Guest)
on 2009-01-28 23:25
(Received via mailing list)
On Jan 28, 4:04 pm, "F. Senault" <removed_email_address@domain.invalid> wrote:
> The best (IMHO) is, of course, the freedom of :
>
> def funcfoo
>   yield foo if block_given?
>   foo
> end


thanks Fred, this sounds sane to me.
Robert K. (Guest)
on 2009-01-29 10:34
(Received via mailing list)
2009/1/28 klochner <removed_email_address@domain.invalid>
>
>  vs.
> the block is executed by the caller or by the method (returnfoo/
> yieldfoo).  It could be done either way because no operations are
> performed by the method after the yield.

IMHO that would be a bad use case for /yield/. The power of /yield/
comes from the fact that the method is in control _when_ and _how
often_ it invokes /yield/ and _what_ it passes on.  Basically your
block is an anonymous callback function.  For methods that simply do a
computation that does not need adjustment by custom code (the
callback) using /return/ is the most appropriate method.

Since with /yield/ the method is in control another typical idiom is
safe cleanup:

def x
  yield 123
ensure
  cleanup
end

File.open with block works that way.

Kind regards

robert
This topic is locked and can not be replied to.