Why Ruby?
Andrei Alexandrescu
SeeWebsiteForEmail at erdani.org
Sun Dec 12 13:39:38 PST 2010
On 12/12/10 2:50 PM, Nick Sabalausky wrote:
> "Andrei Alexandrescu"<SeeWebsiteForEmail at erdani.org> wrote in message
> news:ie341e$bru$1 at 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
More information about the Digitalmars-d
mailing list