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