PDA

View Full Version : Ruby's yield: WTF?


chucker
2006-01-29, 09:33
I've been going through this (http://www.math.umd.edu/~dcarrera/ruby/0.3/) Ruby tutorial (again), which, while it has some flaws and things I would starkly disagree with, is still a reasonably good course.

But there's just one thing I don't get, and that's "yield". It's first used in this (http://www.math.umd.edu/~dcarrera/ruby/0.3/chp_04/iterators.html) section, the first example being:

def twice
yield
yield
end

twice { puts "Hello World" }

As much as I understand what it does, why it does it and how it works, I just can't stop thinking how... absurd this is. I mean, here, you have a line of code (twice {..}) that calls up a method, twice. But the method doesn't contain the actual code to wane through, no, it just "yields" the code. Twice. Huh? Isn't that the very opposite way of how any logical person would do it?

It gets really bad, though, when the author gets to this example:

class AddressBook
def each
@persons.each { |p| yield p }
end
end

:err:

As a programmer friend of mine said, "it's like return... but... only not...".

I'm sorry, but this "yield" thing occurs to me as incredibly queer. Am I missing something?

MCQ
2006-01-29, 09:47
So, I've never looked at Ruby before. I also think it's a very strange construct.

ghoti
2006-01-29, 13:34
I haven't used Ruby, but yield struck me as an ingenious construct. Your second example is basically an iterator, going through all the people in the address book, and calling back the function that called it. You can look at it as a different way of doing callbacks, or a way of using function pointers without needing pointers. It just requires a slightly different way of thinking to use, but I think once you get used to it, it gives you a very elegant way of doing some things that otherwise would be much less pretty.

pmazer
2006-01-29, 14:10
I have used Ruby before, a lot, and I can tell you that the "yield thing" or code blocks are quite possibly the best thing about Ruby. It makes Ruby a bit more Lisp-like. You can do things such as:


lineups.delete_if do |lineup|
not (lineup.players.eql?(pair) or lineup.players.eql?(pair.reverse))
end


You can basically pass a custom function to the function, making it much easier to write things. That line before would have taken at least an additional line, and much more custom scripting in Java, and it's easier to read in Ruby, too.

Weirdbro
2006-01-29, 19:39
Well, yield calls the code block you attach to it. So in each, you are giving the array iterator each a codeblock telling it to run the code block attached to AddressBook.each and pass it each item in the array. I'd explain better, but I don't think their really is a good way to explain.

dfj225
2006-01-31, 10:50
I really don't know Ruby at all, but after a quick search and having read what others have posted here, I think I can help :)

It seems to me that in Ruby you are able to send a block of code to a function as a type of argument. The yield statement executes this block. In your print example the block that is being passed is { puts "Hello World"} and each time yield statement executes this block.

As someone who is also not framiliar with Ruby, you are right, it is a rather odd syntax.