www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - delegates, lambdas and functions pitfall

reply dom <dschoerk gmx.at> writes:
I am about to write my own stupid and simple http client .. and i 
have added a callback function that has the received content as a 
parameter.

class AsyncHttpGet
{
     this(string host, ushort port, string path, void 
delegate(string) callback )
     { ... }
}

My first attempt was to write:

auto f = new AsyncHttpGet("www.dprogramming.com", 80, 
"/index.php", (string content) => {
   ...
});

but this is does not work because my AsyncHttpGet takes a normal 
delegate and this => seems to add nothrow  nogc  safe to my 
delegate type.

The correct syntax is only marginally differnt, but took me quite 
a while to figure out:
( the missing arrow )

auto f = new AsyncHttpGet("www.dprogramming.com", 80, 
"/index.php", (string content)
{
  ... // this is of type function
});

i noticed that delegates are "more powerful" than functions. once 
the passed function e.g. needs to capture a value from the 
outside it becomes a delegate type. I have also read that a 
delegate can contain a reference to a class method bound to an 
instance.

int dummy = 0;
auto f = new AsyncHttpGet("www.dprogramming.com", 80, 
"/index.php", (string content)
{
  dummy = 1; // this is of type delegate
});

but what is the difference between a lambda (=>) and a 
functions/delegates?
i think this is a major pitfall for newcomers, and should be 
adressed somehow.
Sep 05 2016
next sibling parent Daniel Kozak via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
Dne 5.9.2016 v 14:15 dom via Digitalmars-d-learn napsal(a):

 I am about to write my own stupid and simple http client .. and i have 
 added a callback function that has the received content as a parameter.

 class AsyncHttpGet
 {
     this(string host, ushort port, string path, void delegate(string) 
 callback )
     { ... }
 }

 My first attempt was to write:

 auto f = new AsyncHttpGet("www.dprogramming.com", 80, "/index.php", 
 (string content) => {
   ...
 });

 but this is does not work because my AsyncHttpGet takes a normal 
 delegate and this => seems to add nothrow  nogc  safe to my delegate 
 type.

 The correct syntax is only marginally differnt, but took me quite a 
 while to figure out:
 ( the missing arrow )

 auto f = new AsyncHttpGet("www.dprogramming.com", 80, "/index.php", 
 (string content)
 {
  ... // this is of type function
 });

 i noticed that delegates are "more powerful" than functions. once the 
 passed function e.g. needs to capture a value from the outside it 
 becomes a delegate type. I have also read that a delegate can contain 
 a reference to a class method bound to an instance.

 int dummy = 0;
 auto f = new AsyncHttpGet("www.dprogramming.com", 80, "/index.php", 
 (string content)
 {
  dummy = 1; // this is of type delegate
 });

 but what is the difference between a lambda (=>) and a 
 functions/delegates?
 i think this is a major pitfall for newcomers, and should be adressed 
 somehow.
(string content) => { } // this is delegate which returns another delegates {} is shorthand here for (){} when you use => syntax you can just return expression (string content) => content; is same as (string content) { return content; }
Sep 05 2016
prev sibling next sibling parent reply Daniel Kozak via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
Dne 5.9.2016 v 14:15 dom via Digitalmars-d-learn napsal(a):
 ...
 but what is the difference between a lambda (=>) and a 
 functions/delegates?
 i think this is a major pitfall for newcomers, and should be adressed 
 somehow.
Yes, RTFM :)
Sep 05 2016
parent dom <dschoerk gmx.at> writes:
On Monday, 5 September 2016 at 12:30:37 UTC, Daniel Kozak wrote:
 Dne 5.9.2016 v 14:15 dom via Digitalmars-d-learn napsal(a):
 ...
 but what is the difference between a lambda (=>) and a 
 functions/delegates?
 i think this is a major pitfall for newcomers, and should be 
 adressed somehow.
Yes, RTFM :)
yes you are right, but laziness you know :D those pages aren't especially beginner friendly x) https://dlang.org/spec/expression.html#Lambda
Sep 05 2016
prev sibling next sibling parent Daniel Kozak via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
Dne 5.9.2016 v 14:30 Daniel Kozak napsal(a):

 Dne 5.9.2016 v 14:15 dom via Digitalmars-d-learn napsal(a):
 ...
 but what is the difference between a lambda (=>) and a 
 functions/delegates?
 i think this is a major pitfall for newcomers, and should be adressed 
 somehow.
Yes, RTFM :)
But to be fair I have made this mistake myself many times :)
Sep 05 2016
prev sibling parent reply Lodovico Giaretta <lodovico giaretart.net> writes:
On Monday, 5 September 2016 at 12:15:35 UTC, dom wrote:
 [...]
You misunderstood the error message and the lambda syntax (it also happened to me the first time). The grammar says that you can use one of these syntaxes: 1) `(arguments) {block of code}` 2) `(arguments) => expression`, which is equivalent to `(arguments) {return expression;}` 3) `{block of code}`, which is equivalent to `(){block of code}`. So if you write `(arguments) => {block of code}`, this is equivalent to (see rule 2) `(arguments) { return {block of code}; }`. And because of rule 3, it becomes `(arguments) { return (){block of code} }`. So what you have is a function that returns a function. That's why it does not match your signature. The fact that the compiler also adds nothrow, nogc, safe is not important in this case, as those attributes can be implicitly casted away.
Sep 05 2016
parent dom <dschoerk gmx.at> writes:
On Monday, 5 September 2016 at 12:32:49 UTC, Lodovico Giaretta 
wrote:
 On Monday, 5 September 2016 at 12:15:35 UTC, dom wrote:
 [...]
You misunderstood the error message and the lambda syntax (it also happened to me the first time). The grammar says that you can use one of these syntaxes: 1) `(arguments) {block of code}` 2) `(arguments) => expression`, which is equivalent to `(arguments) {return expression;}` 3) `{block of code}`, which is equivalent to `(){block of code}`. So if you write `(arguments) => {block of code}`, this is equivalent to (see rule 2) `(arguments) { return {block of code}; }`. And because of rule 3, it becomes `(arguments) { return (){block of code} }`. So what you have is a function that returns a function. That's why it does not match your signature. The fact that the compiler also adds nothrow, nogc, safe is not important in this case, as those attributes can be implicitly casted away.
thank you for that detailed answer.
Sep 05 2016