## digitalmars.D - Function literals and lambda functions

• Russel Winder (40/40) Mar 06 2011 OK, this one surprised me, all that remains is for me to find out why it
• bearophile (17/22) Mar 06 2011 import std.stdio, std.algorithm, std.range;
• Russel Winder (19/51) Mar 06 2011 b ; } ) ( 0.0 , outputData )
• Simen kjaeraas (7/12) Mar 06 2011 Well, they are. One is a delegate literal, the other a function literal.
• Russel Winder (22/36) Mar 06 2011 y
• Simen kjaeraas (25/34) Mar 06 2011 There's been some discussion of that before, but I cannot remember whenc...
• Andrei Alexandrescu (5/14) Mar 06 2011 The limitations related to frame pointers should be handled as important...
• KennyTM~ (2/14) Mar 06 2011 Probably unaryFun and binaryFun should accept function pointers as well.
• Peter Alexander (9/13) Mar 06 2011 You probably know this already, but just in case...
• retard (4/22) Mar 06 2011 It also generates a bit of redundant code for each template instantiatio...
• bearophile (11/14) Mar 06 2011 From a recent answer, I think Walter hopes in a magic solution for this ...
• Walter Bright (3/6) Mar 06 2011 Have you tested this to see if multiple copies of the same code wind up ...
Russel Winder <russel russel.org.uk> writes:
```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
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
Russel Winder <russel russel.org.uk> writes:
```On Sun, 2011-03-06 at 10:08 -0500, bearophile wrote:
Russel Winder:
=20
reduce ! ( ( a , b ) { return a + b ; } ) ( 0.0 , outputData )=

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

b ; } ) ( 0.0 , outputData )
=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=

tData);
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
"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
Russel Winder <russel russel.org.uk> writes:
```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 +=

=20
b ; } ) ( 0.0 , outputData )

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

y
different things as far as the compiler is concerned.

=20
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
"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
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
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
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
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
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
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