www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Function literals and lambda functions

reply Russel Winder <russel russel.org.uk> writes:
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

OK, this one surprised me, all that remains is for me to find out why it
shouldn't have done:

        reduce ! ( ( a , b ) { return a + b ; } ) ( 0.0 , outputData )=20

works just fine, but:

        reduce ! ( function double ( double a , double b ) { return a + b ;=
 } ) ( 0.0 , outputData )

results in:

        pi_d2_sequentialMap.d(45): Error: function std.algorithm.reduce!(fu=
nction double(double a, double b)
        {
        return a + b;
        }
        ).reduce!(double,Map!(partialSum,Tuple!(int,int,double)[])).reduce.=
__funcliteral1 cannot access frame of function pi_d2_sequentialMap.execute.=
__funcliteral1
        pi_d2_sequentialMap.d(45): Error: function std.algorithm.reduce!(fu=
nction double(double a, double b)
        {
        return a + b;
        }
        ).reduce!(double,Map!(partialSum,Tuple!(int,int,double)[])).reduce.=
__funcliteral1 cannot access frame of function pi_d2_sequentialMap.execute.=
__funcliteral1

which I think qualifies for the label "incomprehensible".  Not to
mention repetitious.


PS  If you ask why not:

        reduce ! ( "a+b" ) ( 0.0 , outputData )
       =20
I find this somehow unacceptable.  It's the string, its not a function.
Fine, my problem, but that still leaves the above.
--=20
Russel.
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D
Dr Russel Winder      t: +44 20 7585 2200   voip: sip:russel.winder ekiga.n=
et
41 Buckmaster Road    m: +44 7770 465 077   xmpp: russel russel.org.uk
London SW11 1EN, UK   w: www.russel.org.uk  skype: russel_winder
Mar 06 2011
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Russel Winder:

         reduce ! ( ( a , b ) { return a + b ; } ) ( 0.0 , outputData ) 
 
 works just fine, but:
 
         reduce ! ( function double ( double a , double b ) { return a + b ; }
) ( 0.0 , outputData )

import std.stdio, std.algorithm, std.range; void main() { auto outputData = iota(1.0, 10.0); auto r1 = reduce!((a, b){ return a + b; })(0.0, outputData); writeln(r1); auto r2 = reduce!((double a, double b){ return a + b; })(0.0, outputData); writeln(r2); auto r3 = reduce!("a + b")(0.0, outputData); writeln(r3); auto r4 = reduce!q{a + b}(0.0, outputData); writeln(r4); auto r5 = reduce!q{a + b}(outputData); // not exactly the same writeln(r5); } Bye, bearophile
Mar 06 2011
next sibling parent KennyTM~ <kennytm gmail.com> writes:
On Mar 7, 11 00:45, Simen kjaeraas wrote:
 Russel Winder <russel russel.org.uk> wrote:

 So why does:

 reduce ! ( function double ( double a , double b ) { return a + b ; }
 ) ( 0.0 , outputData )

 fail? It implies that a function literal and a lambda are significantly
 different things as far as the compiler is concerned.

Well, they are. One is a delegate literal, the other a function literal. Delegates may be closures, functions may not. That said, the above looks like it should work, and I'm not sure why it doesn't.

Probably unaryFun and binaryFun should accept function pointers as well.
Mar 06 2011
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 3/6/11 11:25 AM, Simen kjaeraas wrote:
 Russel Winder <russel russel.org.uk> wrote:

 That said, the above looks like it should work, and I'm not sure why it
 doesn't.

Obviously (now :-) because the context requires a delegate not a function -- it is just that the error message doesn't say that in terms that don't relate to the code they relate to the realization within the compiler.

Yeah, but reduce should accept a function, not just a delegate.

The limitations related to frame pointers should be handled as important bugs. D has innovated a lot in this regard, and I believe that the full potential has yet to be attained. Andrei
Mar 06 2011
prev sibling next sibling parent Russel Winder <russel russel.org.uk> writes:
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

On Sun, 2011-03-06 at 10:08 -0500, bearophile wrote:
 Russel Winder:
=20
         reduce ! ( ( a , b ) { return a + b ; } ) ( 0.0 , outputData )=


=20
 works just fine, but:
=20
         reduce ! ( function double ( double a , double b ) { return a +=


=20
=20
 import std.stdio, std.algorithm, std.range;
=20
 void main() {
     auto outputData =3D iota(1.0, 10.0);
=20
     auto r1 =3D reduce!((a, b){ return a + b; })(0.0, outputData);
     writeln(r1);
=20
     auto r2 =3D reduce!((double a, double b){ return a + b; })(0.0, outpu=

     writeln(r2);
=20
     auto r3 =3D reduce!("a + b")(0.0, outputData);
     writeln(r3);
=20
     auto r4 =3D reduce!q{a + b}(0.0, outputData);
     writeln(r4);
=20
     auto r5 =3D reduce!q{a + b}(outputData); // not exactly the same
     writeln(r5);
 }
=20
 Bye,
 bearophile

So why does: reduce ! ( function double ( double a , double b ) { return a + b ;= } ) ( 0.0 , outputData ) fail? It implies that a function literal and a lambda are significantly different things as far as the compiler is concerned. --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.winder ekiga.n= et 41 Buckmaster Road m: +44 7770 465 077 xmpp: russel russel.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder
Mar 06 2011
prev sibling next sibling parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Russel Winder <russel russel.org.uk> wrote:

 So why does:

         reduce ! ( function double ( double a , double b ) { return a +  
 b ; } ) ( 0.0 , outputData )

 fail?  It implies that a function literal and a lambda are significantly
 different things as far as the compiler is concerned.

Well, they are. One is a delegate literal, the other a function literal. Delegates may be closures, functions may not. That said, the above looks like it should work, and I'm not sure why it doesn't. -- Simen
Mar 06 2011
prev sibling next sibling parent Russel Winder <russel russel.org.uk> writes:
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

On Sun, 2011-03-06 at 17:45 +0100, Simen kjaeraas wrote:
 Russel Winder <russel russel.org.uk> wrote:
=20
 So why does:

         reduce ! ( function double ( double a , double b ) { return a +=


 b ; } ) ( 0.0 , outputData )

 fail?  It implies that a function literal and a lambda are significantl=


 different things as far as the compiler is concerned.

Well, they are. One is a delegate literal, the other a function literal. Delegates may be closures, functions may not.

Hummm... good point. If you s/function/delegate/ in the above it works fine
 That said, the above looks like it should work, and I'm not sure why it
 doesn't.

Obviously (now :-) because the context requires a delegate not a function -- it is just that the error message doesn't say that in terms that don't relate to the code they relate to the realization within the compiler. Is this use of the term delegate consistent with the C# idea of delegate? It certainly is not consistent with the use in Groovy and other dynamic languages.=20 --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.winder ekiga.n= et 41 Buckmaster Road m: +44 7770 465 077 xmpp: russel russel.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder
Mar 06 2011
prev sibling next sibling parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Russel Winder <russel russel.org.uk> wrote:

 That said, the above looks like it should work, and I'm not sure why it
 doesn't.

Obviously (now :-) because the context requires a delegate not a function -- it is just that the error message doesn't say that in terms that don't relate to the code they relate to the realization within the compiler.

Yeah, but reduce should accept a function, not just a delegate.
 Is this use of the term delegate consistent with the C# idea of
 delegate?  It certainly is not consistent with the use in Groovy and
 other dynamic languages.

There's been some discussion of that before, but I cannot remember whence the term comes. Basically, it it chosen because it's a function pointer with a context passed alongside it, and that's no different for a pointer-to-member-function or a closure. And to illustrate the latter: The venerable master Qc Na was walking with his student, Anton. Hoping to prompt the master into a discussion, Anton said "Master, I have heard that objects are a very good thing - is this true?" Qc Na looked pityingly at his student and replied, "Foolish pupil - objects are merely a poor man's closures." Chastised, Anton took his leave from his master and returned to his cell, intent on studying closures. He carefully read the entire "Lambda: The Ultimate..." series of papers and its cousins, and implemented a small Scheme interpreter with a closure-based object system. He learned much, and looked forward to informing his master of his progress. On his next walk with Qc Na, Anton attempted to impress his master by saying "Master, I have diligently studied the matter, and now understand that objects are truly a poor man's closures." Qc Na responded by hitting Anton with his stick, saying "When will you learn? Closures are a poor man's object." At that moment, Anton became enlightened. -- Anton van Straaten -- Simen
Mar 06 2011
prev sibling next sibling parent reply Peter Alexander <peter.alexander.au gmail.com> writes:
On 6/03/11 2:03 PM, Russel Winder wrote:
 PS  If you ask why not:

          reduce ! ( "a+b" ) ( 0.0 , outputData )

 I find this somehow unacceptable.  It's the string, its not a function.
 Fine, my problem, but that still leaves the above.

You probably know this already, but just in case... The string is converted into a function at compile time, so if you were scared of the possible performance hit of having to parse the string at runtime, then you can rest assured that it is as fast as supplying a normal function. On the other hand, if you just don't like the appearance of a string as a function in source code then, yah, I agree. It does seem a little wrong, although you get used to it.
Mar 06 2011
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
retard:

 It also generates a bit of redundant code for each template instantiation.
 No solution for this has been proposed afaik.

From a recent answer, I think Walter hopes in a magic solution for this bunch of problems. In past I have shown some possible attacks against this bunch of problems: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=108136 http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=108275 My theory is that you can't ask the compiler to magically solve this problem, or to produce a ton of templates and them remove most of them and most of the code duplication. A more practical approach is probably needed, and this means using several different ideas to avoid creating templates, etc. One idea: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=126655
  It's a deal breaker in embedded programming.

Don't worry, I don't see people using D for embedded programming soon. D is not designed for this purposes. Today there are no good languages for embedded programming. C is used out of desperation because there is almost nothing else for it. On the other hand "embedded programming" is slowly changing, the available RAM is growing and sometimes even 32 bit CPUs are used (but smaller CPUs are hugely more common still). Thank you retard. Bye, bearophile
Mar 06 2011
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
retard wrote:
 It also generates a bit of redundant code for each template instantiation. 
 No solution for this has been proposed afaik. It's a deal breaker in 
 embedded programming.

Have you tested this to see if multiple copies of the same code wind up in the executable?
Mar 06 2011
prev sibling parent retard <re tard.com.invalid> writes:
Sun, 06 Mar 2011 20:24:12 +0000, Peter Alexander wrote:

 On 6/03/11 2:03 PM, Russel Winder wrote:
 PS  If you ask why not:

          reduce ! ( "a+b" ) ( 0.0 , outputData )

 I find this somehow unacceptable.  It's the string, its not a function.
 Fine, my problem, but that still leaves the above.

You probably know this already, but just in case... The string is converted into a function at compile time, so if you were scared of the possible performance hit of having to parse the string at runtime, then you can rest assured that it is as fast as supplying a normal function. On the other hand, if you just don't like the appearance of a string as a function in source code then, yah, I agree. It does seem a little wrong, although you get used to it.

It also generates a bit of redundant code for each template instantiation. No solution for this has been proposed afaik. It's a deal breaker in embedded programming.
Mar 06 2011