New block notation (was: Re: ruby-dev summary 26468-26661)

Yukihiro Matsumoto wrote:

Hi,

>Nah, just use the _collection_ brackets for both array and hash. The
>parser can tell them apart:
>
> # array
> [ a, b, c ]
>
> # hash
> [ a=>x, b=>y, c=>z ]
> [ a: x, b: y, c: z ]

Yes, if it isn't empty.

But that's easy enough to remedy:

  [:] # empty hash

That said, I realize its atypical from most other languages. But Ruby
isn't most other languages. Ruby is a fully OOP agile language. Ask
yourself, what is a Hash? In a very real sense (real as in utility) it
is an Array of Associations. This is not to say I'm suggesting hashes
neccessarily be fully OOPized in this way, but it does show at least,
the syntax above is quite sensible. Not to mention the clarity it would
give to blocks/lambdas. Alas, I imagine that such a change would be
considered huge, and for that reason alone (although I imagine both
syntaxes could be supported in a transition), unfortunately, Not Going
To Happen(tm).

T.

···

In message "Re: new block notation" > on Fri, 5 Aug 2005 19:56:06 +0900, "Trans" <transfire@gmail.com> writes:

Hi,

···

In message "Re: new block notation (was: Re: ruby-dev summary 26468-26661)" on Fri, 5 Aug 2005 10:23:56 +0900, "Trans" <transfire@gmail.com> writes:

Why not pioneer the first language with it's own fontset :slight_smile:

It's not funny for a person who had bunch of troubles with managing /
preparing fontset.

But asides of that, it was funny :wink:

              matz.

Trans wrote:

Why not pioneer the first language with it's own fontset :slight_smile:

I assume that you're kidding, but for anyone who didn't understand
there's more information at
APL (programming language) - Wikipedia,
        nikolai

···

--
Nikolai Weibull: now available free of charge at http://bitwi.se/\!
Born in Chicago, IL USA; currently residing in Gothenburg, Sweden.
main(){printf(&linux["\021%six\012\0"],(linux)["have"]+"fun"-97);}

Hi,

This is probably the wrong place to ask, but is there resources that
explain the evolution of Ruby's design in detail? It is something that I
find very interesting.

I don't think so. Google on ruby-talk may give you some information.
Or, ask me. I will answer you, if I could have some spare time.

I think that the check is not strictly necessary in blocks. I guess it
could be argued about if it is necessary to have it for lambdas.

Or can we just add the check to all blocks and lambdas? This would mean
that multiple assignment semantics are totally gone and that [1, 2,
3].each_with_index { |x| p x } would no longer work which might be a
good thing, anyway.

Ignoring values has been troublesome even with multiple assignment
because of the array assignment effect anyway.

Don't misunderstand me. Blocks will remain blocks. I just want to
make lambdas real anonymous functions. Current lambdas are sort of
"faked anonymous functions" mostly due to its handling of arguments
(and local-exit).

Here's another try to come up with an alternative:

[1, 2, 3].inject { |a| a } # => 1
[1, 2, 3].inject { |*a| a } # => [[1, 2], 3]
I think both would eventually not produce warnings. The first could
still emit a warning for a short period to get users used to the change.

Again, this issue is not related to block behavior.

              matz.

···

In message "Re: new block notation (was: Re: ruby-dev summary 26468-26661)" on Fri, 5 Aug 2005 11:44:23 +0900, Florian Groß <florgro@gmail.com> writes:

At first I rejected the syntax, too. But after thinking about it for a
while, it made some sense: if you see -> as a shortcut for "function""
and as a operator that creates a lambda expression with the bound
variables a, b and the body { ... }. If lambda would have been made a
special form instead of a method call, it could have been
lambda(a, b) { ... } as well.

I still like { a, b = 5 -> a ** 2 + b ** 2 } better and think it's more
similar to the older {|| } syntax. (I don't know if there are any
parsing problems with this syntax.)

It's also slightly less confusing in more complex cases. Compare

foo(->(x){ 2 * x }) &->(y){ 3 * y }

to

foo({ x -> 2 * x }) &{ y -> 3 * y}

If the ->() syntax stays, we should get used to cartoon character
swearing jokes like Perlers had to. :wink:

···

On 2005-08-05 11:44:23 +0900, Florian Gro?? wrote:

I really don't understand the idea behind x = ->(a, b) { ... } -- it
makes as much sense as x = ^^(a, b) { ... } to me so I would like if
it would not replace the anonymous functions or blocks I use so
frequently.

--
Florian Frank

nice. i like it!

-a

···

On Fri, 5 Aug 2005, Jason Foreman wrote:

I hadn't seen this particular variant posted in this thread yet.
Apologies if it was and I missed it. I make no claims as to its ease
of parsing or whatever, but it looks better than many of the other
options to me.

bar = { x, y=3, z=b|5 ->
x + y * z
}

I believe this is similar to the approach that Groovy [1] uses for its blocks.

Jason

[1] http://groovy.codehaus.org

--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
My religion is very simple. My religion is kindness.
--Tenzin Gyatso

===============================================================================

A few of us (you, me, Florian) have suggested variants of this:

{ arg-list <delimiter> code }

You and Florian suggested the delimiter be "->". I suggested
":"+spacing (to not confuse with symbols) or ;/newline if the
args were made mandatory.

I think any of these delimiters plus probably others could work
and look good. The general form above is about the most
concise you can get and probably the best if workable.

The problem with this is 2 fold:

1. It can be difficult/impossible to differentiate a lambda vs.
a hash. I'd prefer to change the hash syntax.

2. If the arg-list/delimiter is optional, it requires an
indeterminate amount of lookahead to determine whether the
lambda/block starts with an arg list or code. A parser
solution to this is to initially treat the arg-list as code and
then if the delimiter is found (could be thought of as an
arg-list operator) in the first statement/expression where that
expression/statement can terminate, treat what is to the left
as the arg-list. I think this should work because as far as I
see any valid arg-list (including defaults) also happens to be
a valid expression. But, after the delimiter is found, the
parse tree for the arg-list would have to be cleaned up and
some extra syntax checking would be needed. Kind of ugly, but
doable.

···

--- Jason Foreman <threeve.org@gmail.com> wrote:

I hadn't seen this particular variant posted in this thread
yet.
Apologies if it was and I missed it. I make no claims as to
its ease
of parsing or whatever, but it looks better than many of the
other
options to me.

bar = { x, y=3, z=b|5 ->
  x + y * z
}

I believe this is similar to the approach that Groovy [1]
uses for its blocks.

____________________________________________________
Start your day with Yahoo! - make it your home page
http://www.yahoo.com/r/hs

Hi --

I hadn't seen this particular variant posted in this thread yet.
Apologies if it was and I missed it. I make no claims as to its ease
of parsing or whatever, but it looks better than many of the other
options to me.

bar = { x, y=3, z=b|5 ->
x + y * z
}

The problem I have with this is that you can't tell until you get to
the -> that it isn't a hash. There's no case in Ruby, that I've ever
been able to identify, where you have to go beyond the { to make that
determination:

   a = {w,x,y=3,z=5} # hash
   a { x } # block
   a({ x,y }) # hash

etc. I'm not even thinking of it from the parser's point of view, but
only from the human's. It introduces a whole new level of visual
uncertainty.

(This came up here or perhaps on ruby-core a few months ago, in
slightly different form I think but essentially the same concept.)

David

···

On Fri, 5 Aug 2005, Jason Foreman wrote:

--
David A. Black
dblack@wobblini.net

Hi --

···

On Sat, 6 Aug 2005, Trans wrote:

Martin DeMello wrote:

# empty array

# empty hash

[:]

and

[=>]

=> is a connector between a key and value. It doesn't make sense for
it to appear if there are no keys and no values.

David

--
David A. Black
dblack@wobblini.net

Hello all,

I'm trying to marshal an object and I get an error "<Classname> cannot be referred"

Does anyone know what this error indicates? I've googled it to no avail, and the source code where the error is raised isn't much help either lest I spend hours digging through it. Thanks!

Nate

Hi --

Yukihiro Matsumoto wrote:

Hi,

>Nah, just use the _collection_ brackets for both array and hash. The
>parser can tell them apart:
>
> # array
> [ a, b, c ]
>
> # hash
> [ a=>x, b=>y, c=>z ]
> [ a: x, b: y, c: z ]

Yes, if it isn't empty.

But that's easy enough to remedy:

[:] # empty hash

That said, I realize its atypical from most other languages. But Ruby
isn't most other languages. Ruby is a fully OOP agile language. Ask
yourself, what is a Hash? In a very real sense (real as in utility) it
is an Array of Associations. This is not to say I'm suggesting hashes
neccessarily be fully OOPized in this way, but it does show at least,
the syntax above is quite sensible. Not to mention the clarity it would
give to blocks/lambdas. Alas, I imagine that such a change would be
considered huge, and for that reason alone (although I imagine both
syntaxes could be supported in a transition), unfortunately, Not Going
To Happen(tm).

I'm still not seeing how

   [:]

or

   [=>]

conveys the notion of 'emptiness' better than

   {}

Maybe it's just my new-punctuation allergy....

David

···

On Sat, 6 Aug 2005, Trans wrote:

In message "Re: new block notation" >> on Fri, 5 Aug 2005 19:56:06 +0900, "Trans" <transfire@gmail.com> writes:

--
David A. Black
dblack@wobblini.net

matz,

I haven't heard any comment from you on the with do and the def with style

hash.each with a,b do
  #blah
end

or

def foo with a,b
  #blah
end

j.

···

On 8/4/05, Yukihiro Matsumoto <matz@ruby-lang.org> wrote:

Hi,

In message "Re: new block notation (was: Re: ruby-dev summary 26468-26661)" > on Fri, 5 Aug 2005 11:44:23 +0900, Florian Groß <florgro@gmail.com> writes:

>This is probably the wrong place to ask, but is there resources that
>explain the evolution of Ruby's design in detail? It is something that I
>find very interesting.

I don't think so. Google on ruby-talk may give you some information.
Or, ask me. I will answer you, if I could have some spare time.

>I think that the check is not strictly necessary in blocks. I guess it
>could be argued about if it is necessary to have it for lambdas.
>
>Or can we just add the check to all blocks and lambdas? This would mean
>that multiple assignment semantics are totally gone and that [1, 2,
>3].each_with_index { |x| p x } would no longer work which might be a
>good thing, anyway.
>
>Ignoring values has been troublesome even with multiple assignment
>because of the array assignment effect anyway.

Don't misunderstand me. Blocks will remain blocks. I just want to
make lambdas real anonymous functions. Current lambdas are sort of
"faked anonymous functions" mostly due to its handling of arguments
(and local-exit).

>Here's another try to come up with an alternative:
>
>[1, 2, 3].inject { |a| a } # => 1
>[1, 2, 3].inject { |*a| a } # => [[1, 2], 3]
>I think both would eventually not produce warnings. The first could
>still emit a warning for a short period to get users used to the change.

Again, this issue is not related to block behavior.

                                                        matz.

--
"So long, and thanks for all the fish"

Jeff Wood

Matz, I see that you plan on keeping the syntax and mechanics of blocks separate from lambdas. I assume this means that internally there will be a Block class separate from a Lambda (or other-named) class.

From this thread I think I understand why:
     * need really terse syntax for blocks
     * sometimes you want arity matching, sometimes you don't

But it still makes me sad that we will (at least) have Blocks different from Methods, despite the fact that both are code chunks that take arguments.

Will lambdas be interchangeable with methods? Or do you envision the future of Ruby as still having at least three distinct functional items:
   * Blocks
   * Lambdas (whatever the syntax)
   * Methods

(And by distinct, I mean more than just different syntax for defining them; that internally they will be different, non-interchangeable objects.)

If the answer is "yes, there will still be three distinct chunk-of-code-with-parameters items", I request that there at least be methods for transforming between all three:
     my_array.each( &MyClass.instance_method( :foo ) )

     f = lambda{ ... }
     my_array.each( &f )

     etc.

···

On Aug 4, 2005, at 11:58 PM, Yukihiro Matsumoto wrote:

Don't misunderstand me. Blocks will remain blocks. I just want to
make lambdas real anonymous functions. Current lambdas are sort of
"faked anonymous functions" mostly due to its handling of arguments
(and local-exit).

Hi --

···

On Fri, 5 Aug 2005, Florian Frank wrote:

If the ->() syntax stays, we should get used to cartoon character
swearing jokes like Perlers had to. :wink:

That's a good reason for it not to stay. I wish there were some way
to predict. As I've said, I fear the same thing (too much
punctuation), but it's so hard to know where the threshold is.

David

--
David A. Black
dblack@wobblini.net

Yukihiro Matsumoto wrote:

>This is probably the wrong place to ask, but is there resources that >explain the evolution of Ruby's design in detail? It is something that I >find very interesting.

I don't think so. Google on ruby-talk may give you some information.
Or, ask me. I will answer you, if I could have some spare time.

Thank you. If there ever is the chance of you writing another book on Ruby this would be a cool thing to include, I think. I can't promise you that other Rubyists will be as interested in it as I am, but I hope so. :slight_smile:

Don't misunderstand me. Blocks will remain blocks. I just want to
make lambdas real anonymous functions. Current lambdas are sort of
"faked anonymous functions" mostly due to its handling of arguments
(and local-exit).

Why not go with lambda(arg-list) { body } or fun(arg-list) { body } or def(arg-list) { body } then? I think that the syntax would point out that this is more than a method that turns a block into an object and I think that it would be a simple solution.

In action:

adder = lambda(a, b) { a + b }
adder.call(1, 2) # => 3
[1, 2, 3].inject(&adder)

generic_adder = lambda(a) do
   lambda(b) do
     a + b
   end
end

add_five = generic_adder.call(5)
add_five.call(3) # => 8
[1, 2, 3].map(&add_five) # => [6, 7, 8]

(All with function call semantics.)

It would mean that lambda() would no longer be a method call, but rather special syntax like defined?(), but I can live with that, especially since lambda wasn't the same as just doing def lambda(&block) block end in the past either.

I'm not sure what lambda(&obj) should do in the future, but I think it is equivalent to calling obj.to_proc currently anyway.

Eric Mahurin wrote:

--- Jason Foreman wrote: [...]

A few of us (you, me, Florian) have suggested variants of this:

{ arg-list <delimiter> code }

You and Florian suggested the delimiter be "->". I suggested
":"+spacing (to not confuse with symbols) or ;/newline if the
args were made mandatory.

I think any of these delimiters plus probably others could work
and look good. The general form above is about the most
concise you can get and probably the best if workable.

Nobu has given his assessment to you here:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/150834

The problem with this is 2 fold:
[...]

Yes. The second is the show-stopper:

2. If the arg-list/delimiter is optional, it requires an
indeterminate amount of lookahead to determine whether the
lambda/block starts with an arg list or code. A parser
solution to this is to initially treat the arg-list as code and
then if the delimiter is found (could be thought of as an
arg-list operator) in the first statement/expression where that
expression/statement can terminate, treat what is to the left
as the arg-list. I think this should work because as far as I
see any valid arg-list (including defaults) also happens to be
a valid expression. But, after the delimiter is found, the
parse tree for the arg-list would have to be cleaned up and
some extra syntax checking would be needed. Kind of ugly, but
doable.

For the purposes of keeping the discussion relevant, this should
be considered impossible, I think.
The tight linkage between parser and lexer states means that the
subtle differences appearing in either code or argument lists
have been occluded.
back the lexer would not be an enjoyable task <<understatement>>.
Maybe possible with a pre-compile pass but that option has been
rejected before, I'm sure.

Any "desirable" variants should acknowledge that the lexer needs
to be able to recognise the arrival of an argument list.

- My humble recommendation.

daz

···

From my (slightly less than) superficial understanding, rolling

> [=>]

=> is a connector between a key and value. It doesn't make sense for
it to appear if there are no keys and no values.

Except to say 'keys and values go here'. But it's one of those
personal taste things, you can't argue it.

That said, I'm not a big fan of it. Although I like the '[:]' syntax
for empty hashes in 1.9, but I got clobbered on ruby-core for
suggesting it a couple months back :slight_smile:

Dan

Which particular <Classname> are we talking about here? Can you show us a small code example?

James Edward Gray II

···

On Aug 5, 2005, at 3:57 PM, Nathan Smith wrote:

Hello all,

I'm trying to marshal an object and I get an error "<Classname> cannot be referred"

Does anyone know what this error indicates? I've googled it to no avail, and the source code where the error is raised isn't much help either lest I spend hours digging through it. Thanks!

"David A. Black" <dblack@wobblini.net> writes:

I'm still not seeing how

   [:]

or

   [=>]

conveys the notion of 'emptiness' better than

   {}

The reason people are suggesting the [:] syntax is to avoid
the confusion with blocks. Since {} doesn't avoid the
confusion with blocks, [:] is in this sense better.

···

--
Daniel Brockman <daniel@brockman.se>

Hi --

matz,

I haven't heard any comment from you on the with do and the def with style

hash.each with a,b do
#blah
end

or

def foo with a,b
#blah
end

With regard to the first one (and for the sake of all of us, including
me, who weren't clear that this was about lambdas per se), Matz said:

Don't worry. The block syntax will not be changed. Never.

David

···

On Fri, 5 Aug 2005, Jeff Wood wrote:

--
David A. Black
dblack@wobblini.net