From: Austin Ziegler Date: 2015-05-17T15:42:54-04:00 Subject: [ruby-core:69218] Re: [Ruby trunk - Bug #11156] Indeterminate Behavior for Curly-braced Blocks with Function Argument Missing Parenthesis --001a113a9564d428ca05164c49d8 Content-Type: text/plain; charset=ISO-8859-1 These are well-established rules of precedence for blocks in Ruby for a long time. As a Rubyist for the last thirteen years, changing this would surprise me more. You may as well ask about precedence of mathematical operators in general (because people *do* find that surprising across all languages). If you want to use braces against a function, use parentheses just as if you want to do addition before multiplication. Note that using POLS/POLA in an argument is specious. The measure of surprise is whether Matz is surprised by the behaviour. *Everyone* finds Ruby surprising early on for various reasons. -a On Sat, May 16, 2015 at 4:06 AM, wrote: > 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/ > -- Austin Ziegler * halostatue@gmail.com * austin@halostatue.ca http://www.halostatue.ca/ * http://twitter.com/halostatue --001a113a9564d428ca05164c49d8 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable
These are well-established rules of precedence for blocks = in Ruby for a long time. As a Rubyist for the last thirteen years, changing= this would surprise me more. You may as well ask about precedence of mathe= matical operators in general (because people *do* find that surprising acro= ss all languages). If you want to use braces against a function, use parent= heses just as if you want to do addition before multiplication.

Note that using POLS/POLA in an argument is specious. The measure o= f surprise is whether Matz is surprised by the behaviour. *Everyone* finds = Ruby surprising early on for various reasons.

-a

On Sat,= May 16, 2015 at 4:06 AM, <faraz.yashar@gmail.com> wro= te:
Issue #11156 has been updated by Fara= z Yashar.


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

Consider the `travel_to` time travel method given by Rails' `ActiveSupp= ort::Testing::TimeHelpers`. One would naturally expect that the following t= wo statements would behave equivalently...

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

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

...but they don't because of precedence behaviors. To me, these differe= nces violate the principle of least astonishment, and they cause more confu= sion and open room for errors.

----------------------------------------
Bug #11156: Indeterminate Behavior for Curly-braced Blocks with Function Ar= gument 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 va= ries 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 parenth= eses 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 =3D 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 pres= ent:

~~~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
# =3D> nil
example Time.parse('2015-01-01 0:00:00+00:00') { "block" = }
# 0000-01-01 00:00:00 +0000  <---- Year 2000?!
# no block
# =3D> nil
~~~

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




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



--
=
--001a113a9564d428ca05164c49d8--