Why Ruby?

Jacob Carlborg doob at me.com
Sun Dec 12 04:44:43 PST 2010


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


More information about the Digitalmars-d mailing list