Feature #8956

Allow hash members delimited by \n inside of {}

Added by Adam Dunson 7 months ago. Updated 5 months ago.

[ruby-core:57396]
Status:Open
Priority:Normal
Assignee:-
Category:core
Target version:-

Description

=begin
Currently, hashes require members to be delimited by commas ((({,}))), even inside curly braces. E.g.,

some_hash = {
:foo => 'bar',
:bar => 'foo',
:baz => {
:qux => 'quux',
:corge => 'grault'
}
}

In my opinion, these commas add nothing of value to this particular example since, visually, the members are already delimited by a newline ((({\n}))). Additionally, missing a comma between members results in (({syntax error, unexpected tSYMBEG, expecting '}'})).

I propose we make these commas optional, such that the following syntax would be possible:

some_hash = {
:foo => 'bar'
:bar => 'foo'
:baz => {
:qux => 'quux'
:corge => 'grault'
}
}

This change would not affect existing hashes. Developers would be able to mix and match the old and new syntaxes as such:

some_hash = {
:foo => 'bar'
:bar => 'foo'
:baz => {
:foo => 'bar' + 'baz'
:bar => 'foo', :qux => 'quux'
:corge => 'grault'
}
}

This change would also reduce the occurrence of syntax errors in cases where the developer temporarily replaces a value in the hash, e.g.,

some_hash = {
:this => 'that',
:foo => 'not bar'#'bar',
:those => 'the other'
}

Finally, this change would only affect hashes inside curly braces (for hopefully obvious reasons).

I have attached a diff of my suggested changes along with a script to test a variety of use cases. I also have an open pull request on GitHub: ((URL:https://github.com/ruby/ruby/pull/402))

Please let me know if there's anything I've missed or that needs clarification.
=end

fix-hash-delims.patch Magnifier (1.37 KB) Adam Dunson, 09/26/2013 11:54 PM

hash-test.rb Magnifier (1.05 KB) Adam Dunson, 09/26/2013 11:54 PM

add-array-support.patch Magnifier (2.6 KB) Adam Dunson, 10/01/2013 05:53 AM

add-method-arg-support.patch Magnifier (2.48 KB) Adam Dunson, 10/02/2013 04:05 AM

add-method-arg-support-FIXED.patch Magnifier (2.32 KB) Adam Dunson, 10/02/2013 04:47 AM

no-comma-tests.patch Magnifier (2.38 KB) Adam Dunson, 10/12/2013 12:16 AM

comic-pet-desktop-very-happy-cat.jpg - Happy Cat (457 KB) Tim Rosenblatt, 11/22/2013 05:55 AM

History

#1 Updated by Adam Dunson 7 months ago

=begin
I feel the need to mention that at this time, my changes do not include Ruby 1.9 style symbol hashes. These still require commas, e.g.,

some_hash = {
foo: 'bar',
bar: 'foo',
baz: {
qux: 'quux',
corge: 'grault'
}
}
=end

#2 Updated by Nobuyoshi Nakada 7 months ago

=begin
Additional patch for labeled assocs.

diff --git a/parse.y b/parse.y
index b0a7cc4..63b4334 100644
--- a/parse.y
+++ b/parse.y
@@ -5013,4 +5013,7 @@ trailer : /* none */

assocseperator : '\n'
+ {
+ command
start = FALSE;
+ }
| ','
;
=end

#3 Updated by Alexey Muranov 7 months ago

Same about arrays, i guess? :)

#4 Updated by Tsuyoshi Sawada 7 months ago

=begin
If this proposal is going to be considered, then I think it should not be just for hashes, but also for arrays, and for arguments passed to a method.

[
   :foo
   :bar
]

foo(
   "arg1"
   "arg2"
)

Also note that, since "\n" should be replacable by ";", the proposal would mean the following is allowed:

{:foo => 1; :bar => 2}

=end

#5 Updated by Adam Dunson 7 months ago

Thanks for the patch, nobu. That was easier than I thought it would be; I was looking in the wrong place entirely.

sawa (Tsuyoshi Sawada) wrote:

[...] I think it should not be just for hashes, but also for arrays, and for arguments passed to a method.

I agree. Hashes were the easiest to tackle, but I have also been working on a solution for arrays and arguments. I'm definitely open to suggestions if anyone figures it out before I do.

sawa (Tsuyoshi Sawada) wrote:

Also note that, since "\n" should be replacable by ";", the proposal would mean the following is allowed:

{:foo => 1; :bar => 2}

Is this a desired effect? My current patch does not account for this, but it shouldn't be difficult to add support for it.

#6 Updated by Adam Dunson 7 months ago

=begin
I've attached a patch for array support (only between square brackets). I've also renamed the (({assocseperator})) rule to be (({nlor_comma})) to make it a little more generic.

This allows for syntax similar to hashes (here's a rather complex example):

some_array = [
:foo
:bar
[
'baz'
:qux
]
{
:quux => 'grault'
'garply' => [
'waldo' => :fred
]
:plugh => 'xyzzy'
}
]

=end

#7 Updated by Adam Dunson 7 months ago

=begin
Adding a patch for method argument support. For example, this allows the following syntaxes:

Hash[
:foo, 'bar'
:baz, 'qux'
]

which becomes (({{ :foo => "bar", :baz => "qux" }})), as well as

puts("this is line one"
"this is line two"
"this is line three")
=end

#8 Updated by Adam Dunson 7 months ago

Sorry, the previous patch was incorrect (add-method-arg-support.patch). Please use the attached version instead.

#9 Updated by Adam Dunson 7 months ago

=begin
I should also mention that this patch does not apply to method definitions, so these still require commas (at least, for now):

def some_method(foo,
bar,
baz)
# do stuff
end
=end

#10 Updated by Tsuyoshi Sawada 7 months ago

=begin
Another case where similar syntax might be relevant is | | inside a block. Whether you want to do this:

{|
foo
bar
baz
| ....}

should go together with whether arguments in method definition can be written as:

def foo(
  foo
  bar = some_complicated_expression_as_default_value
  baz = maybe_another_complicated_default_value
)... end

The latter is useful if you want to put some complicated expression as default value. Usefulness of the former would depend on whether default value would be allowed for block variables.

=end

#11 Updated by Tsuyoshi Sawada 7 months ago

=begin
I also thought that maybe you can go one step further and allow any sequence of white characters as delimiters when the parentheses/braces/brackets/pipes are not omitted:

foo(:foo :bar :baz)
{foo: "bar baz: "qux"}
[:foo :bar :baz]
foo{|foo bar baz| ...}

=end

#12 Updated by Adam Dunson 6 months ago

=begin

Hi sawa,

((Another case where similar syntax might be relevant is | | inside a block. ... should go together with ... arguments in method definition))

I agree. Arguments in method definitions have been on my to-do list — I haven't had much time lately to look at this, but good call on allowing newlines inside vertical bars in a block.

((I also thought that maybe you can go one step further and allow any sequence of white characters as delimiters when the parentheses/braces/brackets/pipes are not omitted))

I like the idea, but this one might be too ambitious. The problem that I see is that it introduces ambiguity when passing a method as an argument, e.g.,

def foo(a, b = 0, c = 0)
puts a + b + c
end

def bar(a = 0)
a + 1
end

foo(bar 1 2)

In this instance, it is difficult to tell whether ((%foo%)) is being called with three arguments (((%bar%)), ((%1%)), and ((%2%))) or with two arguments (((%bar(1)%)) and ((%2%))).
=end

#13 Updated by Tsuyoshi Sawada 6 months ago

=begin
adamdunson,

As I wrote already, omission of comma is to be allowed only when the ()[]{}| is not omitted.

foo(bar 1 2)

would be unambiguously foo taking three arguments bar, 1, and 2.
=end

#14 Updated by Adam Dunson 6 months ago

=begin
sawa,

Could you elaborate? I still find that expression to be ambiguous. Here's another example that works with ruby 2.0.0-p247:

def foo(a, b = 0, c = 0)
a + b + c
end

def bar(a = 1, b = 0)
a + b
end

puts foo(bar 1, 2) # outputs 3
puts foo(bar, 1, 2) # outputs 4

If spaces and commas were made to be interchangeable inside parentheses, then the above two calls to ((%foo%)) would be equivalent (which they are not).
=end

#15 Updated by Adam Dunson 6 months ago

Adding another patch with tests for no-comma hashes, arrays, and method arguments.

#16 Updated by Tim Rosenblatt 6 months ago

bump? This looks helpful.

#17 Updated by Tim Rosenblatt 5 months ago

=begin
Bump again. Can we get a thumbs up or down on this?

As a gift, here is a picture of a very happy cat. http://www.freefever.com/stock/comic-pet-desktop-very-happy-cat.jpg

((URL:http://www.freefever.com/stock/comic-pet-desktop-very-happy-cat.jpg))

=end

Also available in: Atom PDF