Hashes don't allow preceding commas by design?

I

Iain Barnett

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 =3D {
:first =3D> "first",
:second =3D> "second"
}
{:first=3D>"first", :second=3D>"second"}

myhash3 =3D {
:first =3D> "first"
, :second =3D> "second"
}
SyntaxError: (irb):48: syntax error, unexpected ',', expecting '}'
, :second =3D> "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 =3D [ 1, 2, 3]
[1, 2, 3]

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

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


Iain=
 
J

Josh Cheek

[Note: parts of this message were removed to make it a legal post.]

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

Peter Hickman

[Note: parts of this message were removed to make it a legal post.]

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

Iain Barnett

=20
I don't know the reasoning for that decision [quirk?] but commas at = the end
of lines should not hinder commenting out lines
=20
=20
=20
a =3D {
1 =3D> 2 ,
3 =3D> 4 ,
5 =3D> 6 ,
}
a # =3D> {5=3D>6, 1=3D>2, 3=3D>4}
=20
=20
=20
a =3D {
# 1 =3D> 2 ,
3 =3D> 4 ,
5 =3D> 6 ,
}
a # =3D> {5=3D>6, 3=3D>4}
=20
=20
=20
a =3D {
1 =3D> 2 ,
# 3 =3D> 4 ,
5 =3D> 6 ,
}
a # =3D> {5=3D>6, 1=3D>2}
=20
=20
=20
a =3D {
1 =3D> 2 ,
3 =3D> 4 ,
# 5 =3D> 6 ,
}
a # =3D> {1=3D>2, 3=3D>4}

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

Iain
 
I

Iain Barnett

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.

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

Iain
 
J

Josh Cheek

[Note: parts of this message were removed to make it a legal post.]

On Wed, Jul 7, 2010 at 3:36 AM, Peter Hickman <
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.
 
P

Peter Hickman

[Note: parts of this message were removed to make it a legal post.]

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.

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

Josh Cheek

[Note: parts of this message were removed to make it a legal post.]

On Wed, Jul 7, 2010 at 4:36 AM, Peter Hickman <
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"
 
M

Marvin Gülker

Iain said:
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
 
P

Peter Hickman

[Note: parts of this message were removed to make it a legal post.]

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"

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

Brian Candler

Peter said:
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.
 
P

Peter Hickman

[Note: parts of this message were removed to make it a legal post.]

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
from :0

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top