Project

General

Profile

Actions

Feature #8956

closed

Allow hash members delimited by \n inside of {}

Added by adamdunson (Adam Dunson) over 10 years ago. Updated over 9 years ago.

Status:
Rejected
Assignee:
-
Target version:
-
[ruby-core:57396]

Description

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.


Files

fix-hash-delims.patch (1.37 KB) fix-hash-delims.patch adamdunson (Adam Dunson), 09/26/2013 11:54 PM
hash-test.rb (1.05 KB) hash-test.rb adamdunson (Adam Dunson), 09/26/2013 11:54 PM
add-array-support.patch (2.6 KB) add-array-support.patch adamdunson (Adam Dunson), 10/01/2013 05:53 AM
add-method-arg-support.patch (2.48 KB) add-method-arg-support.patch adamdunson (Adam Dunson), 10/02/2013 04:05 AM
add-method-arg-support-FIXED.patch (2.32 KB) add-method-arg-support-FIXED.patch adamdunson (Adam Dunson), 10/02/2013 04:47 AM
no-comma-tests.patch (2.38 KB) no-comma-tests.patch adamdunson (Adam Dunson), 10/12/2013 12:16 AM
comic-pet-desktop-very-happy-cat.jpg (457 KB) comic-pet-desktop-very-happy-cat.jpg Happy Cat timrosenblatt (Tim Rosenblatt), 11/22/2013 05:55 AM

Updated by adamdunson (Adam Dunson) over 10 years ago

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'
  }
}

Updated by nobu (Nobuyoshi Nakada) over 10 years ago

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 */
 
 assoc_seperator	: '\n'
+		    {
+			command_start = FALSE;
+		    }
 		| ','
 		;

Updated by alexeymuranov (Alexey Muranov) over 10 years ago

Same about arrays, i guess? :)

Updated by sawa (Tsuyoshi Sawada) over 10 years ago

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}

Updated by adamdunson (Adam Dunson) over 10 years 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.

Updated by adamdunson (Adam Dunson) over 10 years ago

I've attached a patch for array support (only between square brackets). I've also renamed the assoc_seperator rule to be nl_or_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'
  }
]

Updated by adamdunson (Adam Dunson) over 10 years ago

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")

Updated by adamdunson (Adam Dunson) over 10 years ago

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

Updated by adamdunson (Adam Dunson) over 10 years ago

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

Updated by sawa (Tsuyoshi Sawada) over 10 years ago

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.

Updated by sawa (Tsuyoshi Sawada) over 10 years ago

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| ...}

Updated by adamdunson (Adam Dunson) over 10 years ago

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).

Updated by sawa (Tsuyoshi Sawada) over 10 years ago

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.

Updated by adamdunson (Adam Dunson) over 10 years ago

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).

Updated by adamdunson (Adam Dunson) over 10 years ago

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

Updated by timrosenblatt (Tim Rosenblatt) over 10 years ago

bump? This looks helpful.

Updated by nobu (Nobuyoshi Nakada) almost 10 years ago

  • Description updated (diff)
  • Status changed from Open to Rejected

It seems this issue has diverged so far from the original.
I reject it for now.

Updated by alexeymuranov (Alexey Muranov) over 9 years ago

I have proposed another version: #10528.

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0