digitalmars.D - Anonymous function syntax
- Walter Bright (23/23) Sep 21 2011 I've collected a few from various languages for comparison:
- bearophile (13/17) Sep 21 2011 In D to define a true lambda you need types too:
- deadalnix (6/15) Sep 21 2011 That would be less readable for somebody coming from a C styled
- Adam Ruppe (3/5) Sep 21 2011 Indeed! I find most the proposed lambdas to look like random noise.
- Timon Gehr (19/38) Sep 21 2011 If you leave types away, you in fact create a function template literal....
- Andrei Alexandrescu (3/8) Sep 21 2011 No.
- Jacob Carlborg (17/28) Sep 22 2011 void foo (int delegate (int, int) a){}
- Andrei Alexandrescu (3/31) Sep 22 2011 That's a bug in the compiler.
- Jacob Carlborg (4/39) Sep 22 2011 Ok, has that been reported?
- Andrei Alexandrescu (3/26) Sep 22 2011 Yes :o). http://d.puremagic.com/issues/show_bug.cgi?id=6714
- bearophile (4/5) Sep 22 2011 Thank you for adding it, and sorry for not filing it myself in past.
- Jesse Phillips (4/14) Sep 21 2011 This is true of C# too and I think is appropriate to mention, though it
- Walter Bright (3/13) Sep 22 2011 As Andrei pointed out, it is not true of D, since D does not require the...
- Max Klyga (23/23) Sep 21 2011 Actually Scala doesn't need type declarations in labmda literals. Most
- Walter Bright (2/4) Sep 22 2011 It does, and it is awesome!
- Timon Gehr (4/8) Sep 22 2011 Indeed, but it currently only works if the delegate literal is a
- Walter Bright (2/4) Sep 22 2011 It gets internally rewritten into being a template function.
- Andrei Alexandrescu (4/8) Sep 22 2011 C++'s lambdas require the types to be present, which some consider a
- Jacob Carlborg (8/31) Sep 22 2011 Scala also has this syntax that can be useful sometimes:
- Andrei Alexandrescu (3/5) Sep 22 2011 Already does. We're looking for a briefer syntax.
- pillsy (12/16) Sep 22 2011 What is the problem with just inferring the `return`, allowing you to re...
- Andrei Alexandrescu (10/25) Sep 22 2011 The objection is that it introduces a number of questions:
- pillsy (16/34) Sep 22 2011 At the risk of relitigating a long-settled issue, I think there are good...
- Walter Bright (2/8) Sep 22 2011 Besides just looking awfully hackish.
- Lutger Blijdestijn (7/34) Sep 22 2011 As an alternative, a brief syntax could just be restricted to lambda
- Jacob Carlborg (5/30) Sep 22 2011 I function/delegate that returns a value should be implicitly converted
- Walter Bright (6/8) Sep 22 2011 That doesn't work in some cases - consider a function that returns an ob...
- Timon Gehr (3/13) Sep 22 2011 The compiler could insert a thunk that discards the result if the two
- Jacob Carlborg (21/31) Sep 22 2011 What I'm saying is that you can ignore the returned value of a delegate
- Daniel Murphy (9/21) Sep 22 2011 I can see the appeal, but the abi makes it difficult. As Walter said, w...
- Jacob Carlborg (5/29) Sep 22 2011 Why can't the compiler do something similar automatically. Then we won't...
- Walter Bright (6/10) Sep 23 2011 1. This can get arbitrarily expensive if there are parameters involved (...
- Jacob Carlborg (6/20) Sep 23 2011 Maybe, but so could not using the returned value as well.
- travert phare.normalesup.org (Christophe) (21/42) Sep 23 2011 I think such shortcut should be allowed only for one-liners. There is no...
- travert phare.normalesup.org (Christophe) (16/20) Sep 22 2011 Few ideas:
- Jacob Carlborg (12/35) Sep 22 2011 I vote for the Scala/C# syntax. It's worth noting there's a couple of
- Jesse Phillips (6/18) Sep 22 2011 The only issue I have with current syntax is return. The type inferring ...
- Andrei Alexandrescu (33/34) Sep 22 2011 [snip]
- Andrei Alexandrescu (18/22) Sep 22 2011 [snip]
- bearophile (4/5) Sep 22 2011 Are you willing to explain me why, and show an use case?
- Andrei Alexandrescu (5/8) Sep 22 2011 An important application is optimizing for specific lambdas (e.g.
- pillsy (8/16) Sep 23 2011 Is there some reason this isn't better handled through templating
- Andrei Alexandrescu (4/20) Sep 23 2011 Forgot to mention - the comparison should work statically, i.e. inside a...
- Daniel Murphy (7/17) Sep 23 2011 I think this is better handled by a library solution - define standard
- Jacob Carlborg (13/18) Sep 22 2011 When using lambdas as event handlers:
- Steven Schveighoffer (4/8) Sep 22 2011 Am I missing something here?
- Andrei Alexandrescu (4/14) Sep 22 2011 I am. The rewrite should be:
- Cristi Cobzarenco (7/18) Sep 22 2011 ---
- Walter Bright (2/12) Sep 22 2011 I like easy rewrites!
- dsimcha (6/108) Sep 22 2011 I'd much rather see the bugs in the current lambda syntax get fixed (e.g...
- Andrei Alexandrescu (11/14) Sep 22 2011 That's not an either-or choice, and of course improving current lambdas
- Jonathan M Davis (12/27) Sep 22 2011 It wouldn't hurt my feelings any if an abbreviated lambda syntax weren't...
- Jacob Carlborg (17/51) Sep 22 2011 I like it.
- travert phare.normalesup.org (Christophe) (10/93) Sep 23 2011 No, we should not kill a good syntax idea by giving ways to abuse it
- Jacob Carlborg (5/96) Sep 23 2011 Yeah, I know.
- zeljkog (6/6) Sep 23 2011 While we are about rewrites, it would be nice one:
- travert phare.normalesup.org (Christophe) (2/11) Sep 23 2011 I quite like it.
- Martin Nowak (67/101) Sep 23 2011 I want to add some points against introducing this particular syntax.
- Andrei Alexandrescu (9/58) Sep 23 2011 I don't understand the point being made here.
- Jonathan M Davis (16/27) Sep 23 2011 And Andrei's suggested syntax is very similar to C#'s lambda syntax, so ...
- John Chapman (4/20) Sep 24 2011 Java's adopting the C# syntax for its lambdas too.
- Jonathan M Davis (14/40) Sep 24 2011 I definitely agree with the reasoning given in the article:
- Jacob Carlborg (4/31) Sep 24 2011 --
- Martin Nowak (43/115) Sep 24 2011 => looks like an infix operator. It harder to distinguish in a parameter...
- travert phare.normalesup.org (Christophe) (25/59) Sep 27 2011 this is a compile time error, because you are appending an int (a+5)
- Caligo (4/4) Sep 28 2011 Is there a reason why a new syntax is needed for anonymous function? Ca...
- bearophile (4/5) Sep 28 2011 In my not humble opinion C++0x lambdas are over-engineered (but they go ...
- Peter Alexander (5/10) Sep 24 2011 Just wanted to jump in here and mention that Java is probably going to
- travert phare.normalesup.org (Christophe) (11/13) Sep 27 2011 I may repeat myself, but I think -> is a better symbol than =>. => is
- Alix Pexton (9/9) Sep 24 2011 What are the pros and cons of using "=>" rather than "->"?
- Timon Gehr (5/14) Sep 24 2011 Both would work, but => and -> both can read as "implies", in which case...
- Mafi (7/41) Sep 25 2011 If we decide to add something like this, the => 'operator' has in my
- Timon Gehr (9/75) Sep 25 2011 It cannot have higher precedence than !, because then your example would...
- Jason House (11/46) Sep 22 2011 std.algorithm already introduces a sort of lambda syntax...
- Robert Jacques (10/20) Sep 22 2011 I like the idea, although 1,2,3 and 5 are too close to valid D syntax fo...
- bearophile (4/8) Sep 22 2011 Right, it's a bit too much magical and inflexible for my taste.
- Alex_Dovhal (9/12) Sep 23 2011 Nice.
- Alex_Dovhal (3/4) Sep 23 2011 Sorry, my mistake
- Robert Jacques (8/21) Sep 23 2011 Well, actually, this is Jason's proposal and it's explicitly for a std.a...
- Alex_Dovhal (21/32) Sep 24 2011 Maybe, x=>f(x) syntax isn't bad, but in most simple and most oftern case...
- Robert Jacques (5/39) Sep 24 2011 How is !() different from !\; ? \; is for literals. Hence, it would work...
- hhaammaadd (2/5) Sep 22 2011 I prefer to make "return" optional as the argument type
- Alvaro (6/29) Sep 24 2011 Just for the record, Vala also uses
I've collected a few from various languages for comparison: D (a,b) { return a + b; } Ruby ->(a,b) { a + b } C++0x [](int a, int b) { return a + b; } (a,b) => a + b Scala (a:Int, b:Int) => a + b Erlang fun(a, b) -> a + b end. Haskell \a b -> a + b Javascript function(a,b) { return a + b; } Clojure Lua function(a,b) return a + b end Python lambda a,b: a + b
Sep 21 2011
Walter Bright:D (a,b) { return a + b; }In D to define a true lambda you need types too: auto f = (int a,int b){ return a + b; }; For D I think I'd like a syntax like: { int a, int b => a + b } That in some cases becomes just: { a,b => a + b }Haskell \a b -> a + bIn Haskell you often don't use lambdas. You curry functions, or your use already written little higher order functions/operators to build something, or sometimes you use list comprehensions: http://www.haskell.org/haskellwiki/List_comprehension take 10 [ (i,j) | i <- [1..], let k = i*i, j <- [1..k]] In Python too you often use list comprehensions instead of lambdas + filter + map. Bye, bearophile
Sep 21 2011
Le 22/09/2011 00:29, bearophile a écrit :Walter Bright:That would be less readable for somebody coming from a C styled language. Curly braces for body and parenthesis for arguments is something very familiar. This makes Javascript's and D's closures the most readable for somebody having this background.D (a,b) { return a + b; }In D to define a true lambda you need types too: auto f = (int a,int b){ return a + b; }; For D I think I'd like a syntax like: { int a, int b => a + b } That in some cases becomes just: { a,b => a + b }
Sep 21 2011
deadalnix wrote:This makes Javascript's and D's closures the most readable for somebody having this background.Indeed! I find most the proposed lambdas to look like random noise. D has it good just how it is.
Sep 21 2011
On 09/22/2011 12:47 AM, deadalnix wrote:Le 22/09/2011 00:29, bearophile a écrit :If you leave types away, you in fact create a function template literal. Interestingly those only work for templates so far. I'd like them to work at other places, eg when the argument types are clear from the type signature of a function the delegate gets passed to. void foo(int delegate(int)){} void main(){ foo((a){return a;}); // this could work }Walter Bright:D (a,b) { return a + b; }In D to define a true lambda you need types too: auto f = (int a,int b){ return a + b; };Then you'd probably have map!{a => 2*a}(range); That is very easy on the eyes. +1. What about: void foo(int delegate(int)){} void main(){ foo{a=>2*a}; // ok? } Is binary '{' worth spending like that?For D I think I'd like a syntax like: { int a, int b => a + b } That in some cases becomes just: { a,b => a + b }That would be less readable for somebody coming from a C styled language. Curly braces for body and parenthesis for arguments is something very familiar. This makes Javascript's and D's closures the most readable for somebody having this background.The delegates themselves are very readable indeed but they tend to screw up the readability of larger expressions that contain them. An alternate delegate syntax could help a great deal in these cases.
Sep 21 2011
On 9/21/11 5:29 PM, bearophile wrote:Walter Bright:No. AndreiD (a,b) { return a + b; }In D to define a true lambda you need types too: auto f = (int a,int b){ return a + b; };
Sep 21 2011
On 2011-09-22 00:50, Andrei Alexandrescu wrote:On 9/21/11 5:29 PM, bearophile wrote:void foo (int delegate (int, int) a){} void main () { foo((a, b) { return a +b;}); } Results in: main.d(48): Error: undefined identifier a main.d(48): Error: undefined identifier b main.d(48): Error: function main.foo (int delegate(int, int) a) is not callable using argument types (_error_ delegate(_error_, _error_)) main.d(48): Error: cannot implicitly convert expression (__dgliteral1) of type _error_ delegate(_error_, _error_) to int delegate(int, int) Failed: /Users/jacob/.dvm/bin/dvm-current-dc -v -o- '/Users/jacob/development/d/main.d' -I'/Users/jacob/development/d'Walter Bright:No. AndreiD (a,b) { return a + b; }In D to define a true lambda you need types too: auto f = (int a,int b){ return a + b; };/Users/jacob/development/d/main.d.deps-- /Jacob Carlborg
Sep 22 2011
On 9/22/11 3:49 AM, Jacob Carlborg wrote:On 2011-09-22 00:50, Andrei Alexandrescu wrote:That's a bug in the compiler. AndreiOn 9/21/11 5:29 PM, bearophile wrote:void foo (int delegate (int, int) a){} void main () { foo((a, b) { return a +b;}); } Results in: main.d(48): Error: undefined identifier a main.d(48): Error: undefined identifier b main.d(48): Error: function main.foo (int delegate(int, int) a) is not callable using argument types (_error_ delegate(_error_, _error_)) main.d(48): Error: cannot implicitly convert expression (__dgliteral1) of type _error_ delegate(_error_, _error_) to int delegate(int, int) Failed: /Users/jacob/.dvm/bin/dvm-current-dc -v -o- '/Users/jacob/development/d/main.d' -I'/Users/jacob/development/d' >/Users/jacob/development/d/main.d.depsWalter Bright:No. AndreiD (a,b) { return a + b; }In D to define a true lambda you need types too: auto f = (int a,int b){ return a + b; };
Sep 22 2011
On 2011-09-22 16:11, Andrei Alexandrescu wrote:On 9/22/11 3:49 AM, Jacob Carlborg wrote:Ok, has that been reported? -- /Jacob CarlborgOn 2011-09-22 00:50, Andrei Alexandrescu wrote:That's a bug in the compiler. AndreiOn 9/21/11 5:29 PM, bearophile wrote:void foo (int delegate (int, int) a){} void main () { foo((a, b) { return a +b;}); } Results in: main.d(48): Error: undefined identifier a main.d(48): Error: undefined identifier b main.d(48): Error: function main.foo (int delegate(int, int) a) is not callable using argument types (_error_ delegate(_error_, _error_)) main.d(48): Error: cannot implicitly convert expression (__dgliteral1) of type _error_ delegate(_error_, _error_) to int delegate(int, int) Failed: /Users/jacob/.dvm/bin/dvm-current-dc -v -o- '/Users/jacob/development/d/main.d' -I'/Users/jacob/development/d'Walter Bright:No. AndreiD (a,b) { return a + b; }In D to define a true lambda you need types too: auto f = (int a,int b){ return a + b; };/Users/jacob/development/d/main.d.deps
Sep 22 2011
On 9/22/11 9:17 AM, Jacob Carlborg wrote:Yes :o). http://d.puremagic.com/issues/show_bug.cgi?id=6714 AndreiOk, has that been reported?void foo (int delegate (int, int) a){} void main () { foo((a, b) { return a +b;}); } Results in: main.d(48): Error: undefined identifier a main.d(48): Error: undefined identifier b main.d(48): Error: function main.foo (int delegate(int, int) a) is not callable using argument types (_error_ delegate(_error_, _error_)) main.d(48): Error: cannot implicitly convert expression (__dgliteral1) of type _error_ delegate(_error_, _error_) to int delegate(int, int) Failed: /Users/jacob/.dvm/bin/dvm-current-dc -v -o- '/Users/jacob/development/d/main.d' -I'/Users/jacob/development/d'That's a bug in the compiler. Andrei/Users/jacob/development/d/main.d.deps
Sep 22 2011
Andrei Alexandrescu:Yes :o). http://d.puremagic.com/issues/show_bug.cgi?id=6714Thank you for adding it, and sorry for not filing it myself in past. Bye, bearophile
Sep 22 2011
On Wed, 21 Sep 2011 18:29:34 -0400, bearophile wrote:Walter Bright:can take the destination type into account when doing inference.D (a,b) { return a + b; }In D to define a true lambda you need types too: auto f = (int a,int b){ return a + b; };For D I think I'd like a syntax like: { int a, int b => a + b } That in some cases becomes just: { a,b => a + b }I'd rather the C which is basically the same as D already.
Sep 21 2011
On 9/21/2011 8:10 PM, Jesse Phillips wrote:On Wed, 21 Sep 2011 18:29:34 -0400, bearophile wrote:As Andrei pointed out, it is not true of D, since D does not require the types for the parameters.Walter Bright:can take the destination type into account when doing inference.D (a,b) { return a + b; }In D to define a true lambda you need types too: auto f = (int a,int b){ return a + b; };
Sep 22 2011
Actually Scala doesn't need type declarations in labmda literals. Most of the time argument types are infered. It would be awesome if D infered argument types for labdas too. To add a few things to your list: Nemerle fun (x, y) { x + y } (x, y) => x + y Scala and Nemerle supports placeholder lambda syntax _ + _ Scheme (lambda (x y) (+ x y)) Smalltalk [ :x :y | x + y ] fun x y -> x + y Ruby has a whole zoo of syntaxes {|x, y| x + y } ->(x, y) { x + y } do |x, y| x + y end Groovy { x, y -> x + y } So "(args) => body" is the most common syntax now
Sep 21 2011
On 9/21/2011 11:47 PM, Max Klyga wrote:It would be awesome if D infered argument types for labdas too.It does, and it is awesome!
Sep 22 2011
On 09/22/2011 09:35 AM, Walter Bright wrote:On 9/21/2011 11:47 PM, Max Klyga wrote:Indeed, but it currently only works if the delegate literal is a template parameter, in which case the literal is actually fully generic, right?It would be awesome if D infered argument types for labdas too.It does, and it is awesome!
Sep 22 2011
On 9/22/2011 4:36 AM, Timon Gehr wrote:Indeed, but it currently only works if the delegate literal is a template parameter, in which case the literal is actually fully generic, right?It gets internally rewritten into being a template function.
Sep 22 2011
On 9/22/11 2:35 AM, Walter Bright wrote:On 9/21/2011 11:47 PM, Max Klyga wrote:C++'s lambdas require the types to be present, which some consider a large mistake. AndreiIt would be awesome if D infered argument types for labdas too.It does, and it is awesome!
Sep 22 2011
On 2011-09-22 08:47, Max Klyga wrote:Actually Scala doesn't need type declarations in labmda literals. Most of the time argument types are infered. It would be awesome if D infered argument types for labdas too. To add a few things to your list: Nemerle fun (x, y) { x + y } (x, y) => x + y Scala and Nemerle supports placeholder lambda syntax _ + _ Scheme (lambda (x y) (+ x y)) Smalltalk [ :x :y | x + y ] fun x y -> x + y Ruby has a whole zoo of syntaxes {|x, y| x + y } ->(x, y) { x + y } do |x, y| x + y end Groovy { x, y -> x + y } So "(args) => body" is the most common syntax nowScala also has this syntax that can be useful sometimes: foo { } Where "foo" is a method taking a delegate as an argument. This allows to create, what looks like, new statements. Which can be very handy for DSL's. -- /Jacob Carlborg
Sep 22 2011
On 9/22/11 1:47 AM, Max Klyga wrote:Actually Scala doesn't need type declarations in labmda literals. Most of the time argument types are infered.Already does. We're looking for a briefer syntax. Andrei
Sep 22 2011
== Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s articleOn 9/22/11 1:47 AM, Max Klyga wrote:Actually Scala doesn't need type declarations in labmda literals. Most of the time argument types are infered.Already does. We're looking for a briefer syntax.What is the problem with just inferring the `return`, allowing you to replace (a,b) { return a + b; } with (a, b) { a + b; } This seems competitive with the other syntaxes for brevity, but ISTR there was some objection to doing things that way. Also would it make sense to have a template library along the lines of boost::proto/boost::lambda to allow even shorter, expression-based lambdas like _1 + _2 I'm not exactly a D template metaprogramming pro, but I think this would work for a lot of common cases. Cheers, Pillsy
Sep 22 2011
On 9/22/11 10:42 AM, pillsy wrote:== Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s articleThe objection is that it introduces a number of questions: 1. How about using that syntax in regular functions? 2. What if the lambda wants to actually evaluate the expression but return void? 3. How is the semicolon relevant? (If its presence is used as a disambiguator for (2), it's poor design to predicate a large semantic difference on such a distinction.)On 9/22/11 1:47 AM, Max Klyga wrote:Actually Scala doesn't need type declarations in labmda literals. Most of the time argument types are infered.Already does. We're looking for a briefer syntax.What is the problem with just inferring the `return`, allowing you to replace (a,b) { return a + b; } with (a, b) { a + b; } This seems competitive with the other syntaxes for brevity, but ISTR there was some objection to doing things that way.Also would it make sense to have a template library along the lines of boost::proto/boost::lambda to allow even shorter, expression-based lambdas like _1 + _2 I'm not exactly a D template metaprogramming pro, but I think this would work for a lot of common cases.Such an approach has caused more trouble than benefits in C++. Andrei
Sep 22 2011
== Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s articleOn 9/22/11 10:42 AM, pillsy wrote:[...]== Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s articleAlready does. We're looking for a briefer syntax.What is the problem with just inferring the `return`, allowing you to replace(a,b) { return a + b; }with(a, b) { a + b; }This seems competitive with the other syntaxes for brevity, but ISTR there was some objection to doing things that way.The objection is that it introduces a number of questions:At the risk of relitigating a long-settled issue, I think there are good answers to all these questions.1. How about using that syntax in regular functions?That sounds great! :)2. What if the lambda wants to actually evaluate the expression but return void?Is this commonly important? If so, there are three possibilities: a. Have an expression with type void, perhaps a `void` literal or empty patens `()`, that can be used as the ultimate expression when needed, as in (i) { total += i; void; } b. Require the use of a bare `return` in these cases. c. Require the return type to be explicitly declared as void in those cases. This seems like it's especially not a problem for named functions, since `void` isn't any longer than `auto.3. How is the semicolon relevant? (If its presence is used as a disambiguator for (2), it's poor design to predicate a large semantic difference on such a distinction.)It's just part of the syntax. I agree that using it to disambiguate the function's return type is horrible. Mathematica does that, and I've torn out a fair amount of my hair because of it over the years. [...]Fair enough. Cheers, PillsyI'm not exactly a D template metaprogramming pro, but I think this would work for a lot of common cases.Such an approach has caused more trouble than benefits in C++.
Sep 22 2011
On 9/22/2011 9:06 AM, Andrei Alexandrescu wrote:On 9/22/11 10:42 AM, pillsy wrote:Besides just looking awfully hackish._1 + _2 I'm not exactly a D template metaprogramming pro, but I think this would work for a lot of common cases.Such an approach has caused more trouble than benefits in C++.
Sep 22 2011
Andrei Alexandrescu wrote:On 9/22/11 10:42 AM, pillsy wrote:As an alternative, a brief syntax could just be restricted to lambda expressions because we already have complete function literals for statements, unlike python for example. A void returning function is only used for side-effects, I am not be bothered at all to have to use full punctuation for that. (a, b) { a + b } or (a, b) => a + b would be sweet :)== Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s articleThe objection is that it introduces a number of questions: 1. How about using that syntax in regular functions? 2. What if the lambda wants to actually evaluate the expression but return void?On 9/22/11 1:47 AM, Max Klyga wrote:Actually Scala doesn't need type declarations in labmda literals. Most of the time argument types are infered.Already does. We're looking for a briefer syntax.What is the problem with just inferring the `return`, allowing you to replace (a,b) { return a + b; } with (a, b) { a + b; } This seems competitive with the other syntaxes for brevity, but ISTR there was some objection to doing things that way.
Sep 22 2011
On 2011-09-22 18:06, Andrei Alexandrescu wrote:On 9/22/11 10:42 AM, pillsy wrote:I function/delegate that returns a value should be implicitly converted to a function/delegate that returns void. -- /Jacob Carlborg== Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s articleThe objection is that it introduces a number of questions: 1. How about using that syntax in regular functions? 2. What if the lambda wants to actually evaluate the expression but return void?On 9/22/11 1:47 AM, Max Klyga wrote:Actually Scala doesn't need type declarations in labmda literals. Most of the time argument types are infered.Already does. We're looking for a briefer syntax.What is the problem with just inferring the `return`, allowing you to replace (a,b) { return a + b; } with (a, b) { a + b; } This seems competitive with the other syntaxes for brevity, but ISTR there was some objection to doing things that way.
Sep 22 2011
On 9/22/2011 1:13 PM, Jacob Carlborg wrote:I function/delegate that returns a value should be implicitly converted to a function/delegate that returns void.That doesn't work in some cases - consider a function that returns an object that the caller must destruct. Or even just returns a struct - the caller passes in a hidden pointer to where the return type gets written. Implicit conversion of function pointers and delegates requires binary ABI compatibility.
Sep 22 2011
On 09/22/2011 11:46 PM, Walter Bright wrote:On 9/22/2011 1:13 PM, Jacob Carlborg wrote:The compiler could insert a thunk that discards the result if the two delegate types are not ABI compatible.I function/delegate that returns a value should be implicitly converted to a function/delegate that returns void.That doesn't work in some cases - consider a function that returns an object that the caller must destruct. Or even just returns a struct - the caller passes in a hidden pointer to where the return type gets written. Implicit conversion of function pointers and delegates requires binary ABI compatibility.
Sep 22 2011
On 2011-09-22 23:46, Walter Bright wrote:On 9/22/2011 1:13 PM, Jacob Carlborg wrote:What I'm saying is that you can ignore the returned value of a delegate therefore I think it should be possible implicitly convert a delegate returning a value, to a delegate returning void. The same for function pointers as well. Example: void main () { int delegate () bar = { return 1; }; void delegate () foo = bar; int a = bar(); // here we call "bar" and handles the return value bar(); // here we call "bar" and ignores the return value foo(); // here we call "foo", same as the line above } Or are you saying that it would be strange and confusing when calling a delegate that returns void, a struct could be destructed on the callers side? I can agree with that.I function/delegate that returns a value should be implicitly converted to a function/delegate that returns void.That doesn't work in some cases - consider a function that returns an object that the caller must destruct. Or even just returns a struct - the caller passes in a hidden pointer to where the return type gets written.Implicit conversion of function pointers and delegates requires binary ABI compatibility.I'm not suggesting that a function pointer should be implicitly converted to a delegate, if that what is what you are saying. -- /Jacob Carlborg
Sep 22 2011
"Jacob Carlborg" <doob me.com> wrote in message news:j5h98l$ors$1 digitalmars.com...What I'm saying is that you can ignore the returned value of a delegate therefore I think it should be possible implicitly convert a delegate returning a value, to a delegate returning void. The same for function pointers as well. Example: void main () { int delegate () bar = { return 1; }; void delegate () foo = bar; int a = bar(); // here we call "bar" and handles the return value bar(); // here we call "bar" and ignores the return value foo(); // here we call "foo", same as the line above }I can see the appeal, but the abi makes it difficult. As Walter said, what if the return value requires destruction by the caller? What if the return is done through nrvo? While they're called the same, the code generator handles them very differently. If it works, it should work for all cases. Don't forget that you can trivially convert to a delegate returning void with the following syntax: void delegate () foo = { bar(); };
Sep 22 2011
On 2011-09-23 08:42, Daniel Murphy wrote:"Jacob Carlborg"<doob me.com> wrote in message news:j5h98l$ors$1 digitalmars.com...Why can't the compiler do something similar automatically. Then we won't have the problem if a lambda returns void or a value. -- /Jacob CarlborgWhat I'm saying is that you can ignore the returned value of a delegate therefore I think it should be possible implicitly convert a delegate returning a value, to a delegate returning void. The same for function pointers as well. Example: void main () { int delegate () bar = { return 1; }; void delegate () foo = bar; int a = bar(); // here we call "bar" and handles the return value bar(); // here we call "bar" and ignores the return value foo(); // here we call "foo", same as the line above }I can see the appeal, but the abi makes it difficult. As Walter said, what if the return value requires destruction by the caller? What if the return is done through nrvo? While they're called the same, the code generator handles them very differently. If it works, it should work for all cases. Don't forget that you can trivially convert to a delegate returning void with the following syntax: void delegate () foo = { bar(); };
Sep 22 2011
On 9/22/2011 11:55 PM, Jacob Carlborg wrote:On 2011-09-23 08:42, Daniel Murphy wrote:1. This can get arbitrarily expensive if there are parameters involved (temps have to be constructed, copied, & destroyed) and those costs will be hidden. 2. At some point, heroic efforts to coerce one type to another will subvert the point of a type system. After all, if the designer of bar() intended the return value to be the point, wouldn't such a conversion hide a bug?void delegate () foo = { bar(); };Why can't the compiler do something similar automatically. Then we won't have the problem if a lambda returns void or a value.
Sep 23 2011
On 2011-09-23 09:34, Walter Bright wrote:On 9/22/2011 11:55 PM, Jacob Carlborg wrote:I guess so.On 2011-09-23 08:42, Daniel Murphy wrote:1. This can get arbitrarily expensive if there are parameters involved (temps have to be constructed, copied, & destroyed) and those costs will be hidden.void delegate () foo = { bar(); };Why can't the compiler do something similar automatically. Then we won't have the problem if a lambda returns void or a value.2. At some point, heroic efforts to coerce one type to another will subvert the point of a type system. After all, if the designer of bar() intended the return value to be the point, wouldn't such a conversion hide a bug?Maybe, but so could not using the returned value as well. It sounds so easy in my head. -- /Jacob Carlborg
Sep 23 2011
Andrei Alexandrescu , dans le message (digitalmars.D:145023), a écrit :What is the problem with just inferring the `return`, allowing you to replace (a,b) { return a + b; } with (a, b) { a + b; }The objection is that it introduces a number of questions: 1. How about using that syntax in regular functions? 2. What if the lambda wants to actually evaluate the expression but return void? 3. How is the semicolon relevant? (If its presence is used as a disambiguator for (2), it's poor design to predicate a large semantic difference on such a distinction.)I think such shortcut should be allowed only for one-liners. There is no gain not to write return if you already have several statements. The shortcut syntax should be (a, b) { expression }, and not (a, b) { statement } This way, you ensure that only one liners can use this syntax, so there is no abuse. It is true that the return type would depend on the presence of a semicolon, but the compiler will quickly complain if it expects a delegate returning void and gets a delegate returning a type, or vice-versa anyway.Too dangerous. std.algorithm uses a, b, c, etc, but it can only do that because it never checks the context: int b; double x; auto f = lambda { a * x + b } How many arguments does f take ? -- ChristopheAlso would it make sense to have a template library along the lines of boost::proto/boost::lambda to allow even shorter, expression-based lambdas like _1 + _2 I'm not exactly a D template metaprogramming pro, but I think this would work for a lot of common cases.Such an approach has caused more trouble than benefits in C++.
Sep 23 2011
Walter Bright , dans le message (digitalmars.D:144959), a écrit :I've collected a few from various languages for comparison: D (a,b) { return a + b; }Few ideas: (a,b){ a + b } Lambdas can avoid to type 'return'. returning void would be harder, except if to return void, you can just put the semicolon at the end (but it could be confusing). a, b -> a + b Introduce a -> "operator" to generate a delegate. Depending on the precedence, "(a,b) -> (a + b)" might be prefered. "(a,b -> a+b)" will be safer to use obviously. I prefer that instead of {a,b -> a+b} because the second adds a different meaning to {}, which is different from "statement grouping" and "function body". The => symbol is fine too, but looks like a mistyped comparison operator to me. -- Christophe
Sep 22 2011
On 2011-09-22 00:17, Walter Bright wrote:I've collected a few from various languages for comparison: D (a,b) { return a + b; } Ruby ->(a,b) { a + b } C++0x [](int a, int b) { return a + b; } (a,b) => a + b Scala (a:Int, b:Int) => a + b Erlang fun(a, b) -> a + b end. Haskell \a b -> a + b Javascript function(a,b) { return a + b; } Clojure Lua function(a,b) return a + b end Python lambda a,b: a + bthings going on except the syntax that I think is as equally important: * Inferred parameter types * Automatically return the last expression * No need for ending with a semicolon * One line lambdas can omit the braces Note that Scala can infer the parameter types. An additional question, do we want/need a new syntax for declaring lambda/delegate types? -- /Jacob Carlborg
Sep 22 2011
Jacob Carlborg Wrote:* Inferred parameter types * Automatically return the last expression * No need for ending with a semicolon * One line lambdas can omit the braces Note that Scala can infer the parameter types. An additional question, do we want/need a new syntax for declaring lambda/delegate types? -- /Jacob CarlborgThe only issue I have with current syntax is return. The type inferring is a bug so... I've really enjoyed the current syntax options. I've used auto var = { /// function thing return asuth; }() for a more complex ?:
Sep 22 2011
On 9/21/11 5:17 PM, Walter Bright wrote:I've collected a few from various languages for comparison:[snip] I think we should do the following: 1. Introduce a new token "=>" 2. Add this rewrite to the grammar: symbol => expression translates to (symbol) { return expression; } 3. Add this rewrite to the grammar: symbol1 symbol2 => expression translates to (symbol1 symbol2) { return expression; } 4. Add this rewrite to the grammar: (comma_separated_parms) => expression translates to (comma_separated_parms) => expression Each item in comma_separated_parms may be 1 or 2 symbols separated by whitespace. Example: (int a, b) => a + b is valid and translates to (int a, b) { return a + b; } 5. The expression cannot contain commas at top level; an unparenthesized comma is considered to finish expression, just like in a function call's argument list. For example: fun(int a => a + 1, a + 2) is interpreted as fun((int a => a + 1), (a + 2)) To use comma inside expression, add parens around it. 5. Remove bugs and limitations. A function literal may specify none, all, or some parameter types, and the compiler correctly figures out the appropriate template and non-template parameters. The literal subsequently converts to function pointer or delegate whenever there's a match of parameter and result types. Andrei
Sep 22 2011
On 9/22/11 3:54 PM, Andrei Alexandrescu wrote:On 9/21/11 5:17 PM, Walter Bright wrote:[snip] I can't believe I forgot an all-important aspect. A function literal should be comparable to another for equality. Two function literals are equal if they have the same token type sequence (up to alpha renaming) and use the same environment. Example: bool test(auto fun)() { return fun == (x, y => x + y); } unittest { assert(test!(a, b => a + b)()); } This will not be easy to implement (especially when environment dependencies come into play) but is necessary. AndreiI've collected a few from various languages for comparison:[snip] I think we should do the following:
Sep 22 2011
Andrei Alexandrescu:A function literal should be comparable to another for equality.Are you willing to explain me why, and show an use case? Bye, bearophile
Sep 22 2011
On 09/22/11 16:08, bearophile wrote:Andrei Alexandrescu:An important application is optimizing for specific lambdas (e.g. equality). For example, a substring search using equality for characters could use bitwise comparison. AndreiA function literal should be comparable to another for equality.Are you willing to explain me why, and show an use case?
Sep 22 2011
== Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s articleOn 09/22/11 16:08, bearophile wrote:Andrei Alexandrescu:A function literal should be comparable to another for equality.Are you willing to explain me why, and show an use case?An important application is optimizing for specific lambdas (e.g. equality). For example, a substring search using equality for characters could use bitwise comparison.Is there some reason this isn't better handled through templating mechanisms? It seems like this would primarily benefit picking better optimization strategies at *runtime*, which strikes me as a fairly esoteric use case. Cheers, Pillsy
Sep 23 2011
On 09/23/11 10:40, pillsy wrote:== Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s articleForgot to mention - the comparison should work statically, i.e. inside a static if. AndreiOn 09/22/11 16:08, bearophile wrote:Andrei Alexandrescu:A function literal should be comparable to another for equality.Are you willing to explain me why, and show an use case?An important application is optimizing for specific lambdas (e.g. equality). For example, a substring search using equality for characters could use bitwise comparison.Is there some reason this isn't better handled through templating mechanisms? It seems like this would primarily benefit picking better optimization strategies at *runtime*, which strikes me as a fairly esoteric use case. Cheers, Pillsy
Sep 23 2011
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message news:j5ge8v$2a0h$1 digitalmars.com...On 09/22/11 16:08, bearophile wrote:I think this is better handled by a library solution - define standard templated comparators somewhere and have special support for these. There are dozens of ways to write the same comparison in D and allowing equality tests to work in some cases is likely to be as frustrating as string1 == string2 working sometimes in java.Andrei Alexandrescu:An important application is optimizing for specific lambdas (e.g. equality). For example, a substring search using equality for characters could use bitwise comparison. AndreiA function literal should be comparable to another for equality.Are you willing to explain me why, and show an use case?
Sep 23 2011
On 2011-09-22 23:08, bearophile wrote:Andrei Alexandrescu:When using lambdas as event handlers: class Foo { event[] events; void registerEventHandler (void delegate (event) dg) { if (!events.contains(dg)) // register a given just delegate once events ~= dg; } } -- /Jacob CarlborgA function literal should be comparable to another for equality.Are you willing to explain me why, and show an use case? Bye, bearophile
Sep 22 2011
On Thu, 22 Sep 2011 16:54:55 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:4. Add this rewrite to the grammar: (comma_separated_parms) => expression translates to (comma_separated_parms) => expressionAm I missing something here? -Steve
Sep 22 2011
On 9/22/11 4:03 PM, Steven Schveighoffer wrote:On Thu, 22 Sep 2011 16:54:55 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:I am. The rewrite should be: (comma_separated_parms) { return expression; } Andrei4. Add this rewrite to the grammar: (comma_separated_parms) => expression translates to (comma_separated_parms) => expressionAm I missing something here?
Sep 22 2011
--- Cristi Cobzarenco BSc in Artificial Intelligence and Computer Science University of Edinburgh Profile: http://www.google.com/profiles/cristi.cobzarenco On 22 September 2011 22:03, Steven Schveighoffer <schveiguy yahoo.com> wrote:On Thu, 22 Sep 2011 16:54:55 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Of course he meant (comma_separated_parms) { return expression; }4. Add this rewrite to the grammar: (comma_separated_parms) => expression translates to (comma_separated_parms) => expressionAm I missing something here? -Steve
Sep 22 2011
On 9/22/2011 2:03 PM, Steven Schveighoffer wrote:On Thu, 22 Sep 2011 16:54:55 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:I like easy rewrites!4. Add this rewrite to the grammar: (comma_separated_parms) => expression translates to (comma_separated_parms) => expressionAm I missing something here?
Sep 22 2011
I'd much rather see the bugs in the current lambda syntax get fixed (e.g. http://d.puremagic.com/issues/show_bug.cgi?id=4724) rather than spend more time bikeshedding. == Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s articleOn 9/21/11 5:17 PM, Walter Bright wrote:== Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s articleI've collected a few from various languages for comparison:[snip] I think we should do the following: 1. Introduce a new token "=>" 2. Add this rewrite to the grammar: symbol => expression translates to (symbol) { return expression; } 3. Add this rewrite to the grammar: symbol1 symbol2 => expression translates to (symbol1 symbol2) { return expression; } 4. Add this rewrite to the grammar: (comma_separated_parms) => expression translates to (comma_separated_parms) => expression Each item in comma_separated_parms may be 1 or 2 symbols separated by whitespace. Example: (int a, b) => a + b is valid and translates to (int a, b) { return a + b; } 5. The expression cannot contain commas at top level; an unparenthesized comma is considered to finish expression, just like in a function call's argument list. For example: fun(int a => a + 1, a + 2) is interpreted as fun((int a => a + 1), (a + 2)) To use comma inside expression, add parens around it. 5. Remove bugs and limitations. A function literal may specify none, all, or some parameter types, and the compiler correctly figures out the appropriate template and non-template parameters. The literal subsequently converts to function pointer or delegate whenever there's a match of parameter and result types. AndreiOn 9/21/11 5:17 PM, Walter Bright wrote:== Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s articleI've collected a few from various languages for comparison:[snip] I think we should do the following: 1. Introduce a new token "=>" 2. Add this rewrite to the grammar: symbol => expression translates to (symbol) { return expression; } 3. Add this rewrite to the grammar: symbol1 symbol2 => expression translates to (symbol1 symbol2) { return expression; } 4. Add this rewrite to the grammar: (comma_separated_parms) => expression translates to (comma_separated_parms) => expression Each item in comma_separated_parms may be 1 or 2 symbols separated by whitespace. Example: (int a, b) => a + b is valid and translates to (int a, b) { return a + b; } 5. The expression cannot contain commas at top level; an unparenthesized comma is considered to finish expression, just like in a function call's argument list. For example: fun(int a => a + 1, a + 2) is interpreted as fun((int a => a + 1), (a + 2)) To use comma inside expression, add parens around it. 5. Remove bugs and limitations. A function literal may specify none, all, or some parameter types, and the compiler correctly figures out the appropriate template and non-template parameters. The literal subsequently converts to function pointer or delegate whenever there's a match of parameter and result types. AndreiOn 9/21/11 5:17 PM, Walter Bright wrote:I've collected a few from various languages for comparison:[snip] I think we should do the following: 1. Introduce a new token "=>" 2. Add this rewrite to the grammar: symbol => expression translates to (symbol) { return expression; } 3. Add this rewrite to the grammar: symbol1 symbol2 => expression translates to (symbol1 symbol2) { return expression; } 4. Add this rewrite to the grammar: (comma_separated_parms) => expression translates to (comma_separated_parms) => expression Each item in comma_separated_parms may be 1 or 2 symbols separated by whitespace. Example: (int a, b) => a + b is valid and translates to (int a, b) { return a + b; } 5. The expression cannot contain commas at top level; an unparenthesized comma is considered to finish expression, just like in a function call's argument list. For example: fun(int a => a + 1, a + 2) is interpreted as fun((int a => a + 1), (a + 2)) To use comma inside expression, add parens around it. 5. Remove bugs and limitations. A function literal may specify none, all, or some parameter types, and the compiler correctly figures out the appropriate template and non-template parameters. The literal subsequently converts to function pointer or delegate whenever there's a match of parameter and result types. Andrei
Sep 22 2011
On 9/22/11 4:13 PM, dsimcha wrote:I'd much rather see the bugs in the current lambda syntax get fixed (e.g. http://d.puremagic.com/issues/show_bug.cgi?id=4724) rather than spend more time bikeshedding.That's not an either-or choice, and of course improving current lambdas (btw that's not a purely syntactic bug) would improve the rewrites as well. What I noticed lately is that people simply appreciate terse lambdas a whole lot. They hate C++ lambdas because you need to mention types, dislike Java's poor solution to lambdas to the extent the language had to add a feature just for them (which is subject to further controversy) and so on. I think current D is no slouch for lambda expressions, and function attribute deduction adds great power to lambdas, but further simplifying lambdas may mark a sensible improvement in their usability. Andrei
Sep 22 2011
On Thursday, September 22, 2011 14:47 Andrei Alexandrescu wrote:On 9/22/11 4:13 PM, dsimcha wrote:It wouldn't hurt my feelings any if an abbreviated lambda syntax weren't added, but it _is_ a bit annoying that lambdas are as long as they are for simple stuff - especially when I'm forced to use the lambda syntax because the string syntax that I was trying to use wouldn't work for one reason or another. So, adding an abbreviated lambda syntax is likely a good idea. And your suggested syntax is probably the right way to go, since it's most similar syntaxes are really objectively better anyway. But we will need someone to take the time to implement it (though fortunately, that's far easier now than it used to be given the increasing number of contributors to dmd). - Jonathan M DavisI'd much rather see the bugs in the current lambda syntax get fixed (e.g. http://d.puremagic.com/issues/show_bug.cgi?id=4724) rather than spend more time bikeshedding.That's not an either-or choice, and of course improving current lambdas (btw that's not a purely syntactic bug) would improve the rewrites as well. What I noticed lately is that people simply appreciate terse lambdas a whole lot. They hate C++ lambdas because you need to mention types, dislike Java's poor solution to lambdas to the extent the language had to add a feature just for them (which is subject to further controversy) and so on. I think current D is no slouch for lambda expressions, and function attribute deduction adds great power to lambdas, but further simplifying lambdas may mark a sensible improvement in their usability.
Sep 22 2011
On 2011-09-22 22:54, Andrei Alexandrescu wrote:On 9/21/11 5:17 PM, Walter Bright wrote:I like it. Just to be clear, when having a parameter list of one parameter, the parentheses are optional; and when having multiple parameters the parentheses are mandatory? Would any of these be allowed: symbol => { expression } // braces, implicit return, no semicolon symbol => { expression; } // if legal, would this return void or expression symbol => expression; // semicolon symbol => { return expression; } // braces, explicit return, semicolon symbol => return expression; // explicit return, semicolon symbol => { expression; expression } // multi-line lambda, braces, implicit return, no semicolon -- /Jacob CarlborgI've collected a few from various languages for comparison:[snip] I think we should do the following: 1. Introduce a new token "=>" 2. Add this rewrite to the grammar: symbol => expression translates to (symbol) { return expression; } 3. Add this rewrite to the grammar: symbol1 symbol2 => expression translates to (symbol1 symbol2) { return expression; } 4. Add this rewrite to the grammar: (comma_separated_parms) => expression translates to (comma_separated_parms) => expression Each item in comma_separated_parms may be 1 or 2 symbols separated by whitespace. Example: (int a, b) => a + b is valid and translates to (int a, b) { return a + b; } 5. The expression cannot contain commas at top level; an unparenthesized comma is considered to finish expression, just like in a function call's argument list. For example: fun(int a => a + 1, a + 2) is interpreted as fun((int a => a + 1), (a + 2)) To use comma inside expression, add parens around it. 5. Remove bugs and limitations. A function literal may specify none, all, or some parameter types, and the compiler correctly figures out the appropriate template and non-template parameters. The literal subsequently converts to function pointer or delegate whenever there's a match of parameter and result types. Andrei
Sep 22 2011
Jacob Carlborg , dans le message (digitalmars.D:145083), a écrit :On 2011-09-22 22:54, Andrei Alexandrescu wrote:No, we should not kill a good syntax idea by giving ways to abuse it right away. First implement "symbol => expresion" Then see if it works well and if it should benefit from further improvement. BTW, the main improvement is to avoid punctuation and return, so there is no gain to introduce them again. -- ChristopheOn 9/21/11 5:17 PM, Walter Bright wrote:I like it. Just to be clear, when having a parameter list of one parameter, the parentheses are optional; and when having multiple parameters the parentheses are mandatory? Would any of these be allowed: symbol => { expression } // braces, implicit return, no semicolon symbol => { expression; } // if legal, would this return void or expression symbol => expression; // semicolon symbol => { return expression; } // braces, explicit return, semicolon symbol => return expression; // explicit return, semicolon symbol => { expression; expression } // multi-line lambda, braces, implicit return, no semicolonI've collected a few from various languages for comparison:[snip] I think we should do the following: 1. Introduce a new token "=>" 2. Add this rewrite to the grammar: symbol => expression translates to (symbol) { return expression; } 3. Add this rewrite to the grammar: symbol1 symbol2 => expression translates to (symbol1 symbol2) { return expression; } 4. Add this rewrite to the grammar: (comma_separated_parms) => expression translates to (comma_separated_parms) => expression Each item in comma_separated_parms may be 1 or 2 symbols separated by whitespace. Example: (int a, b) => a + b is valid and translates to (int a, b) { return a + b; } 5. The expression cannot contain commas at top level; an unparenthesized comma is considered to finish expression, just like in a function call's argument list. For example: fun(int a => a + 1, a + 2) is interpreted as fun((int a => a + 1), (a + 2)) To use comma inside expression, add parens around it. 5. Remove bugs and limitations. A function literal may specify none, all, or some parameter types, and the compiler correctly figures out the appropriate template and non-template parameters. The literal subsequently converts to function pointer or delegate whenever there's a match of parameter and result types. Andrei
Sep 23 2011
On 2011-09-23 10:50, Christophe wrote:Jacob Carlborg , dans le message (digitalmars.D:145083), a écrit :I wouldn't say it's abusing the syntax.On 2011-09-22 22:54, Andrei Alexandrescu wrote:No, we should not kill a good syntax idea by giving ways to abuse it right away.On 9/21/11 5:17 PM, Walter Bright wrote:I like it. Just to be clear, when having a parameter list of one parameter, the parentheses are optional; and when having multiple parameters the parentheses are mandatory? Would any of these be allowed: symbol => { expression } // braces, implicit return, no semicolon symbol => { expression; } // if legal, would this return void or expression symbol => expression; // semicolon symbol => { return expression; } // braces, explicit return, semicolon symbol => return expression; // explicit return, semicolon symbol => { expression; expression } // multi-line lambda, braces, implicit return, no semicolonI've collected a few from various languages for comparison:[snip] I think we should do the following: 1. Introduce a new token "=>" 2. Add this rewrite to the grammar: symbol => expression translates to (symbol) { return expression; } 3. Add this rewrite to the grammar: symbol1 symbol2 => expression translates to (symbol1 symbol2) { return expression; } 4. Add this rewrite to the grammar: (comma_separated_parms) => expression translates to (comma_separated_parms) => expression Each item in comma_separated_parms may be 1 or 2 symbols separated by whitespace. Example: (int a, b) => a + b is valid and translates to (int a, b) { return a + b; } 5. The expression cannot contain commas at top level; an unparenthesized comma is considered to finish expression, just like in a function call's argument list. For example: fun(int a => a + 1, a + 2) is interpreted as fun((int a => a + 1), (a + 2)) To use comma inside expression, add parens around it. 5. Remove bugs and limitations. A function literal may specify none, all, or some parameter types, and the compiler correctly figures out the appropriate template and non-template parameters. The literal subsequently converts to function pointer or delegate whenever there's a match of parameter and result types. AndreiFirst implement "symbol => expresion" Then see if it works well and if it should benefit from further improvement. BTW, the main improvement is to avoid punctuation and return, so there is no gain to introduce them again.Yeah, I know. -- /Jacob Carlborg
Sep 23 2011
While we are about rewrites, it would be nice one: symbol := expression; -> auto symbol = expression; 1. shorter 2. conspicuous, more readable. 3. highlights distinction between assignment and initialization. 4. will not break any existing code.
Sep 23 2011
zeljkog , dans le message (digitalmars.D:145087), a écrit :While we are about rewrites, it would be nice one: symbol := expression; -> auto symbol = expression; 1. shorter 2. conspicuous, more readable. 3. highlights distinction between assignment and initialization. 4. will not break any existing code.I quite like it.
Sep 23 2011
On Thu, 22 Sep 2011 22:54:55 +0200, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:On 9/21/11 5:17 PM, Walter Bright wrote:I want to add some points against introducing this particular syntax. 1. Foremost using '=>' is unfamiliar. Comming from C++ or Java you really have to learn reading it. If you weighted the lambda syntaxes with the tiobe factor, arrows would be a minority. How often have you stopped reading about a language because the code examples were unreadable? Besides my liking for haskell, I don't want to see anything close to this on the D site. mergesortBy less [] = [] mergesortBy less xs = head $ until (null.tail) pairs [[x] | x <- xs] where pairs (x:y:t) = merge x y : pairs t pairs xs = xs merge (x:xs) (y:ys) | less y x = y : merge (x:xs) ys | otherwise = x : merge xs (y:ys) merge xs ys = xs ++ ys 2. D is not a functional language, using the implies arrow in 'a => write(1, a.ptr, a.length)' creates a horribly association. 3. I don't see any of the proposed rewrites is working for nullary delegates. '=> foo()' ??? Or '_ => foo()' => 'Error can't deduce parameter'. 4. The expression is badly delimited. The first rewrite symbol => expression is actually symbol => expression\{CommaExpression, CatExpression}. E.g.: dgs ~= (int a) => (a + 5) ~ (int a) => (a ^^ 2); foo(a, b => (log(b), b), c) And that with a pending tuple syntax reclaming even more parens, comma overloads. So D is a curly bracket language. http://en.wikipedia.org/wiki/List_of_programming_languages_by_category#Curly-bracket_languages What is wrong the, I think earlier proposed, very simple solution. http://www.digitalmars.com/d/2.0/expression.html#FunctionLiteral FunctionLiteral: function Typeopt ParameterAttributes opt FunctionLiteralBody delegate Typeopt ParameterAttributes opt FunctionLiteralBody ParameterAttributes FunctionLiteralBody FunctionLiteralBody ParameterAttributes: Parameters Parameters FunctionAttributes FunctionLiteralBody: FunctionBody '{' Expression '}' (a, b) {a+b} // takes the same amount of characters (a, b) {return a+b;} // return is no expression, be explicit () {call()} // nullary dgs ~= (int a){a + 5} ~ (int a){a ^^ 2}; foo(a, (b){log(b), b}, c) You still can use the old variant without totally diverging in syntax. - It is brief - It uses very little syntax changes => less unknown traps martin P.S.: I'm very undecided whether this should apply to functions too. size_t foo() { 6 } P.P.S.: D already seems to have the briefest delegates. http://en.wikipedia.org/wiki/Anonymous_function#Examples P.P.P.S.: One can use a full function body for delegates including contracts. auto dg = delegate uint(int a) in{ assert(a >= 3); } body { return a - 3; };I've collected a few from various languages for comparison:[snip] I think we should do the following: 1. Introduce a new token "=>" 2. Add this rewrite to the grammar: symbol => expression translates to (symbol) { return expression; } 3. Add this rewrite to the grammar: symbol1 symbol2 => expression translates to (symbol1 symbol2) { return expression; } 4. Add this rewrite to the grammar: (comma_separated_parms) => expression translates to (comma_separated_parms) => expression Each item in comma_separated_parms may be 1 or 2 symbols separated by whitespace. Example: (int a, b) => a + b is valid and translates to (int a, b) { return a + b; } 5. The expression cannot contain commas at top level; an unparenthesized comma is considered to finish expression, just like in a function call's argument list. For example: fun(int a => a + 1, a + 2) is interpreted as fun((int a => a + 1), (a + 2)) To use comma inside expression, add parens around it. 5. Remove bugs and limitations. A function literal may specify none, all, or some parameter types, and the compiler correctly figures out the appropriate template and non-template parameters. The literal subsequently converts to function pointer or delegate whenever there's a match of parameter and result types. Andrei
Sep 23 2011
On 9/23/11 8:03 PM, Martin Nowak wrote:On Thu, 22 Sep 2011 22:54:55 +0200, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote: I want to add some points against introducing this particular syntax. 1. Foremost using '=>' is unfamiliar. Comming from C++ or Java you really have to learn reading it. If you weighted the lambda syntaxes with the tiobe factor, arrows would be a minority.Well the C++2011 lambda syntax is quite foreign for C++ users, too.How often have you stopped reading about a language because the code examples were unreadable? Besides my liking for haskell, I don't want to see anything close to this on the D site. mergesortBy less [] = [] mergesortBy less xs = head $ until (null.tail) pairs [[x] | x <- xs] where pairs (x:y:t) = merge x y : pairs t pairs xs = xs merge (x:xs) (y:ys) | less y x = y : merge (x:xs) ys | otherwise = x : merge xs (y:ys) merge xs ys = xs ++ ysI don't understand the point being made here.2. D is not a functional language, using the implies arrow in 'a => write(1, a.ptr, a.length)' creates a horribly association.Hackeyed as that sounds, D is a multi-paradigm language and includes a lot of functional artifacts.3. I don't see any of the proposed rewrites is working for nullary delegates. '=> foo()' ??? Or '_ => foo()' => 'Error can't deduce parameter'.The comma-separated list may be empty.4. The expression is badly delimited. The first rewrite symbol => expression is actually symbol => expression\{CommaExpression, CatExpression}. E.g.: dgs ~= (int a) => (a + 5) ~ (int a) => (a ^^ 2); foo(a, b => (log(b), b), c) And that with a pending tuple syntax reclaming even more parens, comma overloads.Not sure I understand this point either, sorry.So D is a curly bracket language. http://en.wikipedia.org/wiki/List_of_programming_languages_by_category#Curly-bracket_languages What is wrong the, I think earlier proposed, very simple solution. http://www.digitalmars.com/d/2.0/expression.html#FunctionLiteral FunctionLiteral: function Typeopt ParameterAttributes opt FunctionLiteralBody delegate Typeopt ParameterAttributes opt FunctionLiteralBody ParameterAttributes FunctionLiteralBody FunctionLiteralBody ParameterAttributes: Parameters Parameters FunctionAttributes FunctionLiteralBody: FunctionBody '{' Expression '}' (a, b) {a+b} // takes the same amount of charactersWe've been discussing the issues of this form. Andrei
Sep 23 2011
On Friday, September 23, 2011 23:42:52 Andrei Alexandrescu wrote:On 9/23/11 8:03 PM, Martin Nowak wrote:_is_ a syntax familiar to some of the programmers who use a major language derived from C++. It's certainly going to be more familiar than the syntax of any of the functional languages out there. My personal take on it is that if we want more compact lambdas, Andrei's rather than one of the functional languages, so it's more likely to be familiar to more D programmers (based on the assumption that D programmers are than any of the functional languages). So, it's probably the best that we're going to get for a compact lambda syntax. The only question is whether we really want to add a more compact lambda syntax, and I think that there's enough desire for it that we do. - Jonathan M DavisOn Thu, 22 Sep 2011 22:54:55 +0200, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote: I want to add some points against introducing this particular syntax. 1. Foremost using '=>' is unfamiliar. Comming from C++ or Java you really have to learn reading it. If you weighted the lambda syntaxes with the tiobe factor, arrows would be a minority.Well the C++2011 lambda syntax is quite foreign for C++ users, too.
Sep 23 2011
== Quote from Jonathan M Davis (jmdavisProg gmx.com)'s articleOn Friday, September 23, 2011 23:42:52 Andrei Alexandrescu wrote:http://java.dzone.com/news/java-8-lambda-syntax-decided And is it that hard to learn?On 9/23/11 8:03 PM, Martin Nowak wrote:_is_ a syntax familiar to some of the programmers who use a major language derived from C++. It's certainly going to be more familiar than the syntax of any of the functional languages out there.On Thu, 22 Sep 2011 22:54:55 +0200, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote: I want to add some points against introducing this particular syntax. 1. Foremost using '=>' is unfamiliar. Comming from C++ or Java you really have to learn reading it. If you weighted the lambda syntaxes with the tiobe factor, arrows would be a minority.Well the C++2011 lambda syntax is quite foreign for C++ users, too.
Sep 24 2011
On Saturday, September 24, 2011 07:14:13 John Chapman wrote:== Quote from Jonathan M Davis (jmdavisProg gmx.com)'s articleI definitely agree with the reasoning given in the article: "Despite extensive searching, there was no clear winner among the alternatives (each form had some good aspects and some really not very good aspects, and there was no form that was clearly better than the others). So, we felt that it was better to choose something that has already been shown to work well in the two languages that are most like It's pretty much my thoughts exactly. So, unless there's something objectively wrong with this syntax which would make it a bad choice for D, I think that we should adopt some version of it. When 2 of the other major C++-derived languages choose a syntax which also works for D, it just seems like a good idea to follow suit. - Jonathan M DavisOn Friday, September 23, 2011 23:42:52 Andrei Alexandrescu wrote:http://java.dzone.com/news/java-8-lambda-syntax-decided And is it that hard to learn?On 9/23/11 8:03 PM, Martin Nowak wrote:it _is_ a syntax familiar to some of the programmers who use a major language derived from C++. It's certainly going to be more familiar than the syntax of any of the functional languages out there.On Thu, 22 Sep 2011 22:54:55 +0200, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote: I want to add some points against introducing this particular syntax. 1. Foremost using '=>' is unfamiliar. Comming from C++ or Java you really have to learn reading it. If you weighted the lambda syntaxes with the tiobe factor, arrows would be a minority.Well the C++2011 lambda syntax is quite foreign for C++ users, too.
Sep 24 2011
On 2011-09-24 06:51, Jonathan M Davis wrote:On Friday, September 23, 2011 23:42:52 Andrei Alexandrescu wrote:Scala uses the same syntax as well.On 9/23/11 8:03 PM, Martin Nowak wrote:_is_ a syntax familiar to some of the programmers who use a major language derived from C++. It's certainly going to be more familiar than the syntax of any of the functional languages out there.On Thu, 22 Sep 2011 22:54:55 +0200, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote: I want to add some points against introducing this particular syntax. 1. Foremost using '=>' is unfamiliar. Comming from C++ or Java you really have to learn reading it. If you weighted the lambda syntaxes with the tiobe factor, arrows would be a minority.Well the C++2011 lambda syntax is quite foreign for C++ users, too.My personal take on it is that if we want more compact lambdas, Andrei's rather than one of the functional languages, so it's more likely to be familiar to more D programmers (based on the assumption that D programmers are than any of the functional languages). So, it's probably the best that we're going to get for a compact lambda syntax. The only question is whether we really want to add a more compact lambda syntax, and I think that there's enough desire for it that we do. - Jonathan M Davis-- /Jacob Carlborg
Sep 24 2011
On Sat, 24 Sep 2011 06:42:52 +0200, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:On 9/23/11 8:03 PM, Martin Nowak wrote:=> looks like an infix operator. It harder to distinguish in a parameter list. The trailing right curly OTOH always ends a function. It makes it visually distinct and is highlighted/matchable in an ide. It prevents interaction of operators with the inner expression. sort!((a, b) => a <= b)(input) vs. sort!((a, b) { a <= b })(input) static assert ((a, b) => a < b != (a, b) => a > b) vs. static assert ((a, b) {a < b} != (a, b) {a > b}) Another minor issue: a => a + 3 Offers worse indentation for long expressions than (a) { a + 3 }On Thu, 22 Sep 2011 22:54:55 +0200, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote: I want to add some points against introducing this particular syntax. 1. Foremost using '=>' is unfamiliar. Comming from C++ or Java you really have to learn reading it. If you weighted the lambda syntaxes with the tiobe factor, arrows would be a minority.Well the C++2011 lambda syntax is quite foreign for C++ users, too.How often have you stopped reading about a language because the code examples were unreadable? Besides my liking for haskell, I don't want to see anything close to this on the D site. mergesortBy less [] = [] mergesortBy less xs = head $ until (null.tail) pairs [[x] | x <- xs] where pairs (x:y:t) = merge x y : pairs t pairs xs = xs merge (x:xs) (y:ys) | less y x = y : merge (x:xs) ys | otherwise = x : merge xs (y:ys) merge xs ys = xs ++ ysI don't understand the point being made here.2. D is not a functional language, using the implies arrow in 'a => write(1, a.ptr, a.length)' creates a horribly association.Hackeyed as that sounds, D is a multi-paradigm language and includes a lot of functional artifacts.3. I don't see any of the proposed rewrites is working for nullary delegates. '=> foo()' ??? Or '_ => foo()' => 'Error can't deduce parameter'.The comma-separated list may be empty.4. The expression is badly delimited. The first rewrite symbol => expression is actually symbol => expression\{CommaExpression, CatExpression}. E.g.: dgs ~= (int a) => (a + 5) ~ (int a) => (a ^^ 2); foo(a, b => (log(b), b), c) And that with a pending tuple syntax reclaming even more parens, comma overloads.Not sure I understand this point either, sorry.I've only found one argument being made for this.So D is a curly bracket language. http://en.wikipedia.org/wiki/List_of_programming_languages_by_category#Curly-bracket_languages What is wrong the, I think earlier proposed, very simple solution. http://www.digitalmars.com/d/2.0/expression.html#FunctionLiteral FunctionLiteral: function Typeopt ParameterAttributes opt FunctionLiteralBody delegate Typeopt ParameterAttributes opt FunctionLiteralBody ParameterAttributes FunctionLiteralBody FunctionLiteralBody ParameterAttributes: Parameters Parameters FunctionAttributes FunctionLiteralBody: FunctionBody '{' Expression '}' (a, b) {a+b} // takes the same amount of charactersWe've been discussing the issues of this form. Andrei2. What if the lambda wants to actually evaluate the expression but return void? 3. How is the semicolon relevant? (If its presence is used as a disambiguator for (2), it's poor design to predicate a large semantic difference on such a distinction.)It will error when you want to use the return value of the delegate. It will error when the expression has no side-effect. It allows to easily create a void return delegate. We already have implicit return for our second lambda syntax q{a+b}. Having both (a, b) { foo(a, b); } and (a, b) => foo(a, b) for such similar constructs is no good design either. after the fat arrow. Scala has an implicit return for this '() => { count += 1; count }'. Will we allow statements () => { return 5; }? We won't remove the existing function literal syntax due to code breakage. We won't remove the string predicates because they are still shorter. I am worried about having three subtly different language constructs for the same concept. (a, b) { return a < b; } | q{a < b} | (a, b) => a < b | old delegate syntax | string predicates | fat arrow delegates |-------------------------------------------------------------- scope | declaration | instantiation | declaration return | explicit | implicit | implicit body | statements | expression | expression types | optional | no | optional martin
Sep 24 2011
"Martin Nowak" , dans le message (digitalmars.D:145287), a écrit :this is a compile time error, because you are appending an int (a+5) with a delegate ((int a) => (a^^2)). You should write : dgs ~= [(int a) => a + 5), ((int a) => a ^^ 2)];4. The expression is badly delimited. The first rewrite symbol => expression is actually symbol => expression\{CommaExpression, CatExpression}. E.g.: dgs ~= (int a) => (a + 5) ~ (int a) => (a ^^ 2);That seems fine to me.foo(a, b => (log(b), b), c)sort!((a, b) => a <= b)(input) vs. sort!((a, b) { a <= b })(input)OKstatic assert ((a, b) => a < b != (a, b) => a > b)That is a compile time error too, because you use != on a boolean on one side, and on a delegate on the other side. You have to use parenthesis arround the delegates to use an operator on them, otherwise the operator could be a part of the delegate. static assert (((a, b) => a < b) != ((a, b) => a > b))vs. static assert ((a, b) {a < b} != (a, b) {a > b})OKAnother minor issue: a => a + 3 Offers worse indentation for long expressions than (a) { a + 3 }Why?We won't remove the existing function literal syntax due to code breakage. We won't remove the string predicates because they are still shorter. I am worried about having three subtly different language constructs for the same concept. (a, b) { return a < b; } | q{a < b} | (a, b) => a < b | old delegate syntax | string predicates | fat arrow delegates |-------------------------------------------------------------- scope | declaration | instantiation | declaration return | explicit | implicit | implicit body | statements | expression | expression types | optional | no | optionalDon't forget the return-omissing delegate syntax (a, b) { a < b } :P Old delegate should be kept as the normal way to build a delegate. They are needed to make more than one-liners. Maybe optional types might be removed in the long term to make the language simpler, but they can't be removed. In the long term (D>=3.0, not to break existing code), I am not sure it is worth keeping string predicates if delegates offer a convenient syntax. Moreover they are not a langage feature, they are a library feature. Nothing prevents people from writing a dozen syntax like that. -- Christophe
Sep 27 2011
Is there a reason why a new syntax is needed for anonymous function? Can we get the current one working and then worry about making things pretty? C++ anonymous function may not be any better, but it works, and that's in an experimental implementation (GCC 4.6).
Sep 28 2011
Caligo:C++ anonymous function may not be any better, but it works, and that's in an experimental implementation (GCC 4.6).In my not humble opinion C++0x lambdas are over-engineered (but they go along with the rest of the language). Bye, bearophile
Sep 28 2011
On 24/09/11 2:03 AM, Martin Nowak wrote:I want to add some points against introducing this particular syntax. 1. Foremost using '=>' is unfamiliar. Comming from C++ or Java you really have to learn reading it. If you weighted the lambda syntaxes with the tiobe factor, arrows would be a minority.Just wanted to jump in here and mention that Java is probably going to adopt this syntax for Java 8 lambdas. http://mail.openjdk.java.net/pipermail/lambda-dev/2011-September/003936.html Make of that what you will.
Sep 24 2011
"Martin Nowak" , dans le message (digitalmars.D:145209), a écrit :2. D is not a functional language, using the implies arrow in 'a => write(1, a.ptr, a.length)' creates a horribly association.I may repeat myself, but I think -> is a better symbol than =>. => is not just a mistyped comparison operator, it is also, like Martin say, the imply arrow in mathematical language. -> looks like mathematical function notation http://en.wikipedia.org/wiki/Function_%28mathematics%29#Notation although strictly speaking it should be |-> (but that one is horrible). I like both => / -> and (){} notations, both having advantages and inconvenients. -- Christophe
Sep 27 2011
What are the pros and cons of using "=>" rather than "->"? In an ideal world we might be able to use the correct "rightwards arrow from bar" character (u+21A6), but I'm not suggesting we try to make one out of the characters we can type ("|->" looks terrible). To my mind, "->" is somewhat closer to being mathematically correct, while "=>" reads as "implies", which is probably why lambdas in other languages have confused me. Is there a lexical justification for choosing "=>" over "->"? A...
Sep 24 2011
On 09/24/2011 01:24 PM, Alix Pexton wrote:What are the pros and cons of using "=>" rather than "->"? In an ideal world we might be able to use the correct "rightwards arrow from bar" character (u+21A6), but I'm not suggesting we try to make one out of the characters we can type ("|->" looks terrible). To my mind, "->" is somewhat closer to being mathematically correct, while "=>" reads as "implies", which is probably why lambdas in other languages have confused me. Is there a lexical justification for choosing "=>" over "->"? A...Both would work, but => and -> both can read as "implies", in which case => is a semantic implication (a statement that the implication is true) and -> is a mere binary boolean operator. (in languages that have this operator, it can be very useful for formulating assertions)
Sep 24 2011
Am 22.09.2011 22:54, schrieb Andrei Alexandrescu:On 9/21/11 5:17 PM, Walter Bright wrote:If we decide to add something like this, the => 'operator' has in my opinion to have a higher precidence thand ! or you should be able to write it at least without parenthesis (using other parser tricks). Like this: map!x=>x+1(list) MafiI've collected a few from various languages for comparison:[snip] I think we should do the following: 1. Introduce a new token "=>" 2. Add this rewrite to the grammar: symbol => expression translates to (symbol) { return expression; } 3. Add this rewrite to the grammar: symbol1 symbol2 => expression translates to (symbol1 symbol2) { return expression; } 4. Add this rewrite to the grammar: (comma_separated_parms) => expression translates to (comma_separated_parms) => expression Each item in comma_separated_parms may be 1 or 2 symbols separated by whitespace. Example: (int a, b) => a + b is valid and translates to (int a, b) { return a + b; } 5. The expression cannot contain commas at top level; an unparenthesized comma is considered to finish expression, just like in a function call's argument list. For example: fun(int a => a + 1, a + 2) is interpreted as fun((int a => a + 1), (a + 2)) To use comma inside expression, add parens around it. 5. Remove bugs and limitations. A function literal may specify none, all, or some parameter types, and the compiler correctly figures out the appropriate template and non-template parameters. The literal subsequently converts to function pointer or delegate whenever there's a match of parameter and result types. Andrei
Sep 25 2011
On 09/25/2011 11:43 AM, Mafi wrote:Am 22.09.2011 22:54, schrieb Andrei Alexandrescu:It cannot have higher precedence than !, because then your example would be parsed as (map!(x=>x))+(1(list)) Other parser tricks are impossible, because: map!(x=>x+y(list)) and map!(x=>x+y)(list) cannot be distinguished without parens.On 9/21/11 5:17 PM, Walter Bright wrote:If we decide to add something like this, the => 'operator' has in my opinion to have a higher precidence thand ! or you should be able to write it at least without parenthesis (using other parser tricks). Like this: map!x=>x+1(list)I've collected a few from various languages for comparison:[snip] I think we should do the following: 1. Introduce a new token "=>" 2. Add this rewrite to the grammar: symbol => expression translates to (symbol) { return expression; } 3. Add this rewrite to the grammar: symbol1 symbol2 => expression translates to (symbol1 symbol2) { return expression; } 4. Add this rewrite to the grammar: (comma_separated_parms) => expression translates to (comma_separated_parms) => expression Each item in comma_separated_parms may be 1 or 2 symbols separated by whitespace. Example: (int a, b) => a + b is valid and translates to (int a, b) { return a + b; } 5. The expression cannot contain commas at top level; an unparenthesized comma is considered to finish expression, just like in a function call's argument list. For example: fun(int a => a + 1, a + 2) is interpreted as fun((int a => a + 1), (a + 2)) To use comma inside expression, add parens around it. 5. Remove bugs and limitations. A function literal may specify none, all, or some parameter types, and the compiler correctly figures out the appropriate template and non-template parameters. The literal subsequently converts to function pointer or delegate whenever there's a match of parameter and result types. Andrei
Sep 25 2011
std.algorithm already introduces a sort of lambda syntax... map!"a+b"(...) or map!q{a+b}(...) If D is looking for its own style of short lambda, maybe implicit use of a and b could be extended. Candidates: a+b {a+b} f{a+b} auto{a+b} auto a+b Personally, I like the 2nd or 3rd one. The second is visually cleaner while the 3rd is easily parsed and feels very similar to q strings. I picked f because that's frequently used to represent a function. x could work, but that's a common variable name... Walter Bright Wrote:I've collected a few from various languages for comparison: D (a,b) { return a + b; } Ruby ->(a,b) { a + b } C++0x [](int a, int b) { return a + b; } (a,b) => a + b Scala (a:Int, b:Int) => a + b Erlang fun(a, b) -> a + b end. Haskell \a b -> a + b Javascript function(a,b) { return a + b; } Clojure Lua function(a,b) return a + b end Python lambda a,b: a + b
Sep 22 2011
On Thu, 22 Sep 2011 18:59:31 -0400, Jason House <jason.james.house gmail.com> wrote:std.algorithm already introduces a sort of lambda syntax... map!"a+b"(...) or map!q{a+b}(...) If D is looking for its own style of short lambda, maybe implicit use of a and b could be extended. Candidates: a+b {a+b} f{a+b} auto{a+b} auto a+b Personally, I like the 2nd or 3rd one. The second is visually cleaner while the 3rd is easily parsed and feels very similar to q strings. I picked f because that's frequently used to represent a function. x could work, but that's a common variable name...I like the idea, although 1,2,3 and 5 are too close to valid D syntax for my comfort. We could borrow from Haskell: \{a+b} But I'd prefer not to have special syntax rules inside lambda blocks. (It increases the cognitive load of D) So why not make it a statement? i.e. \a+b; then {} would only be for multi-statement or void functions: \{a+b; return;} What I worry about though is variable hijacking rules. e.g. auto b = 5; reduce!\a+b(map!\a+b([1,2,3,4));
Sep 22 2011
Robert Jacques:What I worry about though is variable hijacking rules. e.g. auto b = 5; reduce!\a+b(map!\a+b([1,2,3,4));Right, it's a bit too much magical and inflexible for my taste. bye, bearophile
Sep 22 2011
"Robert Jacques" <sandford jhu.edu> wroteWhat I worry about though is variable hijacking rules. e.g. auto b = 5; reduce!\a+b(map!\a+b([1,2,3,4));Nice. What if we extend your proposal to \(comma_separated_params)simple_expression \(comma_separated_params){expressions} Then no variable hijacking would be auto b = 5; reduce!\(a)a+b(map!\(x)x+b([1,2,3,4)); reduce!\a+b(map!\a+b([1,2,3,4)); //error, shadowing b
Sep 23 2011
"Alex_Dovhal" <alex_dovhal yahoo.com> wrotereduce!\(a)a+b(map!\(x)x+b([1,2,3,4));Sorry, my mistake reduce!\(a,b)a+b(map!\(x)x+b([1,2,3,4));
Sep 23 2011
On Fri, 23 Sep 2011 03:03:04 -0400, Alex_Dovhal <alex_dovhal yahoo.com> wrote:"Robert Jacques" <sandford jhu.edu> wroteWell, actually, this is Jason's proposal and it's explicitly for a std.algorithm style, by convention, super-short lambda syntax. i.e. primarily for one liners and std.algorithm. If you go the comma_separated_params, then I think the a => a+x; route is better. Actually, I made a error in my final example as each lambda must be terminated somehow. i.e. with a semi-colon: reduce!\a+b;(map!\a+b;([1,2,3,4)) Also, you could consider !\ to be a bit redundent and allow 'symbol\statement' to be lowered to 'symbol!\statement'. Thus the following would also be valid: reduce\a+b;(map\a+b;([1,2,3,4)); As for hijacking, I think by-convention lambdas should be disallowed if a or b are used in the lambda and are already defined in the namespace. In those cases, you'd have to revert to a more general syntax, i.e. reduce!"a+b"(map!(a => a+b)([1,2,3,4)));What I worry about though is variable hijacking rules. e.g. auto b = 5; reduce!\a+b(map!\a+b([1,2,3,4));Nice. What if we extend your proposal to \(comma_separated_params)simple_expression \(comma_separated_params){expressions} Then no variable hijacking would be auto b = 5; reduce!\(a)a+b(map!\(x)x+b([1,2,3,4)); reduce!\a+b(map!\a+b([1,2,3,4)); //error, shadowing b
Sep 23 2011
"Robert Jacques" <sandford jhu.edu> wroteWell, actually, this is Jason's proposal and it's explicitly for a std.algorithm style, by convention, super-short lambda syntax. i.e. primarily for one liners and std.algorithm. If you go the comma_separated_params, then I think the a => a+x; route is better.Maybe, x=>f(x) syntax isn't bad, but in most simple and most oftern cases -- \a*a is 4 chars while a=>a*a is 6 chars. Then \(x,y)x+y is 9 chars, (x,y)=>x+y is 10 chars, while \a+b is still 4 chars.Actually, I made a error in my final example as each lambda must be terminated somehow. i.e. with a semi-colon: reduce!\a+b;(map!\a+b;([1,2,3,4))No. Those semicolons in the middle of expression looks strange. Compiler can't determine that expression following ! has ended so you must use !() int b = 5; reduce!(\(a,b)a+b)(map!(\(a)a+b)([1, 2, 3, 4]))As for hijacking, I think by-convention lambdas should be disallowed if a or b are used in the lambda and are already defined in the namespace. In those cases, you'd have to revert to a more general syntax, i.e. reduce!"a+b"(map!(a => a+b)([1,2,3,4)));In such not often cases one can even use long lambdas reduce!"a+b"(map!((int a){return a+b;})([1,2,3,4]))); BTW, existing usage of strings ("a+b") is second shortest afrer \a+b and is properly delimited. maybe allowing several variations of \lambdas (1) \a+b - automatic names, shortest lambda possible, easy to read. for use when it can be easily delimited e.g list_comprehent!(\a*a, \a!=1)(a) (2) \{a+b} - automatic names, to properly delimit lambda, usefil in map!\{a*a}(a), eh, you are rigth here compiler can omit ! -- map\{a*a}(a) (3) \(x)x+a -- explicit names, to prevent name hijacking. (4) \(x){x+a} - explicit names and properly delimited in (1) and (3) no comma allowed, as it can cause ambiguities.
Sep 24 2011
On Sat, 24 Sep 2011 03:23:13 -0400, Alex_Dovhal <alex_dovhal yahoo.com> wrote:"Robert Jacques" <sandford jhu.edu> wroteI'm not sure you understand the main point: there are multiple ways to define a lambda. So \a+b and (a,b)=>a+b could co-exist together just fine.Well, actually, this is Jason's proposal and it's explicitly for a std.algorithm style, by convention, super-short lambda syntax. i.e. primarily for one liners and std.algorithm. If you go the comma_separated_params, then I think the a => a+x; route is better.Maybe, x=>f(x) syntax isn't bad, but in most simple and most oftern cases -- \a*a is 4 chars while a=>a*a is 6 chars. Then \(x,y)x+y is 9 chars, (x,y)=>x+y is 10 chars, while \a+b is still 4 chars.How is !() different from !\; ? \; is for literals. Hence, it would work just like !"a+b".Actually, I made a error in my final example as each lambda must be terminated somehow. i.e. with a semi-colon: reduce!\a+b;(map!\a+b;([1,2,3,4))No. Those semicolons in the middle of expression looks strange. Compiler can't determine that expression following ! has ended so you must use !()int b = 5; reduce!(\(a,b)a+b)(map!(\(a)a+b)([1, 2, 3, 4]))Which is what I was suggesting, although I used the most concise syntax: a => a+b Also, as non-trivial use of algorithm often results in 120+ line widths, today using the "a+b" style syntax, conciseness is golden.As for hijacking, I think by-convention lambdas should be disallowed if a or b are used in the lambda and are already defined in the namespace. In those cases, you'd have to revert to a more general syntax, i.e. reduce!"a+b"(map!(a => a+b)([1,2,3,4)));In such not often cases one can even use long lambdas reduce!"a+b"(map!((int a){return a+b;})([1,2,3,4])));BTW, existing usage of strings ("a+b") is second shortest afrer \a+b and is properly delimited. maybe allowing several variations of \lambdas (1) \a+b - automatic names, shortest lambda possible, easy to read. for use when it can be easily delimited e.g list_comprehent!(\a*a, \a!=1)(a) (2) \{a+b} - automatic names, to properly delimit lambda, usefil in map!\{a*a}(a), eh, you are rigth here compiler can omit ! -- map\{a*a}(a) (3) \(x)x+a -- explicit names, to prevent name hijacking. (4) \(x){x+a} - explicit names and properly delimited in (1) and (3) no comma allowed, as it can cause ambiguities.
Sep 24 2011
On 09/22/2011 01:17 AM, Walter Bright wrote:I've collected a few from various languages for comparison: D (a,b) { return a + b; }I prefer to make "return" optional as the argument type
Sep 22 2011
El 22/09/2011 0:17, Walter Bright escribió:I've collected a few from various languages for comparison: D (a,b) { return a + b; } Ruby ->(a,b) { a + b } C++0x [](int a, int b) { return a + b; } (a,b) => a + b Scala (a:Int, b:Int) => a + b Erlang fun(a, b) -> a + b end. Haskell \a b -> a + b Javascript function(a,b) { return a + b; } Clojure Lua function(a,b) return a + b end Python lambda a,b: a + bJust for the record, Vala also uses (a, b) => a + b no curly braces needed if only one statement, and no argument types. http://live.gnome.org/Vala/Tutorial#Delegates BTW, al least superficially, Vala reminds me of D quite a lot.
Sep 24 2011