Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Ruby

Jeff Lange
Jeff Lange
8,788 Points

Yield runs a block, but I don't understand what block this yield is running. And more! Come on in if you like to teach!

I understand that "yield" runs a "block" of code sharing the same name as the method containing "yield." However, in this particular code (which allows you to write a speech in lines and then print to the screen) I don't understand what the "def each" method is doing on lines 26-28.

Can someone explain this in detail? And I mean slow: as if I have brain damage. I know this method is making it possible to print each line consecutively, but I have absolutely no clue about how it's doing that.

Relevant questions (mostly center on lines 26-28 near the bottom, the def each method):

  • why is there &block? I don't see a block.call anywhere? (line 26)
  • isn't .each already defined by default in Ruby? Did we redefine it? (lines 26-28)
  • how do the pipes || work? Why did we have to put "line" in the pipes? (lines 26-28)
  • how is yield working properly here if we didn't create a separate block that shares the name of this method? I thought that's how yield worked: it ran the code from a block that shares the name of method yield is in. (lines 26-28)
  • shouldn't it be for each line we "puts" that line rather than yield it? Why did we write the code that prints the speech to the screen down on lines 36-38 instead of including it here?

And finally the code itself:

class Speech
    def initialize 
        print "What is the speech name? "
        @title = gets.chomp 
        @lines = []
        while add_line
            puts "Line added."
        end
    end

    def title 
        @title
    end

    def add_line
        puts "Add a line: (blank line to exit)"
        line = gets.chomp
        if line.length > 0
            @lines.push line 
            return line
        else
            return nil
        end
    end

    def each(&block)
        @lines.each { |line| yield line}
    end

 end


 speech = Speech.new
 puts "#{speech.title.upcase}\n\n"

 speech.each do |line|
    puts "#{line}"
 end

Hopefully there are some natural teachers out here in the forum that love answering questions--I'm certainly full of them! :)

1 Answer

Kang-Kyu Lee
Kang-Kyu Lee
52,045 Points

I'm positive that block.call is the same thing to yield here. And yes, each method of Speech class redefines (overrides) built-in each method. In this case looks like, in order to run the block only for each of @lines of Speech object.

Jeff Lange
Jeff Lange
8,788 Points

Thanks for responding!

I still don't understand why &block had to be put in, as yield never needed &block in the treehouse tutorial videos.

Ok, so you can override Ruby's built-in methods. Interesting!

Any other thoughts from anyone? I still don't really get what's going on with this code.

Kang-Kyu Lee
Kang-Kyu Lee
52,045 Points

Hi Jeff, a block can take parameters. kinda hard to explain. I think there's another person will explain it more comprehensively or you may look up any ruby language books. Putting & to block coverts it into a Proc so it can take Proc instance methods (like call) in the method which receives that. blocks are not objects.