Difference between "{}" & "do...end" in Ruby
TLDR
- In Ruby, blocks in braces,
{ ... }
, bind stronger than indo ... end
do - Rule of thumb
- Use
{ ... }
for single-line blocks do ... end
for multi-liners
- Use
Try Guess the Output
Answers in section “Precedence in Execution”
arr = [1, 2, 3]
a = arr.map { |num| num * 2 }
b = arr.map do
|num| num * 2
end
puts a # => ???
puts b # => ???
arr = [1, 2, 3]
puts arr.map { |num| num * 2 } # => ???
puts arr.map do
|num| num * 2
end # => ???
What is Block in Ruby
In Ruby, a (code) block is a piece of code that takes arguments. A block can NOT “survive” on its own, UNLESS it is attached to methods, or in the form of proc
or lambda
.
# Two ways to wrap a block in Ruby
# They will cause errors if put like these
# 1. { ... }
{ puts 1 } # gets "SyntaxError"
# 2. do ... end
do puts 1 end # gets "SyntaxError"
def some_method
yield
end
# Good; these will not cause SyntaxError
some_method { puts 1 }
proc_print_one = proc { puts 1 }
lambda_print_one = lambda { puts 1 }
Read more about the difference between
proc
andlambda
in my blog post Proc & Lambda in Ruby!
Precedence in Execution
Per documentation in Ruby-Doc.org, { ... }
blocks have priority below all listed operations, but do ... end
blocks have even lower priority.
- No difference in terms of output, as all gets executed before printed
arr = [1, 2, 3]
a = arr.map { |num| num * 2 }
b = arr.map do
|num| num * 2
end
puts a # => [2, 4, 6]
puts b # => [2, 4, 6]
- The following
#map
s are interpreted differently in Rubyputs arr.map { ... }
equalsputs(arr.map { ... })
, butputs arr.map do ... end
are actuallyputs(arr.map) do ... end
arr = [1, 2, 3]
puts arr.map { |num| num * 2 } # prints the following
# 2
# 4
# 6
puts arr.map do
|num| num * 2
end # => #<Enumerator:0x00007fb34d8d40c0>
See Precedence for the comprehensive list of precedence.
References
- Precedence by Ruby-Doc.org