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".

If we have a look at the next code example from the talk there is no clear and natural way to translate it into D, first the Ruby code:

class PeopleController < ActionController::Base
    before_filter :authenticate

    def index
        @people = Person.where("age > 30").order("name DESC")

        respond_to do |format|
            format.html
            format.xml { render :xml => @people.to_xml }
        end
    end
end

And then the translated D code:

class PeopleController : ActionController.Base
{
    Person[] people;

    mixin before_filter!(authenticate);

    void index ()
    {
        people = Person.where("age > 30").order("name DESC");

        respond_to((Format format) {
            format.html;
            format.xml({
                render(["xml" : people.to_xml]);
            });
        });
    }
}

In D there is no way to call a function in a class declaration like you can in Ruby so I guess the closest translation would be the mixin used above (maybe one could use "static this"). Again we can see in the D translation that the lack of a nice way of passing delegates to a function makes the code look uglier. Also the requirements of parentheses in function calls and square brackets in aa literals makes the code look less appealing in D. (Note, I'm pretty sure that activerecord doesn't return a plain Ruby array but instead some other class that behaves like an array but I took the freedom of translating it into a plain D array).

If we take a look at an enhanced D translation it could look like this:

class PeopleController : ActionController.Base
{
    Person[] people;

    mixin before_filter!(authenticate);

    void index ()
    {
        people = Person.where("age > 30").order("name DESC");

        respond_to(format) {
            format.html;
            format.xml {
                render(["xml" : people.to_xml]);
            }
        }
    }
}

Here the only change is how delegates are passed to the functions, same as in the previous code example.

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.

--
/Jacob Carlborg

Reply via email to