On 2010-12-12 19:27, Nick Sabalausky wrote:
"Jacob Carlborg"<d...@me.com>  wrote in message
news:ie2g72$1sf...@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();

Yes, absolutely correct, I totally forgot about this. D would need a way to return from the delegate and a way to return from the context where the delegate is called. Perhaps introduce a new keyword "yield"?

--
/Jacob Carlborg

Reply via email to