Why Ruby?

Jacob Carlborg doob at me.com
Thu Dec 16 11:01:14 PST 2010


On 2010-12-15 17:06, Stephan Soller wrote:
> 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.

I would though it just mixed in the string with some other code to make 
a complete expression.

> 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

-- 
/Jacob Carlborg


More information about the Digitalmars-d mailing list