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 Ruby-
puts arr.map { ... }
equalsputs(arr.map { ... })
, but -
puts 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