Why Ruby?

Stephan Soller stephan.soller at helionweb.de
Wed Dec 15 08:06:01 PST 2010


On 14.12.2010 20:03, Jacob Carlborg wrote:
> On 2010-12-14 19:33, Stephan Soller wrote:
>>>>
>>>> I think it's a matter of consistency. In Ruby blocks are used all the
>>>> time for pretty much everything. In D this isn't the case because
>>>> usually templates are used for stuff where blocks are used in Ruby
>>>> (e.g.
>>>> map, group and find in std.algorithm).
>>>
>>> I think that the templates that take a string as a predicate is just an
>>> ugly hack because D has a too verbose delegate syntax.
>>>
>>
>> I absolutely agree with that. However I don't have a better idea how to
>> write it. Delegate syntax is already fairly compact in D.
>>
>> For example code as this isn't very uncommon in Ruby:
>>
>> [1, 2, 3, 4, 5].select{|e| e > 3}.collect{|e| e*e}
>>
>> Of course this is a simplified example. Usually the collection would
>> contain some objects and the blocks would filter for a method call (like
>> "e.even?"). However I built a small D1 struct that implements a select
>> and collect function. With the unified function call synatax for array
>> with code should actually work:
>>
>> [1, 2, 3, 4, 5].select((int e){ return e > 3; })
>> .collect((int e){ return e*e; });
>>
>> It's already fairly compact. The main overhead is the parameter type and
>> the return statement. I don't believe this can be reduced any more
>> without breaking consistency of the language.
>
> Probably not, but, for example, Scala allows very compact delegate
> literals:
>
> Array(1, 2, 3, 4, 5).select(_ > 3).collect(_ * _)
>
> Or more verbose:
>
> Array(1, 2, 3, 4, 5).select((x) => x > 3).collect((x, y) => x * y)
>
> I'm not 100% sure I that the syntax is correct.
>
>> Delegates are way more verbose in other languages like PHP and
>> JavaScript (more or less the same syntax in both languages). Despite
>> that it's no problem to use it and in case of jQuery it's used very
>> often. I think the main reason why delegates are not used like that in D
>> is performance. I'm really not sure about it but I suspect that
>> delegates are less effective than code directly generated by a template
>> like map!(). I don't know how efficient templates can integrate
>> delegates so I just suspect that this is a performance problem.
>>
>> Happy programming
>> Stephan Soller
>
> PHP has a very verbose delegate syntax with explicit closures, one of
> the many reasons I don't use PHP. JavaScript has quite similar syntax as
> D but the "function" keyword is required, I try to use CoffeeScript
> (compiles to javascript), which has a lot nicer delegate syntax, as
> often I can.
>
> D(dmd) needs to be able to inline delegates.
>

I'm not so much concerned about verbose delegate syntax. Personally I 
don't mind using the current delegate syntax with templates like map!. 
However I'm concerned about performance and parameter order. Does 
someone know how delegates within templates are handled? I looked at the 
source of std.algorithm and std.functional but I'm still not sure what 
actually happens if you call something like

	auto ary = [1, 2, 3];
	map!((e){ return e*e; })(ary);

I can't test this code right now since I don't have a D2 compiler 
installed at this computer but the std.algorithm source contains unit 
tests with delegates.

If that now works with uniform function call syntax it could be written 
like that:

	auto ary = [1, 2, 3];
	ary.map!((e){ return e*e; });

I don't know if chaining of such calls is possible but the above syntax 
is already pretty good. Sure, it's not perfect and the "return" still is 
some overhead, but I don't think it needs work. What's more important 
(at least for me) is the chaining ability and how performant such 
delegates actually are. From what I understood from std.functional it 
wraps string expressions in delegates anyway so using

	ary.map!("a*a");

is not more efficient. Please correct me if I'm wrong! The 
std.functional code is definitely above my understanding.


So, _if_ we can figure out a way to do some nice chaining of such calls 
we can get:

	[1, 2, 3, 4, 5].filter!((e){ return e > 3; })
		.map!((e){ return e*e; });

Or if you don't like delegates and don't mind obvious compile time black 
magic:

	[1, 2, 3, 4, 5].filter!("a > 3").map!("a * a");

I think if chaining would work like that D would already be pretty close 
to the expressive power of Ruby. It's just that this kind of programming 
is very dependent on the ability of built in collections and libraries 
that allow such a programming style.

Happy programming
Stephan Soller


More information about the Digitalmars-d mailing list