List comprehensions in D?

Oskar Linde oskar.lindeREM at OVEgmail.com
Fri Jun 30 09:48:53 PDT 2006


David Medlock wrote:
> Oskar Linde wrote:
>> David Medlock wrote:
>>
>>> David Medlock wrote:
>>>
>>>> My meager attempts to clone some list functionality in Python:
>>>>
>>>> r = [ y for y in array if y > 10 ];
>>>
>>> <snip>
>>>
>>>> Pretty cool, IMO.
>>
>>
>> Yes, the new delegate syntax is very convenient. The above functions 
>> are also in my std.array proposal (under different names). Your update 
>> function with an inout argument instead of my suggested doMap with a 
>> pure functional argument is interesting:
>>
>> arr.update((inout int x){ x++; });
>> vs
>> arr.doMap((int x){ return x+1; });
>>
>> A smart implementation would be able to support both versions in one 
>> function. I wounder if that is appropriate. It would be helpful if 
>> there were any way to tell if the arguments of a delegate type were 
>> in/out/inout. I guess some .mangleof hackery could help there.
> 
> I'm not sure, but since arrays are by reference I would prefer to make 
> update functions named differently (sort and reverse still bite me on 
> occasion).

I should have mentioned that the doMap is also an in-place modifying 
function. I agree that such functions should preferably have a different 
name, and that is the reason for the "do"-prefix. update is a nice and 
clear name though.

I also find the behavior of sort and reverse to be unfortunate. For 
example, I've more than once seen code similar to:

foreach(x ; arr.reverse) {...},

where I believe the side effect was unintentional. Since .sort and 
.reverse are now fully library-implementable (sans the lacking trailing 
parentheses), I think they should be made depreciated at some point.

>>> in addition,
>>>
>>> If you consider that arrays are just machine-optimized versions of 
>>> maps(or graphs) with the allowed index as integers between 0 and N,
>>> then passing a predicate function on those indexes makes some sense.
>>>
>>> for containers: (depending on your view of the syntax)
>>>
>>> T[]  opIndex( bool delegate(T) dg ) { return items.where( dg ); }
>>> T[]  opIndexAssign( void delegate( inout T) dg ){ items.update( dg ); }
>>
>>
>> In my view of the syntax, opIndex(bool delegate) should return a view, 
>> rater then a new array with copied elements, 
> 
> Do you mean a container which transforms the elements passed through 
> opIndex using the delegate?  That could be an issue with the delegate 
> going out of scope.

Yes. And you are right.

> Otherwise I don't see how you could do it without making a new array.

You could use the delegate to evaluate an index array, but that would 
also count as making a new array I guess. :)

> similar to how a slice of
>> an array returns a view rather than copied elements. A combined 
>> select/update would also be cool:
>>
>> void opIndexAssign(T delegate(T) updater, bool delegate(T) selecter)
>>
> Yes combined functionality is nice and getting close to the list 
> comprehensions i covet from python.
> 
> I also toyed with the idea of using the (just added) opIn operator.
> 
> int[] result = container in (int a) {return a>5;};
> 
> But this seemed too 'out of the ordinary'.
> 
> PS. I will be glad to see your array lib in phobos.

Thanks. I'm actually not very concerned about getting /my/ library in 
phobos, but I would certainly like to see /a/ library there.

Sadly, D's incomplete ifti support is an inhibiting factor that makes 
writing template libraries more awkward than needed. The uncertainty 
regarding when and how we can expect an improvement doesn't help either.

Regards,

Oskar



More information about the Digitalmars-d mailing list