Skip to content

Instantly share code, notes, and snippets.

@syntacticsugar
Created November 20, 2012 19:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save syntacticsugar/4120269 to your computer and use it in GitHub Desktop.
Save syntacticsugar/4120269 to your computer and use it in GitHub Desktop.
Ruby: {} versus 'do/end' syntax

Curly braces vs. do/end in code block syntax

The difference between the two ways of delimiting a code block is a difference in pre- cedence. Look at this example, and you’ll start to see how this plays out:

array = [1,2,3]
  => [1,2,3]
array.map {|n| n * 10 }
  => [10, 20, 30]
array.map do |n| n * 10 end
  => [10, 20, 30]
puts array.map {|n| n * 10 }
  10
  20
  30
=> nil
puts array.map do |n| n * 10 end =>#<Enumerable::Enumerator:0x3ab664>

The map method works through an array one item at a time, calling the code block once for each item and creating a new array consisting of the results of all of those calls to the block. Mapping our [1,2,3] array through a block that multiplies each item by 10 results in the new array [10,20,30]. Furthermore, for a simple map opera- tion, it doesn’t matter whether we use curly braces B or do/end C. The results are the same.

But look at what happens when we use the outcome of the map operation as an argument to puts. The curly-brace version prints out the [10,20,30] array (one item per line, in keeping with how puts handles arrays) D. But the do/end version returns

B C D E 166 CHAPTER 6 Control-flow techniques 6.3.5 an enumerator—which is precisely what map does when it’s called with no code block E. (You’ll learn more about enumerators in chapter 10. The relevant point here is that the two block syntaxes produce different results.) The reason is that the precedence is different. The first puts statement is inter- preted like this: puts(array.map {|n| n * 10 |) The second is interpreted like this: puts(array.map) do |n| n * 10 end In the second case, the code block is interpreted as being part of the call to puts, not the call to map. And if you call puts with a block, it ignores the block. So the do/end version is really equivalent to puts array.map And that’s why we get an enumerator.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment