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 Ruby Blocks Blocks Practice Build a Monster Class: Part 4

Anthony Baird
Anthony Baird
15,477 Points

Why do you use (&block)

Why do you use (&block) in your methods, but don't use block.call to call the block. You are using yield.

3 Answers

You are right, Anthony. If you try this in an irb shell or put it in a .rb file and call it from the CLI:

def foo(n, &block) yield end

foo (1) { |n| n + 1 }

...you will get a NoMethodError: undefined method `+' for nil:NilClass

But if you change foo to this:

def foo(n, &block) block.call(n) end

or this:

def foo(n, &block) yield n end

...in either form the program will return 2.

After reading your reply, I looked at your original question again and I think on my first attempt I may have misunderstood what you were trying to find out. It seems you have a good grasp of how to use block.call and yield -- maybe you were just wondering why the instructor used &block for passing the block. You can actually put anything you want in that argument placeholder: &block, &clock, &glock, &bar...as long as it begins with an ampersand (&) and follows the ruby variable name snake-case convention (lowercase word or words separated by an underscore "_"). But in all the examples I've ever seen in several Ruby books, the convention has always been to use the term &block because it makes it clear to anyone reading the code that a block is expected. I think the instructor is just demonstrating different options for passing blocks to methods. As I learn other languages like Javascript and Python, I'm finding that developers/engineers who come to Ruby from another language get frustrated by how many different ways you can do something in Ruby.

To be honest, I haven't done that particular course module yet, so I haven't seen the entire code of the hide example. But I've been programming in Ruby for about 9 months before I started using Treehouse, and while I'm no expert, I seek out opportunities to try to help others starting out with Ruby. I hope my explanation can be applied to the code in your specific module.

Okay, this might be an oversimplification, but think of it this way:

  • If your block does NOT require any inputs that go between pipes, { puts ""foo" } then yield is sufficient.
  • However, if your block requires inputs, { |n| puts n } then you need block.call(n) to "call" it.

This is a simplistic explanation, but I wanted to keep it concise for the purposes of this Forum.

Anthony Baird
Anthony Baird
15,477 Points

Can't you do the same thing with yield? if you use: yield var if block_given?, like so, then you can pass an argument to var using { |n| puts n}. At least this is what my understanding was.

If you review the video though, he defines an argument (&block) in the hide method, but uses: yield self if block_given? in order to call the block. (below he uses { |m| puts m.actions.inspect } in order to pass an argument to the yield self variable. He doesn't use block.call() to call the method. This is confusing me because I'm not sure if there is actually a purpose for &block argument in his code or not.

Is there actually a purpose for him defining the (&block) argument in the hide method used in the video?

Anthony Baird
Anthony Baird
15,477 Points

Sam, thanks for time you've taken to respond! This is really well explained and exactly what I was trying to figure out. I understand that there can be many ways of accomplishing the same task and can see how that can be confusing/frustrating, but it is the fact that &Block was merrily being used as a placeholder for passing the block and that it is the ampersand that distinguishes the argument as a block argument that I wasn't sure about. I'm new to programming and Ruby is my first attempt at learning a language and I've been finding it confusing when examples are given that try to use "friendly" variable names that match the different classes, methods, and programming terminology. It makes it difficult to trace back how the logic actually works when variables are called and passed between classes and methods. Thanks for the help.

You're most welcome, Anthony. I'm very glad I was able to help. If you're interested in learning more about Ruby I would recommend two books:

Programming Ruby 1.9 & 2.0: The Pragmatic Programmer's Guide by Dave Thomas. This is a very complete and well written tutorial and reference -- it is knows as the "Ruby Pickaxe". There is an online version at http://ruby-doc.com/docs/ProgrammingRuby/ but I bought a paper copy and it's much easier to follow that way. Just the chapter on Regular Expressions (which are used in just about every software language) alone is extremely instructive.

Learn To Program by Chris Pine is also an excellent book for learning Ruby. There is an online version as well at https://pine.fm/LearnToProgram/