Why Ruby?

Nick Sabalausky a at a.a
Sun Dec 12 10:27:17 PST 2010


"Jacob Carlborg" <doob at me.com> wrote in message 
news:ie2g72$1sf3$1 at digitalmars.com...
> On 2010-12-11 18:21, Andrei Alexandrescu wrote:
>> On 12/11/10 11:05 AM, so wrote:
>>> Not to hijack this one but on the other thread i asked why this is
>>> needed.
>>> I am not here asking for syntax or commanding phobos team to implement
>>> something, I just want to know about technical limitations and license
>>> issues, but got no answer to these.
>>> Why? Either i am labeled here as a troll (maybe something worse since my
>>> usage of English is not the best) or people here lack the vision (Oh
>>> vision here actually bad usage since this bad practice have been here
>>> forever, lack of eyesight would be the better definition)
>>> One another thing might be that the community finds this issue is not an
>>> important, (which makes me ask myself what you guys actually 
>>> developing).
>>
>> I don't think you're near the danger of being labeled as a troll. Would
>> be great to focus the discussion a bit.
>>
>> For example, let's take a look at the code example given in the talk's
>> first part that shows the beauty of Ruby. What does it look like in D?
>> What can we do to make it look and behave better?
>>
>>
>> Andrei
>
> If we take a look at the very first code example from the talk it looks 
> like this:
>
> account.people.each do |person|
>     puts person.name
> end
>
> You could translate this in two ways when translating into D.
> First way:
>
> foreach (person ; account.people)
>     writeln(person.name);
>
> I guess this is the most natural translation into D. If we want to be 
> closer to the Ruby code which uses a block we can translate the code to 
> use a delegate like this:
>
> account.people.each((Person person) {
>     writeln(person.name);
> });
>
> In my opinion this looks really ugly, D has no way of passing a delegate 
> to a function that looks good. If D could allow to pass a delegate to a 
> function outside the parameter list, after the function call, and had 
> better type inference it could look like this:
>
> account.people.each(person) {
>     writeln(person.name);
> }
>
> The above code is very close to the original Ruby code the only 
> differences is that D uses {} and Ruby uses "do" and "end".
>

There's one important difference you missed. Granted, it's not applicable in 
that particular example, but more generally, it's important:

int foo()
{
    foreach (person ; account.people)
    {
        writeln(person.name);
        if(blah)
            return 7; // Returns from foo
    }
}


int bar()
{
    account.people.each((Person person) {
        writeln(person.name);
        if(blah)
            return 7; // Only tries to return from the delegate
    });
}

In D, there is currently no way to convert "foo()" above to use a delgate 
(at least not without odd contorsions). So if we were to make syntax sugar 
for "bar()", it would get really confusing:

int bar2()
{
    account.people.each(Person person)
    {
        writeln(person.name);
        if(blah)
            return 7; // Only returns from the delegate, not bar2!! WTF?!
    }
}

There are similar issues with break, continue, and probably goto.

In Ruby, the syntax sugar works out fine because you can make it work it 
either way. You can create something that behaves like a delegate ("return" 
only returns from the delegate), or you can create something that is treated 
as part of the function it's declared within ("return" unwinds the stack and 
returns from the function that created it). (Although Ruby leaves the choice 
up the the caller. I'm not entirely convinced that's the right way to do 
it.)

D would need something similar for "passing a delegate" sugar to work out 
sensibly. One idea is to say that if-and-only-if the "sugar" is used, it's 
considered part of the original function that declared it rather than being 
a true degelate. The function that takes the "sugared delegate" must declare 
that it takes a "sugared delegate" instead of a normal one so that it can 
make sure not to do this:

doSomething();
callSugaredDelegateThatMightUnwindTheStackEvenWithoutThrowing();
doCleanup();





More information about the Digitalmars-d mailing list