Hashes don't allow preceding commas by design?

This is the output from irb that shows ruby 1.9.1 doesn't like hash entries to be preceded by a comma, only ended by one:

myhash3 = {
:first => "first",
:second => "second"
}
{:first=>"first", :second=>"second"}

myhash3 = {
:first => "first"
, :second => "second"
}
SyntaxError: (irb):48: syntax error, unexpected ',', expecting '}'
, :second => "second"
  ^
  from /Library/Frameworks/Ruby.framework/Programs/irb:12:in `<main>'

I prefer to put my comma's at the front of a line as it makes a line easier and quicker to comment out (1 vs 2 lines and a lot less fiddly). Is this only-commas-at-the-end by design or did I miss something? I've tested this with a script and with irb.

Quick addendum, thought I'd test this for arrays too, and it's the same.

myarr = [ 1, 2, 3]
[1, 2, 3]

myarr2 = [
1,
2,
3
]
[1, 2, 3]

myarr3 = [
1
,2
,3
]
SyntaxError: (irb):58: syntax error, unexpected ',', expecting ']'
  from /Library/Frameworks/Ruby.framework/Programs/irb:12:in `<main>'

Iain

I don't know the reasoning for that decision [quirk?] but commas at the end
of lines should not hinder commenting out lines

a = {
  1 => 2 ,
  3 => 4 ,
  5 => 6 ,
}
a # => {5=>6, 1=>2, 3=>4}

a = {
  # 1 => 2 ,
  3 => 4 ,
  5 => 6 ,
}
a # => {5=>6, 3=>4}

a = {
  1 => 2 ,
  # 3 => 4 ,
  5 => 6 ,
}
a # => {5=>6, 1=>2}

a = {
  1 => 2 ,
  3 => 4 ,
  # 5 => 6 ,
}
a # => {1=>2, 3=>4}

···

On Wed, Jul 7, 2010 at 3:23 AM, Iain Barnett <iainspeed@gmail.com> wrote:

This is the output from irb that shows ruby 1.9.1 doesn't like hash entries
to be preceded by a comma, only ended by one:

myhash3 = {
:first => "first",
:second => "second"
}
{:first=>"first", :second=>"second"}

myhash3 = {
:first => "first"
, :second => "second"
}
SyntaxError: (irb):48: syntax error, unexpected ',', expecting '}'
, :second => "second"
^
       from /Library/Frameworks/Ruby.framework/Programs/irb:12:in `<main>'

I prefer to put my comma's at the front of a line as it makes a line easier
and quicker to comment out (1 vs 2 lines and a lot less fiddly). Is this
only-commas-at-the-end by design or did I miss something? I've tested this
with a script and with irb.

Quick addendum, thought I'd test this for arrays too, and it's the same.

myarr = [ 1, 2, 3]
[1, 2, 3]

myarr2 = [
1,
2,
3
]
[1, 2, 3]

myarr3 = [
1
,2
,3
]
SyntaxError: (irb):58: syntax error, unexpected ',', expecting ']'
       from /Library/Frameworks/Ruby.framework/Programs/irb:12:in `<main>'

Iain

It's not hashes it is the parser in general. When it parses a line (up to
the newline) if the line appears compete then the parser expects a new
statement on the next line. So with

1: => a, b = 1,
2: => 2

Line 1 is incomplete so the parser treats line 2 as a continuation of line
1. But with

1: => a, b = 1
2: => ,2

Line 1 is complete in that the line contains a valid Ruby statement so the
parser expects the next line to be a new statement, line 2 is in error
because no valid Ruby statements start with a comma.

This is what you are seeing in your examples.

Iain Barnett wrote:

myhash3 = {
:first => "first"
, :second => "second"
}

It is possible if you force the Ruby Interpreter to look at that line to
be incomplete:

myhash3 = {
  :first => "first" \
  , :second => "second"
}

But I don't necessarily like this, since the backslash looks so
misplaced in a nice language like Ruby...

Marvin

···

--
Posted via http://www.ruby-forum.com/.

If you're allowed a comma for the last line then it's not a problem. Thanks for letting me know, too many years working with languages that don't like that meant I didn't try it :slight_smile:

Iain

···

On 7 Jul 2010, at 09:33, Josh Cheek wrote:

I don't know the reasoning for that decision [quirk?] but commas at the end
of lines should not hinder commenting out lines

a = {
1 => 2 ,
3 => 4 ,
5 => 6 ,
}
a # => {5=>6, 1=>2, 3=>4}

a = {
# 1 => 2 ,
3 => 4 ,
5 => 6 ,
}
a # => {5=>6, 3=>4}

a = {
1 => 2 ,
# 3 => 4 ,
5 => 6 ,
}
a # => {5=>6, 1=>2}

a = {
1 => 2 ,
3 => 4 ,
# 5 => 6 ,
}
a # => {1=>2, 3=>4}

Thanks, I'm still getting used to Ruby's ways.

Iain

···

On 7 Jul 2010, at 09:36, Peter Hickman wrote:

It's not hashes it is the parser in general. When it parses a line (up to
the newline) if the line appears compete then the parser expects a new
statement on the next line. So with

1: => a, b = 1,
2: => 2

Line 1 is incomplete so the parser treats line 2 as a continuation of line
1. But with

1: => a, b = 1
2: => ,2

Line 1 is complete in that the line contains a valid Ruby statement so the
parser expects the next line to be a new statement, line 2 is in error
because no valid Ruby statements start with a comma.

This is what you are seeing in your examples.

I think that I feel this should not be the case, because I feel that the
interpreter should not consider any of it complete since it is inside of an
incomplete hash.

However, these examples have me so unsure of what is supposed to be what
that I can't construct a response illustrating this. Please double check
these examples.

···

On Wed, Jul 7, 2010 at 3:36 AM, Peter Hickman < peterhickman386@googlemail.com> wrote:

It's not hashes it is the parser in general. When it parses a line (up to
the newline) if the line appears compete then the parser expects a new
statement on the next line. So with

1: => a, b = 1,
2: => 2

Line 1 is incomplete so the parser treats line 2 as a continuation of line
1. But with

1: => a, b = 1
2: => ,2

Line 1 is complete in that the line contains a valid Ruby statement so the
parser expects the next line to be a new statement, line 2 is in error
because no valid Ruby statements start with a comma.

This is what you are seeing in your examples.

The structure of a has assignment could be either:

1: => a = { :fred => 42 }

or

1: => a =
2: => {
3: => :fred => 42
4: => }

Here line 1 is incomplete so it treats line 2 as a continuation. Line 2 says
'here is the start of a hash' and is also incomplete. So line 3 is seen as a
continuation of line 2.
Line 3 is complete in that it is a valid statement that can be found inside
a hash declaration but the parser is still looking for the closing } to
match the opening { from line 2. So although line 3 is a complete valid
statement it is part of lines 1 and 2 which is an incomplete hash
declaration.

So line 4 is taken to be a continuation of lines 1, 2 and 3 and finally
completes the statement that started on line 1.

···

On 7 July 2010 10:15, Josh Cheek <josh.cheek@gmail.com> wrote:

I think that I feel this should not be the case, because I feel that the
interpreter should not consider any of it complete since it is inside of an
incomplete hash.

However, these examples have me so unsure of what is supposed to be what
that I can't construct a response illustrating this. Please double check
these examples.

> However, these examples have me so unsure of what is supposed to be what
> that I can't construct a response illustrating this. Please double check
> these examples.
>

1: => a = { :fred => 42 }

Okay, I found the point of confusion. The confusion is that "1: => " is not
trying to create a hash table, but is rather a way of identifying line
numbers. I was opening irb in all my different rubies seeing if it would
accept
{ 1: => a = { :fred => 42 } }

1: => a =
2: => {
3: => :fred => 42
4: => }

Here line 1 is incomplete so it treats line 2 as a continuation. Line 2
says
'here is the start of a hash' and is also incomplete. So line 3 is seen as
a
continuation of line 2.
Line 3 is complete in that it is a valid statement that can be found inside
a hash declaration but the parser is still looking for the closing } to
match the opening { from line 2. So although line 3 is a complete valid
statement it is part of lines 1 and 2 which is an incomplete hash
declaration.

So line 4 is taken to be a continuation of lines 1, 2 and 3 and finally
completes the statement that started on line 1.

Your explanation implies to me that the OP's desired use case is valid. If
"line 4 is taken to be a continuation of lines 1, 2 and 3" then how come
line 4 can't be ",:jim => 43"

···

On Wed, Jul 7, 2010 at 4:36 AM, Peter Hickman < peterhickman386@googlemail.com> wrote:

On 7 July 2010 10:15, Josh Cheek <josh.cheek@gmail.com> wrote:

I can understand the confusion but it can be explained like this

"A hash is a '{' followed by a comma separated list of key / value pairs
finished off with a '}'"

So if we read through a couple of examples:

1: {
2: :first => 1,
3: :second => 2
4 }

Line 1 starts the hash declaration, the parser is looking for a key value
pair or a '}'
Line 2 is a key value pair and a comma. The comma tells the parser than it
should expect another key value pair
Line 3 is the next key value pair and does not have a comma. So the parser
has come to the end of the list of key value pairs that makes up a hash and
is therefore expecting a '}'
Line 4 is the expected '}' and the hash declaration is complete

Now try this:

1: {
2: :first => 1
3: :second => 2
4 }

Again line 1 starts the hash declaration, the parser is looking for a key
value pair or a '}'
Line 2 is a key value pair and does not have a comma. So the parser believes
that it has come to the end of the list of key value pairs and is therefore
expecting a '}'
Line 3 is a key value pair but the parser is expecting a '}' so this is an
error. The compiler spits out the error.
We never get to line 4.

This goes back to what I said about 'incomplete' lines ":first => 1," is
incomplete because the comma makes the parser think that another key value
pair should be expected because it is parsing a hash declaration. So line 3
is treated as a continuation of line 2 and all is well with the world.

However ":first => 1" is a complete line, the absence of a comma does not
set the parser up to expect another key value pair. So when it encounters
":second => 2" it goes "what is going on here, according to my rules the
next thing I should find is an '}'".

It is not to say that the parser couldn't handle this situation or at least
handle a line like ", :second => 2" (with a leading comma) but it does not
as currently implemented.

Some languages use things like a ';' as an explicit end of statement marker
to help the parser. Ruby does not do this and treats the end of a line to be
the implicit end of statement marker unless the statement appears to be
incomplete. What constitutes incomplete depends on what it is parsing, a
hash, a list, an if statement etc.

···

On 7 July 2010 11:02, Josh Cheek <josh.cheek@gmail.com> wrote:

> So line 4 is taken to be a continuation of lines 1, 2 and 3 and finally
> completes the statement that started on line 1.
>

Your explanation implies to me that the OP's desired use case is valid. If
"line 4 is taken to be a continuation of lines 1, 2 and 3" then how come
line 4 can't be ",:jim => 43"

Peter Hickman wrote:

So if we read through a couple of examples:

1: {
2: :first => 1,
3: :second => 2
4 }

But I think the question is why the following isn't allowed:

{
:first => 1

···

,
:second => 2
}

I'd say it's just a quirk of the parser, and/or the fact that the
language doesn't have a formal grammar.
--
Posted via http://www.ruby-forum.com/.

But I think the question is why the following isn't allowed:

{
:first => 1
,
:second => 2
}

Look at this in irb might help us understand it

irb(main):001:0> a = {
irb(main):002:1* :first => 1
irb(main):003:1> ,
irb(main):004:1* :second => 2
irb(main):005:1> }
SyntaxError: compile error
(irb):3: syntax error, unexpected ',', expecting '}'
from (irb):4

The irb prompt ends with a > if it is looking for a new line. When it ends
with a *, as in line 2, it means that the parser thinks that the pervious
line is incomplete and that line 2 is a continuation of line 1.

However after entering line 2 the prompt returns to a >. This means that the
parser thinks that line 2 was complete and there is nothing more to be read.
Compare it to this

irb(main):001:0> a = {
irb(main):002:1* :first => 1,
irb(main):003:1* :second => 2
irb(main):004:1> }

The comma is on the end line 2 and the prompt for line 3 ends with a *. The
parser shows us that it does not consider line 2 to be complete and that
line 3 will be treated as a continuation of line 2.

A line ending with a comma tells the parser that (in the cases where a comma
is used such as hashes, lists or functions) that the statement is incomplete
and to treat the next line as a continuation of this line.

I'm not saying that the parser could not be written to handle the case you
present it is just that with the present design that uses the end of line as
an implicit end of statement marker the behaviour you are seeing is the
expected behaviour.

The same thing happens with the if statement

if some_test ||
another_test

will parse the same as

if some_test || another_test

but

if some_test

another_test

is something else entirely.

"if some_test" on a line by itself is a complete statement so the parser is
expecting the statement block (or a "then") but "if some_test ||" is
incomplete as || needs something on the right hand side so it treats the
next line as a continuation of the current one.

···

On 7 July 2010 13:43, Brian Candler <b.candler@pobox.com> wrote:
from :0