RFC Future Ruby hash literal syntax

REQUEST FOR COMMENTS: Change to future Ruby hash literal syntax

In 1.9, if you prefer to omit parentheses and you write this:

  h = { a: Array.new 5, 'A', b: 0, c: 1 } # Syntax error

you will get a syntax error. The following works:

  h = { a: Array.new(5, 'A'), b: 0, c: 1 }

because the parser is not confused by the argument-separating comma
and the element-separating comma.

I propose that the owners consider changing the syntax.

ALTERNATIVE 1: Same input, different interpretation

If the scanner does lookahead and returns tASSOC_SEP for a comma
that is followed by a label, then there is no ambiguity.

ALTERNATIVE 2: Use ';' to separate elements, use ',' for arguments

  h = { a: Array.new 5, 'A'; b: 0; c: 1 } # Proposal 2

This avoids shift-reduce conflicts by a simple change to the assocs
production in parse.y, perhaps. Unfortunately the semicolon looks
strange, especially in array literals, when we address those, too.

ALTERNATIVE 3: Allow ';' as an element separator, but keep ','

h = { a: Array.new 5, 'A'; b: 0, c: 1 } # Proposal 3

This does not break working code. It is like 'or' versus '||',
and 'do' vs. '{', i.e., same role, different precedence.

···

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

Good Afternoon,

REQUEST FOR COMMENTS: Change to future Ruby hash literal syntax

In 1.9, if you prefer to omit parentheses and you write this:

h = { a: Array.new 5, 'A', b: 0, c: 1 } # Syntax error

you will get a syntax error. The following works:

h = { a: Array.new(5, 'A'), b: 0, c: 1 }

because the parser is not confused by the argument-separating comma
and the element-separating comma.

I propose that the owners consider changing the syntax.

ALTERNATIVE 1: Same input, different interpretation

If the scanner does lookahead and returns tASSOC_SEP for a comma
that is followed by a label, then there is no ambiguity.

ALTERNATIVE 2: Use ';' to separate elements, use ',' for arguments

h = { a: Array.new 5, 'A'; b: 0; c: 1 } # Proposal 2

This avoids shift-reduce conflicts by a simple change to the assocs
production in parse.y, perhaps. Unfortunately the semicolon looks
strange, especially in array literals, when we address those, too.

ALTERNATIVE 3: Allow ';' as an element separator, but keep ','

h = { a: Array.new 5, 'A'; b: 0, c: 1 } # Proposal 3

This does not break working code. It is like 'or' versus '||',
and 'do' vs. '{', i.e., same role, different precedence.

I'd vote none of the above. That has got to be some of the ugliest looking
ruby code I've ever seen. None of those concepts looks to be legible at all.
Forget about what the parser handles....the human brain can't make heads nor
tails out of that stuff.

Is there honestly a use case that requires the code to be compacted into
that ugly a grouping of different concepts? I mean I can get the concept
that folks hate parentheses but you really couldn't do this?

x = Array.new 5, 'A'
h = { a: x, b: 0, c: 1 }

John

···

On Mon, Nov 29, 2010 at 2:45 PM, Michael Kaelbling < michael.kaelbling@siemens.com> wrote:

or better:

h = { a: ["A"] * 5, b: 0, c: 1 }

I never understand ppl's obsession with Array.new and Hash.new, not including hash's block initializer. Hash.new {...} is brilliant and I love it. I think all variants or Array.new are essentially useless and stick to for everything.

Most of my students who Array.new that were Java developers and it was pretty easy to break them of the habit.

(and most of my students who obsessively used '' instead of "" were perlers... that was a harder habit to break, even if I could show them that they were just as fast (and always faster than perl)).

···

On Nov 29, 2010, at 14:58 , John W Higgins wrote:

x = Array.new 5, 'A'
h = { a: x, b: 0, c: 1 }

Ditto. Forget about shift/reduce conflicts... I don't care if a parser can't
figure out so much as if my brain can't figure out, and looking at your
examples I can't tell what's going on.

Replacing , with ; in the new hash literal syntax would be a bad change,
imo. The new hash literal syntax works well for keyword arguments and in
fact I'd consider that the main use case, e.g.

    mymethod(arg1: x, arg2: y, arg3: z)

The idea being you could use this in lieu of:

    mymethod(x, y, z)

so using a , is much more natural.

···

On Mon, Nov 29, 2010 at 3:58 PM, John W Higgins <wishdev@gmail.com> wrote:

I'd vote none of the above. That has got to be some of the ugliest looking
ruby code I've ever seen.

--
Tony Arcieri
Medioh! A Kudelski Brand

And, of course:

  BenString.new("my string is better with BenString")

···

On Nov 29, 2010, at 15:31 , Ryan Davis wrote:

I never understand ppl's obsession with Array.new and Hash.new, not including hash's block initializer. Hash.new {...} is brilliant and I love it. I think all variants or Array.new are essentially useless and stick to for everything.

What's your equivalent of `Array.new(3) { Thing.new }`?

···

On Nov 29, 5:31 pm, Ryan Davis <ryand-r...@zenspider.com> wrote:

I think all variants or Array.new are essentially useless and stick to for everything.

--
-yossef

Who uses string literals anymore? I switched to using BenStrings
exclusively.

···

On Mon, Nov 29, 2010 at 6:49 PM, Ryan Davis <ryand-ruby@zenspider.com>wrote:

And, of course:

BenString.new("my string is better with BenString")

--
Tony Arcieri
Medioh! A Kudelski Brand

BenArray.new(3, Thing.new) works great!

···

On Nov 29, 2010, at 19:40 , Yossef Mendelssohn wrote:

On Nov 29, 5:31 pm, Ryan Davis <ryand-r...@zenspider.com> wrote:

I think all variants or Array.new are essentially useless and stick to for everything.

What's your equivalent of `Array.new(3) { Thing.new }`?

Using an inline block like that mandates parens around the argument(s)
anyway so it's moot in this context.

···

On Mon, Nov 29, 2010 at 8:40 PM, Yossef Mendelssohn <ymendel@pobox.com>wrote:

On Nov 29, 5:31 pm, Ryan Davis <ryand-r...@zenspider.com> wrote:
> I think all variants or Array.new are essentially useless and stick to
for everything.

What's your equivalent of `Array.new(3) { Thing.new }`?

--
Tony Arcieri
Medioh! A Kudelski Brand

Don't even need to go that far, even the String version has this issue.

a = ['A'] * 5
a.first << 'B'
a # => ["AB", "AB", "AB", "AB", "AB"]

···

On Mon, Nov 29, 2010 at 9:40 PM, Yossef Mendelssohn <ymendel@pobox.com>wrote:

On Nov 29, 5:31 pm, Ryan Davis <ryand-r...@zenspider.com> wrote:
> I think all variants or Array.new are essentially useless and stick to
for everything.

What's your equivalent of `Array.new(3) { Thing.new }`?

--
-yossef

>> I think all variants or Array.new are essentially useless and stick to for everything.

> What's your equivalent of `Array.new(3) { Thing.new }`?

BenArray.new(3, Thing.new) works great!

I've yet to use BenArray, but assuming it follows BenString
conventions:

  >> Array.new(3, Object.new)
  => [#<Object:0x51af7c>, #<Object:0x51af7c>, #<Object:0x51af7c>]
  >> Array.new(3) { Object.new }
  => [#<Object:0x5136b4>, #<Object:0x5136a0>, #<Object:0x51363c>]

My question still stands.

···

On Nov 29, 9:48 pm, Ryan Davis <ryand-r...@zenspider.com> wrote:

On Nov 29, 2010, at 19:40 , Yossef Mendelssohn wrote:
> On Nov 29, 5:31 pm, Ryan Davis <ryand-r...@zenspider.com> wrote:

--
-yossef

Tony Arcieri wrote in post #965007:

What's your equivalent of `Array.new(3) { Thing.new }`?

Using an inline block like that mandates parens around the argument(s)
anyway so it's moot in this context.

Parens not needed with do/end:

class Thing; end

=> nil

a = Array.new 3 do Thing.new end

=> [#<Thing:0x7f69a1a5e210>, #<Thing:0x7f69a1a5e1e8>,
#<Thing:0x7f69a1a5e198>]

···

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

ruby-1.9.2-p0 > ([1]*3).map! {|x| Object.new}
  => [#<Object:0x00000000a12778>, #<Object:0x00000000a12750>, #<Object:0x00000000a12728>]

??

···

On 30/11/10 16:54, Yossef Mendelssohn wrote:

On Nov 29, 9:48 pm, Ryan Davis<ryand-r...@zenspider.com> wrote:
   

On Nov 29, 2010, at 19:40 , Yossef Mendelssohn wrote:

On Nov 29, 5:31 pm, Ryan Davis<ryand-r...@zenspider.com> wrote:
       

I think all variants or Array.new are essentially useless and stick to for everything.
         
What's your equivalent of `Array.new(3) { Thing.new }`?
       

BenArray.new(3, Thing.new) works great!
     

I've yet to use BenArray, but assuming it follows BenString
conventions:

   >> Array.new(3, Object.new)
   => [#<Object:0x51af7c>, #<Object:0x51af7c>, #<Object:0x51af7c>]
   >> Array.new(3) { Object.new }
   => [#<Object:0x5136b4>, #<Object:0x5136a0>, #<Object:0x51363c>]

My question still stands.

--
-yossef

No! BenArray performs like the latter.

···

On Nov 29, 2010, at 19:54 , Yossef Mendelssohn wrote:

I've yet to use BenArray, but assuming it follows BenString
conventions:

Array.new(3, Object.new)

=> [#<Object:0x51af7c>, #<Object:0x51af7c>, #<Object:0x51af7c>]

Array.new(3) { Object.new }

=> [#<Object:0x5136b4>, #<Object:0x5136a0>, #<Object:0x51363c>]

My question still stands.

Oops, just realised I didn't need the x

ruby-1.9.2-p0 > ([1]*3).map! {Object.new}
  => [#<Object:0x00000000a4b848>, #<Object:0x00000000a4b820>, #<Object:0x00000000a4b7f8>]

Sam

···

On 30/11/10 17:20, Sam Duncan wrote:

ruby-1.9.2-p0 > ([1]*3).map! {|x| Object.new}
=> [#<Object:0x00000000a12778>, #<Object:0x00000000a12750>, #<Object:0x00000000a12728>]

??

On 30/11/10 16:54, Yossef Mendelssohn wrote:

On Nov 29, 9:48 pm, Ryan Davis<ryand-r...@zenspider.com> wrote:

On Nov 29, 2010, at 19:40 , Yossef Mendelssohn wrote:

On Nov 29, 5:31 pm, Ryan Davis<ryand-r...@zenspider.com> wrote:

I think all variants or Array.new are essentially useless and stick to for everything.

What's your equivalent of `Array.new(3) { Thing.new }`?

BenArray.new(3, Thing.new) works great!

I've yet to use BenArray, but assuming it follows BenString
conventions:

>> Array.new(3, Object.new)
   => [#<Object:0x51af7c>, #<Object:0x51af7c>, #<Object:0x51af7c>]
>> Array.new(3) { Object.new }
   => [#<Object:0x5136b4>, #<Object:0x5136a0>, #<Object:0x51363c>]

My question still stands.

--
-yossef

For communication's sake, I suggest you make special cases like that
clear in the future.

···

On Nov 30, 4:19 pm, Ryan Davis <ryand-r...@zenspider.com> wrote:

On Nov 29, 2010, at 19:54 , Yossef Mendelssohn wrote:

> I've yet to use BenArray, but assuming it follows BenString
> conventions:

No! BenArray performs like the latter.

--
-yossef

You don't need the map! either, and while I'm at it...

    (1..3).map { Object.new }

···

On Mon, Nov 29, 2010 at 9:36 PM, Sam Duncan <sduncan@wetafx.co.nz> wrote:

Oops, just realised I didn't need the x

ruby-1.9.2-p0 > ([1]*3).map! {Object.new}
=> [#<Object:0x00000000a4b848>, #<Object:0x00000000a4b820>,
#<Object:0x00000000a4b7f8>]

--
Tony Arcieri
Medioh! A Kudelski Brand

I did. "Ben"

···

On Dec 1, 2010, at 11:54 , Yossef Mendelssohn wrote:

On Nov 30, 4:19 pm, Ryan Davis <ryand-r...@zenspider.com> wrote:

On Nov 29, 2010, at 19:54 , Yossef Mendelssohn wrote:

I've yet to use BenArray, but assuming it follows BenString
conventions:

No! BenArray performs like the latter.

For communication's sake, I suggest you make special cases like that
clear in the future.

i'd do,

3.times.map{Object.new}
#=> [#<Object:0x94df234>, #<Object:0x94df220>, #<Object:0x94df20c>]

since when read, i feel it would be closer to Array.new(3){Object.new}
but i have no qualms about Array.new notations though and i used them
all the time :slight_smile:

best regards -botp

···

On Tue, Nov 30, 2010 at 12:41 PM, Tony Arcieri <tony.arcieri@medioh.com> wrote:

(1..3).map { Object.new }

I wasn't aware that was possible, but it makes sense since `3.times`
returns an enumerator.

It's also the only example that doesn't feel like an overt attempt to
avoid using the right tool for the job.

···

On Nov 29, 11:05 pm, botp <botp...@gmail.com> wrote:

i'd do,

3.times.map{Object.new}
#=> [#<Object:0x94df234>, #<Object:0x94df220>, #<Object:0x94df20c>]

--
-yossef