www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - lambda recursion

reply ddcovery <antoniocabreraperez gmail.com> writes:
I want to express in D the known Haskell qsort 3 lines code (it 
is not a quick sort, but an example of how functional programming 
is expressive).

This is the "javascript" version I use as reference:

     const sorted = ( [pivot, …others] ) => pivot===void 0 ? [ ] : 
[
       … sorted( others.filter( n=> n<pivot ) ),
       pivot,
       … sorted( others.filter( n=> n>=pivot ) )
     ];


This is a possible D implementation:

void main()
{
     import std.stdio, std.algorithm, std.range;
	
     int[] delegate(int[]) qs;
	
     qs = (int[] items) => items.length==0 ? items :
       chain(
         qs(items[1..$].filter!(i=> i<items[0] ).array),
         items[0..1],
         qs(items[1..$].filter!(i=> i >= items[0]).array)
       ).array;
	
     auto result = qs([10,9,5,4,8,7,-20]);
     assert( result.equal([-20,4,5,7,8,9,10]) );
     writeln("Result:", result );
}

First problem I found is "qs" must be splitted in 2 expressions: 
declaration and assignation, because declaration is not 
"effective" until all expression is compiled (compiler says qs 
doesn't exist when compiling the lambda body) .

* Is there any way to reduce the code(using lambdas) to one 
expression only?

   int[] delegate(int[]) qs = (int[] items) => items.length==0 
.....

   Or better

   auto qs = (int[] items) => items.length==0 ?  ...

* Can the lambda be transformed to a template (using T instead 
"int") but avoiding function/return syntax?

This is an example using function

   template qs(T){
     T[] qs( T[] items ){
       return items.length==0
         ? items
         : chain(
           qs(items[1..$].filter!(i=> i<items[0] ).array),
           items[0..1],
           qs(items[1..$].filter!(i=> i >= items[0]).array)
         ).array;
     }
}


* I'm trying to use "ranges" to avoid the "array" conversion.  Do 
you figure out a way to express the lambda params and return as a 
Range to avoid converting to array?
Nov 27 2020
parent reply ddcovery <antoniocabreraperez gmail.com> writes:
On Friday, 27 November 2020 at 16:40:43 UTC, ddcovery wrote:
 ...
 * Can the lambda be transformed to a template (using T instead 
 "int") but avoiding function/return syntax?

 This is an example using function

   template qs(T){
     T[] qs( T[] items ){
       return items.length==0
         ? items
         : chain(
           qs(items[1..$].filter!(i=> i<items[0] ).array),
           items[0..1],
           qs(items[1..$].filter!(i=> i >= items[0]).array)
         ).array;
     }
 }
I mean... transform this into a lambda expression: T[] qs(T)( T[] items ){ return items.length==0 ? items : chain( qs(items[1..$].filter!(i=> i<items[0] ).array), items[0..1], qs(items[1..$].filter!(i=> i >= items[0]).array) ).array; }
Nov 27 2020
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 11/27/20 9:01 AM, ddcovery wrote:
 On Friday, 27 November 2020 at 16:40:43 UTC, ddcovery wrote:
 ...
 * Can the lambda be transformed to a template (using T instead "int") =
 but avoiding function/return syntax?

 This is an example using function

 =C2=A0 template qs(T){
 =C2=A0=C2=A0=C2=A0 T[] qs( T[] items ){
 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return items.length=3D=3D0
 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ? items
 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 : chain(
 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 qs(items[1..$].=
filter!(i=3D> i<items[0] ).array),
 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 items[0..1],
 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 qs(items[1..$].=
filter!(i=3D> i >=3D items[0]).array)
 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ).array;
 =C2=A0=C2=A0=C2=A0 }
 }
=20 I mean... transform this into a lambda expression: =20 =C2=A0=C2=A0=C2=A0 T[] qs(T)( T[] items ){ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return items.length=3D=3D0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ? items =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 : chain( =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 qs(items[1..$].=
filter!(i=3D> i<items[0] ).array),
  =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 items[0..1],
  =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 qs(items[1..$].=
filter!(i=3D> i >=3D items[0]).array)
  =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ).array;
  =C2=A0=C2=A0=C2=A0 }
=20
This has been done with the Y-combinator, where the lambda refers to=20 itself as 'self': =20 https://github.com/gecko0307/atrium/blob/master/dlib/functional/combinato= rs.d There has been been other discussions on it on these forums. Ali
Nov 27 2020
parent ddcovery <antoniocabreraperez gmail.com> writes:
On Friday, 27 November 2020 at 20:53:37 UTC, Ali Çehreli wrote:

 This has been done with the Y-combinator, where the lambda 
 refers to itself as 'self':


 https://github.com/gecko0307/atrium/blob/master/dlib/functional/combinators.d

 There has been been other discussions on it on these forums.

 Ali
Thanks Ali.
Nov 28 2020