Re: Better lambdas!!!!!!!!!!
On Thursday, 10 September 2015 at 17:55:06 UTC, Prudence wrote: void myfunc(double delegate(int i, int z, float f)) {} myfunc((int i, int z, float f) { return i*z*f; } } You could also write `myfunc((i,z,f) => i*z*f);` right now. The names are easy to do.
Re: Better lambdas!!!!!!!!!!
On 09/10/2015 10:55 AM, Prudence wrote: > How bout this: > > void myfunc(double delegate(int i, int z, float f)) {} > > > myfunc((int i, int z, float f) { return i*z*f; } } > > vs > > myfunc({ return i*z*f; }) // Names of parameters are inferred from > signature. Considering other features of the language, that's pretty much impossible in D. What if there is another i in scope: int i; myfunc({ return i*z*f; }); Now, should it call another overload of myfunc that takes (int z, int f) because i is something else? Should the compiler analyze the body of the code and decide which symbols could be parameters? And then go through all overloads of myfunc? etc.? Ali
Re: Better lambdas!!!!!!!!!!
On Thursday, 10 September 2015 at 17:55:06 UTC, Prudence wrote: Of course, this hides the names outside the lambda, but a warning could be issued(no different than if one does it explicitly. This makes the parameter names part of the API. The author of a library is unable to rename parameter without breaking user code. I do not believe the benefit is large enough to accept such a drawback.
Re: Better lambdas!!!!!!!!!!
On Thursday, 10 September 2015 at 18:05:43 UTC, anonymous wrote: On Thursday, 10 September 2015 at 17:55:06 UTC, Prudence wrote: Of course, this hides the names outside the lambda, but a warning could be issued(no different than if one does it explicitly. This makes the parameter names part of the API. The author of a library is unable to rename parameter without breaking user code. I do not believe the benefit is large enough to accept such a drawback. That's one of the main reasons that I hate the idea of named arguments. It's more stuff that's part of the API, more public stuff that you have to name correctly and risk bikeshedding arguments over, and more stuff that can you can't change without breaking existing code. - Jonathan M Davis
Re: Better lambdas!!!!!!!!!!
On Thursday, 10 September 2015 at 18:23:52 UTC, Jonathan M Davis wrote: On Thursday, 10 September 2015 at 18:05:43 UTC, anonymous wrote: On Thursday, 10 September 2015 at 17:55:06 UTC, Prudence wrote: Of course, this hides the names outside the lambda, but a warning could be issued(no different than if one does it explicitly. This makes the parameter names part of the API. The author of a library is unable to rename parameter without breaking user code. I do not believe the benefit is large enough to accept such a drawback. That's one of the main reasons that I hate the idea of named arguments. It's more stuff that's part of the API, more public stuff that you have to name correctly and risk bikeshedding arguments over, and more stuff that can you can't change without breaking existing code. - Jonathan M Davis +1
Re: Better lambdas!!!!!!!!!!
On Thursday, 10 September 2015 at 17:55:06 UTC, Prudence wrote: by specifying the parameter names in the signature, we don't have to specify them in the lamba creation. This doesn't replace the original way, just adds the ability to infer the names if they are not specified. Of course, this hides the names outside the lambda, but a warning could be issued(no different than if one does it explicitly. How about just having numbered parameters like this: { $2 < ($1*$2) }
Re: Better lambdas!!!!!!!!!!
On Thursday, 10 September 2015 at 19:37:53 UTC, Ola Fosheim Grøstad wrote: How about just having numbered parameters like this: { $2 < ($1*$2) } What about this situation? [[1, 2], [3, 4], [5, 6]].reduce!{ auto localMax = { $1 > $2 ? $1 : $2; } auto first = $1.reduce!localMax; auto second = $2.reduce!localMax; return first > second ? first : second; } How can the compiler tell which $1 and $2 is which? What if one wants to access both the outer $1 and the inner $1 in localMax?
Re: Better lambdas!!!!!!!!!!
On Thursday, 10 September 2015 at 20:10:49 UTC, Meta wrote: On Thursday, 10 September 2015 at 19:37:53 UTC, Ola Fosheim Grøstad wrote: How about just having numbered parameters like this: { $2 < ($1*$2) } What about this situation? [[1, 2], [3, 4], [5, 6]].reduce!{ auto localMax = { $1 > $2 ? $1 : $2; } auto first = $1.reduce!localMax; auto second = $2.reduce!localMax; return first > second ? first : second; } How can the compiler tell which $1 and $2 is which? What if one wants to access both the outer $1 and the inner $1 in localMax? Should be `return first > second ? $1 : $2`, but you get the idea.
Re: Better lambdas!!!!!!!!!!
On Thursday, 10 September 2015 at 19:37:53 UTC, Ola Fosheim Grøstad wrote: How about just having numbered parameters like this: { $2 < ($1*$2) } The string lambdas Phobos supports basically does this: `b < a*b` would work in there. These are falling out of favor with the new syntax in the language, but they are still supported by most the library.
Re: Better lambdas!!!!!!!!!!
On Thursday, 10 September 2015 at 20:51:18 UTC, Adam D. Ruppe wrote: The string lambdas Phobos supports basically does this: `b < a*b` would work in there. These are falling out of favor with the new syntax in the language, but they are still supported by most the library. Isn't that a string mixin? Or?
Re: Better lambdas!!!!!!!!!!
On Thursday, 10 September 2015 at 20:10:49 UTC, Meta wrote: How can the compiler tell which $1 and $2 is which? What if one wants to access both the outer $1 and the inner $1 in localMax? If there is a conflict you should use a regular lambda on the outer one?
Re: Better lambdas!!!!!!!!!!
On Thursday, 10 September 2015 at 20:56:58 UTC, Ola Fosheim Grøstad wrote: If there is a conflict you should use a regular lambda on the outer one? You could, but then doesn't that defeat the point a bit? My example was off-the-cuff, but the point is that we already have a fairly concise lambda syntax, and adding a new type will mean that we have 4 different ways of expressing the same lambda function. It's just not really worth it.
Re: Better lambdas!!!!!!!!!!
On Thursday, 10 September 2015 at 21:03:12 UTC, Meta wrote: On Thursday, 10 September 2015 at 20:56:58 UTC, Ola Fosheim Grøstad wrote: If there is a conflict you should use a regular lambda on the outer one? You could, but then doesn't that defeat the point a bit? My example was off-the-cuff, but the point is that we already have a fairly concise lambda syntax, and adding a new type will mean that we have 4 different ways of expressing the same lambda function. It's just not really worth it. Yes, it is usually it is a bad idea to have many ways to do things. A numbered schema probably should only be used in an innermost scope as a single expression, so if you see "$1" you know the definition stops at the brackets. Apropos one way of doing things: http://www.ozonehouse.com/mark/periodic/ :D
Re: Better lambdas!!!!!!!!!!
On Thursday, 10 September 2015 at 21:03:12 UTC, Meta wrote: On Thursday, 10 September 2015 at 20:56:58 UTC, Ola Fosheim Grøstad wrote: If there is a conflict you should use a regular lambda on the outer one? You could, but then doesn't that defeat the point a bit? My example was off-the-cuff, but the point is that we already have a fairly concise lambda syntax, and adding a new type will mean that we have 4 different ways of expressing the same lambda function. It's just not really worth it. Clojure solved this by disallowing nesting lambdas-with-numbered-arguments: Clojure 1.7.0 user=> (#(+ %1 %2) 1 2) 3 user=> (#(#(+ %1 %2) %2 %1) 1 2) IllegalStateException Nested #()s are not allowed clojure.lang.LispReader$FnReader.invoke (LispReader.java:703) #object[clojure.core$_PLUS_ 0x10fde30a "clojure.core$_PLUS_@10fde30a"] CompilerException java.lang.RuntimeException: Unable to resolve symbol: %1 in this context, compiling:(NO_SOURCE_PATH:0:0) CompilerException java.lang.RuntimeException: Unable to resolve symbol: %2 in this context, compiling:(NO_SOURCE_PATH:0:0) RuntimeException Unmatched delimiter: ) clojure.lang.Util.runtimeException (Util.java:221) CompilerException java.lang.RuntimeException: Unable to resolve symbol: %2 in this context, compiling:(NO_SOURCE_PATH:0:0) CompilerException java.lang.RuntimeException: Unable to resolve symbol: %1 in this context, compiling:(NO_SOURCE_PATH:0:0) RuntimeException Unmatched delimiter: ) clojure.lang.Util.runtimeException (Util.java:221) 1 2 RuntimeException Unmatched delimiter: ) clojure.lang.Util.runtimeException (Util.java:221) Than again, Clojure never was a big advocate of the one-way-of-doing-things approach... At any rate, since string lambdas can usually be used in place of this syntax, and in the cases string lambdas can't be used(because you need something from the scope) it's not THAT hard to use proper lambdas - I see no reason to support it.
Re: Better lambdas!!!!!!!!!!
On Thu, 2015-09-10 at 20:51 +, Adam D. Ruppe via Digitalmars-d wrote: > […] > > The string lambdas Phobos supports basically does this: > > `b < a*b` > > would work in there. These are falling out of favor with the new > syntax in the language, but they are still supported by most the > library. And until some bugs get fixed, you have to use string functions in some places, you cannot use proper function literals :-( -- Russel. = Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.win...@ekiga.net 41 Buckmaster Roadm: +44 7770 465 077 xmpp: rus...@winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder signature.asc Description: This is a digitally signed message part
Re: Better lambdas!!!!!!!!!!
On Friday, 11 September 2015 at 08:02:21 UTC, Russel Winder wrote: On Thu, 2015-09-10 at 20:51 +, Adam D. Ruppe via Digitalmars-d wrote: […] The string lambdas Phobos supports basically does this: `b < a*b` would work in there. These are falling out of favor with the new syntax in the language, but they are still supported by most the library. And until some bugs get fixed, you have to use string functions in some places, you cannot use proper function literals :-( Can you elaborate? Are those bugs logged somewhere?
Re: Better lambdas!!!!!!!!!!
On Fri, 2015-09-11 at 11:32 +, ZombineDev via Digitalmars-d wrote: > On Friday, 11 September 2015 at 08:02:21 UTC, Russel Winder wrote: > > On Thu, 2015-09-10 at 20:51 +, Adam D. Ruppe via > > Digitalmars-d wrote: > > > […] > > > > > > The string lambdas Phobos supports basically does this: > > > > > > `b < a*b` > > > > > > would work in there. These are falling out of favor with the > > > new syntax in the language, but they are still supported by > > > most the library. > > > > And until some bugs get fixed, you have to use string functions > > in some places, you cannot use proper function literals :-( > > Can you elaborate? Are those bugs logged somewhere? For example https://issues.dlang.org/show_bug.cgi?id=5710 The affects a number of the std.parallelism functions :-( -- Russel. = Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.win...@ekiga.net 41 Buckmaster Roadm: +44 7770 465 077 xmpp: rus...@winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder signature.asc Description: This is a digitally signed message part
Re: Better lambdas!!!!!!!!!!
On 09/10/2015 08:23 PM, Jonathan M Davis wrote: That's one of the main reasons that I hate the idea of named arguments. It's more stuff that's part of the API, more public stuff that you have to name correctly and risk bikeshedding arguments over, and more stuff that can you can't change without breaking existing code. - Jonathan M Davis Note that parameter names can already be determined by user code using reflection.
Re: Better lambdas!!!!!!!!!!
On Friday, 11 September 2015 at 11:44:13 UTC, Russel Winder wrote: For example https://issues.dlang.org/show_bug.cgi?id=5710 If C++ interop is still important, maybe it would be a good idea to adopt C++ style lambdas.
Re: Better lambdas!!!!!!!!!!
On Friday, 11 September 2015 at 20:16:42 UTC, Timon Gehr wrote: On 09/10/2015 08:23 PM, Jonathan M Davis wrote: That's one of the main reasons that I hate the idea of named arguments. It's more stuff that's part of the API, more public stuff that you have to name correctly and risk bikeshedding arguments over, and more stuff that can you can't change without breaking existing code. - Jonathan M Davis Note that parameter names can already be determined by user code using reflection. True, but as soon as you're doing much with reflection, all bets are off anyway, because it often becomes trivial to break code by making small changes. And I think that it's pretty clear at this point that you can't expect parameter names to not change, since they're not part of the function signature (even if compile-time reflection does let you get at them), which would not be the case if we had named arguments. - Jonathan M Davis
Re: Better lambdas!!!!!!!!!!
On Friday, 11 September 2015 at 20:25:19 UTC, Ola Fosheim Grøstad wrote: On Friday, 11 September 2015 at 11:44:13 UTC, Russel Winder wrote: For example https://issues.dlang.org/show_bug.cgi?id=5710 If C++ interop is still important, maybe it would be a good idea to adopt C++ style lambdas. How would that help with interop? Even if we supported passing a lambda to C++ code, the syntax wouldn't need to match, just the semantics, and that could be done without adopting C++ style lambdas in D. However, given the complexity of C++ templates, as I understand it, there are no plans to ever support them in C++ interop (since it would pretty much mean putting a C++ compiler in the D compiler), in which case, there's no need to worry about C++ lambdas anyway, because they all involve templates. So, while C++ interop is important, and it's gotten some major improvements in the process of switching to D for the compiler front-end (and will likely continue to get improvements), there are still some pretty severe limits on what we're going to be able to do if we don't want to put a full C++ compiler inside of the D compiler, and we really don't want to be doing that. - Jonathan M Davis
Re: Better lambdas!!!!!!!!!!
On Thursday, 10 September 2015 at 18:02:36 UTC, Ali Çehreli wrote: On 09/10/2015 10:55 AM, Prudence wrote: > How bout this: > > void myfunc(double delegate(int i, int z, float f)) {} > > > myfunc((int i, int z, float f) { return i*z*f; } } > > vs > > myfunc({ return i*z*f; }) // Names of parameters are inferred from > signature. Considering other features of the language, that's pretty much impossible in D. What if there is another i in scope: int i; myfunc({ return i*z*f; }); Now, should it call another overload of myfunc that takes (int z, int f) because i is something else? Should the compiler analyze the body of the code and decide which symbols could be parameters? And then go through all overloads of myfunc? etc.? Ali As I said, it could throw a warning or error. It, in some sense, is already a a problem with nested blocks that hide outside variables, is it not? The compiler doesn't need to scan anything. It knows the which parameters from the definition! -> void myfunc(double delegate(int i, int z, float f)) <- Compiler knows to use the names here as the default names in for the parameters when. when used: myfunc({ return i*z*f; }); <- Oh, there are the names, we know what they are because the signature is tells us. The compiler does the following: 1. Sees we have a block without any parameters defined. i.e., a lambda. 2. It looks up the signature of myfunc to find out what the names are 3. It sees that they are i z and f 4. Now it knows and it effectively rewrites the code as myfunc((i,z,f) { return i*z*f; }); Surely this is not difficult, 4 steps?
Re: Better lambdas!!!!!!!!!!
On Saturday, 12 September 2015 at 01:03:54 UTC, Prudence wrote: On Thursday, 10 September 2015 at 18:02:36 UTC, Ali Çehreli wrote: On 09/10/2015 10:55 AM, Prudence wrote: > How bout this: > > void myfunc(double delegate(int i, int z, float f)) {} > > > myfunc((int i, int z, float f) { return i*z*f; } } > > vs > > myfunc({ return i*z*f; }) // Names of parameters are inferred from > signature. Considering other features of the language, that's pretty much impossible in D. What if there is another i in scope: int i; myfunc({ return i*z*f; }); Now, should it call another overload of myfunc that takes (int z, int f) because i is something else? Should the compiler analyze the body of the code and decide which symbols could be parameters? And then go through all overloads of myfunc? etc.? Ali As I said, it could throw a warning or error. It, in some sense, is already a a problem with nested blocks that hide outside variables, is it not? The compiler doesn't need to scan anything. It knows the which parameters from the definition! -> void myfunc(double delegate(int i, int z, float f)) <- Compiler knows to use the names here as the default names in for the parameters when. when used: myfunc({ return i*z*f; }); <- Oh, there are the names, we know what they are because the signature is tells us. The compiler does the following: 1. Sees we have a block without any parameters defined. i.e., a lambda. 2. It looks up the signature of myfunc to find out what the names are 3. It sees that they are i z and f 4. Now it knows and it effectively rewrites the code as myfunc((i,z,f) { return i*z*f; }); Surely this is not difficult, 4 steps? You're making your code more brittle for a small gain. The suggestion makes parameter usage order important and the compiler can't warn about my typos. Consider: myfunc({return "x:"~x~"y:"-y;}) getting changed to myfunc({return "y:"~y~"x:"~x;}); Or the typo in myfunc({return i*z+f*j;}); Lambdas are already very concise. This proposal doesn't give any benefits outside of very simple lambdas. Such lambdas are already so simple that they could use some standard functions instead (like sum, to!T, and bind).
Re: Better lambdas!!!!!!!!!!
On Saturday, 12 September 2015 at 02:13:11 UTC, Pierre Krafft wrote: On Saturday, 12 September 2015 at 01:03:54 UTC, Prudence wrote: On Thursday, 10 September 2015 at 18:02:36 UTC, Ali Çehreli wrote: On 09/10/2015 10:55 AM, Prudence wrote: > How bout this: > > void myfunc(double delegate(int i, int z, float f)) {} > > > myfunc((int i, int z, float f) { return i*z*f; } } > > vs > > myfunc({ return i*z*f; }) // Names of parameters are inferred from > signature. Considering other features of the language, that's pretty much impossible in D. What if there is another i in scope: int i; myfunc({ return i*z*f; }); Now, should it call another overload of myfunc that takes (int z, int f) because i is something else? Should the compiler analyze the body of the code and decide which symbols could be parameters? And then go through all overloads of myfunc? etc.? Ali As I said, it could throw a warning or error. It, in some sense, is already a a problem with nested blocks that hide outside variables, is it not? The compiler doesn't need to scan anything. It knows the which parameters from the definition! -> void myfunc(double delegate(int i, int z, float f)) <- Compiler knows to use the names here as the default names in for the parameters when. when used: myfunc({ return i*z*f; }); <- Oh, there are the names, we know what they are because the signature is tells us. The compiler does the following: 1. Sees we have a block without any parameters defined. i.e., a lambda. 2. It looks up the signature of myfunc to find out what the names are 3. It sees that they are i z and f 4. Now it knows and it effectively rewrites the code as myfunc((i,z,f) { return i*z*f; }); Surely this is not difficult, 4 steps? You're making your code more brittle for a small gain. The suggestion makes parameter usage order important and the compiler can't warn about my typos. Consider: myfunc({return "x:"~x~"y:"-y;}) getting changed to myfunc({return "y:"~y~"x:"~x;}); Or the typo in myfunc({return i*z+f*j;}); Lambdas are already very concise. This proposal doesn't give any benefits outside of very simple lambdas. Such lambdas are already so simple that they could use some standard functions instead (like sum, to!T, and bind). What does this have to do with my proposal? Those issues exist regardless of the simplification. myfunc({return "x:"~x~"y:"-y;}) getting changed to myfunc({return "y:"~y~"x:"~x;}); huh? What do you mean the suggestion makes parameter usage order important? They are important, it has nothing to do with the suggestion? Are you saying that you want to reserve the right to do something like myfunc(string delegate(string x, string y)); and myfunc((y,x){ "y:"~y~"x:"~x; }) ? If so, or unless I'm missing something, that's bad no matter what. Changing the order and reversing the names is more than just confusing, it's hard to read and most people will gloss over that fact. Be consistent with your parameters and maybe you'll have less bugs? Or the typo in myfunc({return i*z+f*j;}); Again, what does this have to do with anything? A typo is a typo and is always a mistake. The above example has the same effect regardless if the parameters are explicit or deduced. myfunc((i,z,f) {return i*z+f*j;}); j is still a problem. If j is defined outside the lambda then regardless of specific or implicit parameter names, it will not cause any problems. In either case, the compiler can see that j is either referenced outside the scope or undefined. It has nothing to do with the parameters used. Of course maybe I'm missing something, but essentially are not almost all uses of lambda's simply copying the parameter signature of the delegate. It already infers types... you could say that leads to typo's too...
Re: Better lambdas!!!!!!!!!!
On Friday, 11 September 2015 at 23:15:58 UTC, Jonathan M Davis wrote: style lambdas in D. However, given the complexity of C++ templates, as I understand it, there are no plans to ever support them in C++ interop (since it would pretty much mean putting a C++ compiler in the D compiler), in which case, there's no need to worry about C++ lambdas anyway, because they all involve templates. No, you have to generate c++ sourcecode. No need to build in the compiler.
Re: Better lambdas!!!!!!!!!!
On Saturday, 12 September 2015 at 03:32:51 UTC, Prudence wrote: On Saturday, 12 September 2015 at 02:13:11 UTC, Pierre Krafft wrote: On Saturday, 12 September 2015 at 01:03:54 UTC, Prudence wrote: On Thursday, 10 September 2015 at 18:02:36 UTC, Ali Çehreli wrote: On 09/10/2015 10:55 AM, Prudence wrote: > How bout this: > > void myfunc(double delegate(int i, int z, float f)) {} > > > myfunc((int i, int z, float f) { return i*z*f; } } > > vs > > myfunc({ return i*z*f; }) // Names of parameters are inferred from > signature. Considering other features of the language, that's pretty much impossible in D. What if there is another i in scope: int i; myfunc({ return i*z*f; }); Now, should it call another overload of myfunc that takes (int z, int f) because i is something else? Should the compiler analyze the body of the code and decide which symbols could be parameters? And then go through all overloads of myfunc? etc.? Ali As I said, it could throw a warning or error. It, in some sense, is already a a problem with nested blocks that hide outside variables, is it not? The compiler doesn't need to scan anything. It knows the which parameters from the definition! -> void myfunc(double delegate(int i, int z, float f)) <- Compiler knows to use the names here as the default names in for the parameters when. when used: myfunc({ return i*z*f; }); <- Oh, there are the names, we know what they are because the signature is tells us. The compiler does the following: 1. Sees we have a block without any parameters defined. i.e., a lambda. 2. It looks up the signature of myfunc to find out what the names are 3. It sees that they are i z and f 4. Now it knows and it effectively rewrites the code as myfunc((i,z,f) { return i*z*f; }); Surely this is not difficult, 4 steps? You're making your code more brittle for a small gain. The suggestion makes parameter usage order important and the compiler can't warn about my typos. Consider: myfunc({return "x:"~x~"y:"-y;}) getting changed to myfunc({return "y:"~y~"x:"~x;}); Or the typo in myfunc({return i*z+f*j;}); Lambdas are already very concise. This proposal doesn't give any benefits outside of very simple lambdas. Such lambdas are already so simple that they could use some standard functions instead (like sum, to!T, and bind). What does this have to do with my proposal? Those issues exist regardless of the simplification. myfunc({return "x:"~x~"y:"-y;}) getting changed to myfunc({return "y:"~y~"x:"~x;}); huh? What do you mean the suggestion makes parameter usage order important? They are important, it has nothing to do with the suggestion? Are you saying that you want to reserve the right to do something like myfunc(string delegate(string x, string y)); and myfunc((y,x){ "y:"~y~"x:"~x; }) ? If so, or unless I'm missing something, that's bad no matter what. Changing the order and reversing the names is more than just confusing, it's hard to read and most people will gloss over that fact. Be consistent with your parameters and maybe you'll have less bugs? Or the typo in myfunc({return i*z+f*j;}); Again, what does this have to do with anything? A typo is a typo and is always a mistake. The above example has the same effect regardless if the parameters are explicit or deduced. myfunc((i,z,f) {return i*z+f*j;}); j is still a problem. If j is defined outside the lambda then regardless of specific or implicit parameter names, it will not cause any problems. In either case, the compiler can see that j is either referenced outside the scope or undefined. It has nothing to do with the parameters used. Of course maybe I'm missing something, but essentially are not almost all uses of lambda's simply copying the parameter signature of the delegate. It already infers types... you could say that leads to typo's too... myfunc({return "x:"~x~"y:"-y;}); is infered to mean myfunc((x,y){return "x:"~x~"y:"-y;}); while myfunc({return "y:"~y~"x:"~x;}); is infered to mean myfunc((y,x){return "y:"~y~"x:"~x;}); which is not what I expect since the lambda I want is myfunc((x,y){return "y:"~y~"x:"~x;}); This can lead to subtle bugs which are very hard to see. In the typo example there could be two overloaded functions differing only in that one takes a delegate having 3 parameters and one taking a delegate having 4 parameters. If we explicitly write the lambda parameters the typo will be found since j is undefined. But when parameters are inferred the compiler will see that {return i*z + f*j;} matches the function taking a lambda with 4 parameters. Inferred parameter types are on the brink of what I can allow. They can risk typos, but not as easily since you write the parameters twice (declaration and usage). They can also silently change if the function taking the delegate has the parameter type changed. I don't want to add more magic to that area.
Re: Better lambdas!!!!!!!!!!
On Saturday, 12 September 2015 at 10:44:05 UTC, Pierre Krafft wrote: myfunc({return "x:"~x~"y:"-y;}); is infered to mean myfunc((x,y){return "x:"~x~"y:"-y;}); while myfunc({return "y:"~y~"x:"~x;}); is infered to mean myfunc((y,x){return "y:"~y~"x:"~x;}); which is not what I expect since the lambda I want is myfunc((x,y){return "y:"~y~"x:"~x;}); This can lead to subtle bugs which are very hard to see. I don't think this is what the OP was suggesting. As far as I understand, the suggestion was that the lambda's arguments would be inferred from the function argument in higher order's function signature - not from the ones used in the lambda's body as you suggest. So, `myfunc` will be declared as: void myfunc(string delegate(string x, string y)) { // ... And when the compiler see `myfunc({return "x:"~x~"y:"-y;});`, it'll see that `x` and `y` appear in the function argument's definition and match them accordingly. This means that `myfunc({/*...*/})` will be inferred to `myfunc((x,y) {/*...*/})` no matter what the order of argument usage in the lambda's body is - because in the function's signature the arguments are `x` and `y` in that order.
Re: Better lambdas!!!!!!!!!!
On 2015-09-10 20:23, Jonathan M Davis wrote: That's one of the main reasons that I hate the idea of named arguments. In Ruby named arguments need to be explicitly requested when declaring a method: def bar(a) a == { a: 3 } # A hash (associative array) end def foo(a:) a == 3 end foo(a: 3) bar(a: 3) Not supplying the name of the parameter in the call to "foo" would result in an error. I think named arguments like this is way, _way_ more superior that the ridiculous idea of using an enum instead of a bool. -- /Jacob Carlborg
Re: Better lambdas!!!!!!!!!!
On 2015-09-10 23:03, Meta wrote: You could, but then doesn't that defeat the point a bit? No, I don't think it does. For example in Scala you can do like this: foo(_ < _) Which would be the same as: foo((a, b) a < b) But if you want to use the same parameter more than once then you cannot use the first syntax. -- /Jacob Carlborg
Re: Better lambdas!!!!!!!!!!
On Saturday, 12 September 2015 at 14:40:05 UTC, Jacob Carlborg wrote: Not supplying the name of the parameter in the call to "foo" would result in an error. Python has similar semantics. Very useful to force explicitness when you have complex changing APIs that have many parameters of the same type "add_row(string,string,string,string,string,string)" But it is a bit different than using named variables in a lambda, since in the lambda case it will shadow local variables.
Re: Better lambdas!!!!!!!!!!
On Saturday, 12 September 2015 at 10:44:05 UTC, Pierre Krafft wrote: On Saturday, 12 September 2015 at 03:32:51 UTC, Prudence wrote: On Saturday, 12 September 2015 at 02:13:11 UTC, Pierre Krafft wrote: On Saturday, 12 September 2015 at 01:03:54 UTC, Prudence wrote: On Thursday, 10 September 2015 at 18:02:36 UTC, Ali Çehreli wrote: On 09/10/2015 10:55 AM, Prudence wrote: > How bout this: > > void myfunc(double delegate(int i, int z, float f)) {} > > > myfunc((int i, int z, float f) { return i*z*f; } } > > vs > > myfunc({ return i*z*f; }) // Names of parameters are inferred from > signature. Considering other features of the language, that's pretty much impossible in D. What if there is another i in scope: int i; myfunc({ return i*z*f; }); Now, should it call another overload of myfunc that takes (int z, int f) because i is something else? Should the compiler analyze the body of the code and decide which symbols could be parameters? And then go through all overloads of myfunc? etc.? Ali As I said, it could throw a warning or error. It, in some sense, is already a a problem with nested blocks that hide outside variables, is it not? The compiler doesn't need to scan anything. It knows the which parameters from the definition! -> void myfunc(double delegate(int i, int z, float f)) <- Compiler knows to use the names here as the default names in for the parameters when. when used: myfunc({ return i*z*f; }); <- Oh, there are the names, we know what they are because the signature is tells us. The compiler does the following: 1. Sees we have a block without any parameters defined. i.e., a lambda. 2. It looks up the signature of myfunc to find out what the names are 3. It sees that they are i z and f 4. Now it knows and it effectively rewrites the code as myfunc((i,z,f) { return i*z*f; }); Surely this is not difficult, 4 steps? You're making your code more brittle for a small gain. The suggestion makes parameter usage order important and the compiler can't warn about my typos. Consider: myfunc({return "x:"~x~"y:"-y;}) getting changed to myfunc({return "y:"~y~"x:"~x;}); Or the typo in myfunc({return i*z+f*j;}); Lambdas are already very concise. This proposal doesn't give any benefits outside of very simple lambdas. Such lambdas are already so simple that they could use some standard functions instead (like sum, to!T, and bind). What does this have to do with my proposal? Those issues exist regardless of the simplification. myfunc({return "x:"~x~"y:"-y;}) getting changed to myfunc({return "y:"~y~"x:"~x;}); huh? What do you mean the suggestion makes parameter usage order important? They are important, it has nothing to do with the suggestion? Are you saying that you want to reserve the right to do something like myfunc(string delegate(string x, string y)); and myfunc((y,x){ "y:"~y~"x:"~x; }) ? If so, or unless I'm missing something, that's bad no matter what. Changing the order and reversing the names is more than just confusing, it's hard to read and most people will gloss over that fact. Be consistent with your parameters and maybe you'll have less bugs? Or the typo in myfunc({return i*z+f*j;}); Again, what does this have to do with anything? A typo is a typo and is always a mistake. The above example has the same effect regardless if the parameters are explicit or deduced. myfunc((i,z,f) {return i*z+f*j;}); j is still a problem. If j is defined outside the lambda then regardless of specific or implicit parameter names, it will not cause any problems. In either case, the compiler can see that j is either referenced outside the scope or undefined. It has nothing to do with the parameters used. Of course maybe I'm missing something, but essentially are not almost all uses of lambda's simply copying the parameter signature of the delegate. It already infers types... you could say that leads to typo's too... myfunc({return "x:"~x~"y:"-y;}); is infered to mean myfunc((x,y){return "x:"~x~"y:"-y;}); while myfunc({return "y:"~y~"x:"~x;}); is infered to mean myfunc((y,x){return "y:"~y~"x:"~x;}); which is not what I expect since the lambda I want is myfunc((x,y){return "y:"~y~"x:"~x;}); This can lead to subtle bugs which are very hard to see. In the typo example there could be two overloaded functions differing only in that one takes a delegate having 3 parameters and one taking a delegate having 4 parameters. If we explicitly write the lambda parameters the typo will be found since j is undefined. But when parameters are inferred the compiler will see that {return i*z + f*j;} matches the function taking a lambda with 4 parameters. Inferred parameter types are on the brink of what I can allow. They can risk typos, but not as easily since you write the parameters twice (declaration and usage). They can also silently change if the function taking the delegate has the parameter type changed. I don't want