Issue #11156 has been updated by Faraz Yashar.


I'm trying to demonstrate that the syntax is very confusing and error-prone, especially given that `do ... end` blocks do not behave similarly due to precedence differences.

Consider the `travel_to` time travel method given by Rails' `ActiveSupport::Testing::TimeHelpers`. One would naturally expect that the following two statements would behave equivalently...

~~~ruby
travel_to Time.parse('2015-01-01 00:00:00 +0000') do
 Time.now # => 2015-01-01 00:00:00 +0000
end

travel_to Time.parse('2014-01-01 00:00:00 +0000') {
 Time.now # => 2015-05-16 03:52:24 -0400
}
~~~

...but they don't because of precedence behaviors. To me, these differences violate the principle of least astonishment, and they cause more confusion and open room for errors.

----------------------------------------
Bug #11156: Indeterminate Behavior for Curly-braced Blocks with Function Argument Missing Parenthesis
https://bugs.ruby-lang.org/issues/11156#change-52465

* Author: Faraz Yashar
* Status: Rejected
* Priority: Normal
* Assignee: 
* ruby -v: ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
* Backport: 2.0.0: UNKNOWN, 2.1: UNKNOWN, 2.2: UNKNOWN
----------------------------------------
Given a function that takes an argument and a block, the behavior wildly varies when parenthesis are omitted from the functions argument.

Consider the following function:

~~~ruby
require 'time'

def example(arg)
  puts arg
  if block_given?
    puts yield
  else
    puts "no block"
  end
end
~~~

Each of the following example sets presents one `example` call with parentheses explicitly defined and one whether the parenthesis are omitted.

For most literals (e.g. 1, 'string', true, false, nil, %w[array]), missing parenthesis causes a syntax error.

~~~ruby
example(1) { "block" }
# 1
# block
example 1 { "block" }
# SyntaxError: syntax error, unexpected '{', expecting end-of-input
~~~

Array literals, however, succeed:

~~~ruby
example([1]) { "block" }
# 1
# block
example [1] { "block" }
# 1
# block
~~~

Identifiers are called as methods if parentheses are omitted:

~~~ruby
example(Time) { "block "}
# Time
# block 
example Time { "block" }
# NoMethodError: undefined method `Time' for main:Object

a = 1
example(a) { "block" }
# 1
# block
example a { "block" }
# NoMethodError: undefined method `a' for main:Object
~~~

Object with method calls simply skip the block when no parenthesis are present:

~~~ruby
example(Time.now) { "block" }
# 2015-05-15 18:16:50 -0400
# block
example Time.now { "block" }
# 2015-05-15 18:16:50 -0400
# no block
~~~

Method calls with arguments behave about the same as the above...

~~~ruby
example(Integer(1)) { "block" }
# 1
# block
example Integer(1) { "block" }
# 1
# no block
~~~

...except `Time.parse` gets weird:

~~~ruby
example(Time.parse('2015-01-01 0:00:00+00:00')) { "block" }
# 2015-01-01 00:00:00 +0000
# block
# => nil 
example Time.parse('2015-01-01 0:00:00+00:00') { "block" }
# 0000-01-01 00:00:00 +0000  <---- Year 2000?! 
# no block
# => nil
~~~

The lack of consistency across these use cases is extremely confusing and misleading. I'm of the opinion that parentheses omission should, in all cases, lead to a syntax error.




-- 
https://bugs.ruby-lang.org/