On 12/12/10 2:50 PM, Nick Sabalausky wrote:
"Andrei Alexandrescu"<seewebsiteforem...@erdani.org>  wrote in message
news:ie341e$br...@digitalmars.com...
On 12/12/10 6:44 AM, Jacob Carlborg wrote:
[snip]
Conclusion:

D needs a better and nicer looking syntax for passing delegates to
functions.

Suggestion:

If a function takes a delegate as its last parameter allow the delegate
literal to be passed outside the parameter list, after the function
call, and allow to drop the semicolon. Also allow type inference of the
delegate parameters. Looking like this:

foo(bar) {
// do something with bar
}

If the function takes other arguments before the delegate I have two
suggestions, either just have two parameter lists, each in its own pair
of parentheses:

foo(3, 'a')(bar) {
// do something with bar
}

Or have two parameter lists in one pair of parentheses seperated by a
semicolon:

foo(3, 'a' ; bar) {
// do something with bar
}

I think that the syntax I've used in these examples has previously been
proposed.

Yah, it's been discussed a couple of times in the past. Both Walter and
myself are favorable to finding a good, simple lowering that improves
syntax without adding burden to the person who learns the language.

By the way, lowerings are great. Defining features as lowerings is a huge
win in language definition, ease of understanding, and correctness of
implementation. Features that have been implemented through lowering have
had very few bugs - e.g. scope() and the new operator overloading, which
was only a week's work.

Getting back to finding a good lowering, consider:

foreach (a, b ; c) stmt

A Ruby syntactic equivalent that clarifies what belongs to the block and
what belongs to the invoker of the block is:

c.each do |a, b|
   stmt
end

So a and b are passed to the block and each is a method of c (or more
general, each is a function called taking c as an argument). Going now
back to D, we can imagine the following lowering:

fun (a, b ; c) stmt

=>

fun(c, (a, b) { stmt })

This could and should be generalized for more parameters, which I'm sure
is very useful:

fun (a, b ; c, d) stmt

=>

fun(c, d, (a, b) { stmt })

Of course "fun" could be actually "obj.method".

With this we have a compelling syntax that has semantics obtained via
lowering.


I'm still concerned about this inconsistency:

void foo1()
{
     foreach(a, b; c) {
         return; // Return from foo1
     }
}

void foo2()
{
     fun(a, b; c) {
         return; // Effectively a "continue;" even though the syntax suggests
otherwise.
     }
}

And one consequence of that is that contrary to what has been said, this
would *not* allow foreach to be implemented as a library function.

I can appreciate the difficulty of getting the delegate's flow control to be
handled as expected, but I think going ahead with this sugar without
addressing that in some way would be a mistake.

Control flow inside the delegate can be addressed through a slightly more complicated lowering (the kind foreach already does). Probably break and continue should not be accepted because generally you can't expect all user-defined constructs to do iteration. Early returns should be easy to handle.

Andrei

Reply via email to