Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
June 25, 2006 List comprehensions in D? | ||||
---|---|---|---|---|
| ||||
My meager attempts to clone some list functionality in Python: r = [ y for y in array if y > 10 ]; thanks to shortened delegate declarations its pretty close in D: (this is a first stab but I'm sure we can get closer with some hackery) int[] r = array.where( (int y){ return y>10; } ); and for mutating the array: int[] r = array.map( (int y){return y + 5;} ); and in place modifications: array.update( (inout int y){ y+=5; } ); // template code begins template where(T) { T[] where( T[] arr, bool delegate(T) dg ) { T[] result ; foreach( T val; arr ) if ( dg(val) ) result ~= val; return result; } } template map(T) { T[] map( T[] arr, T delegate(T) dg ) { T[] result = new T[arr.length]; for( int n =0; n<arr.length; n++ ) result[n] = dg(arr[n]); return result; } } template update(T) { void update( T[] arr, void delegate(inout T) dg ) { foreach( int n,T val; arr ) dg( arr[n] ); } } Pretty cool, IMO. -DavidM |
June 25, 2006 Re: List comprehensions in D? | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Medlock | 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. > -DavidM 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 ); } x = vector[ (int t){return t>5;} ]; // subset of vector vector[] = (inout int x) { x += 100; } ; // update all members of vector And of course extending to opSlice/opSliceAssign.... -DavidM |
June 25, 2006 Re: List comprehensions in D? | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Medlock | In article <e7mg88$1mh3$1@digitaldaemon.com>, David Medlock says... > >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. >> -DavidM > >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 ); } > >x = vector[ (int t){return t>5;} ]; // subset of vector >vector[] = (inout int x) { x += 100; } ; // update all members of vector > >And of course extending to opSlice/opSliceAssign.... > >-DavidM Wonderfull !!! And simply powerfull too !!! D is looking more and more like a strongly typed Python like language with braces. Compiled languages can also support high level programming ( if well designed, but D is indeed ). |
June 27, 2006 Re: List comprehensions in D? | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Medlock | David Medlock wrote:
> My meager attempts to clone some list functionality in Python:
>
> r = [ y for y in array if y > 10 ];
>
> thanks to shortened delegate declarations its pretty close in D:
> (this is a first stab but I'm sure we can get closer with some hackery)
>
> int[] r = array.where( (int y){ return y>10; } );
>
> and for mutating the array:
>
> int[] r = array.map( (int y){return y + 5;} );
>
> and in place modifications:
>
> array.update( (inout int y){ y+=5; } );
>
>
> // template code begins
>
> template where(T)
> {
> T[] where( T[] arr, bool delegate(T) dg )
> {
> T[] result ;
> foreach( T val; arr ) if ( dg(val) ) result ~= val;
> return result;
> }
> }
>
> template map(T)
> {
> T[] map( T[] arr, T delegate(T) dg )
> {
> T[] result = new T[arr.length];
> for( int n =0; n<arr.length; n++ ) result[n] = dg(arr[n]);
> return result;
> }
> }
>
> template update(T)
> {
> void update( T[] arr, void delegate(inout T) dg )
> {
> foreach( int n,T val; arr ) dg( arr[n] );
> }
> }
>
> Pretty cool, IMO.
> -DavidM
Another useful pair of templates for parsing: skip and collect
// skip whitespace during parsing
char[] r = text.skip( (char c){ return c<=32; } );
// get the next token from the input text
char[] tok = text.collect( (char c){return isalnum(c)!=0; } );
template skip(T)
{
T[] skip( T[] arr, bool delegate(T) dg )
{
int count = 0;
foreach( T val; arr ) if ( dg( arr[count] )) count++; else break;
return arr[count..arr.length];
}
}
template collect(T)
{
T[] collect( T[] arr, bool delegate(T) dg )
{
int count = 0;
foreach( T val; arr ) if ( dg( arr[count] )) count++; else break;
return arr[0..count];
}
}
Love the new syntax, so clean.
-DavidM
|
June 29, 2006 Re: List comprehensions in D? | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Medlock | 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. > 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, 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) /Oskar |
June 29, 2006 Re: List comprehensions in D? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Oskar Linde | 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). > >> 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. Otherwise I don't see how you could do it without making a new array. 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) > > /Oskar 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. -DavidM |
June 30, 2006 Re: List comprehensions in D? | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Medlock | 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 |
Copyright © 1999-2021 by the D Language Foundation