digitalmars.D - Lambda syntax, etc
- bearophile (31/34) Feb 04 2009 I've taken a look at the syntax for lambda in other C-like languages.
- BCS (4/24) Feb 04 2009 That syntax, and a few of the below, show the one major gripe I have wit...
- Andrei Alexandrescu (4/18) Feb 04 2009 Strings are immune from the problem. :o) Also they make for readily
- Nick Sabalausky (10/28) Feb 04 2009 I would be all for the string-style, *if* things like the following were...
- Yigal Chripun (13/31) Feb 04 2009 Personally I prefer to have syntax for "blocks" like Ruby/smalltalk.
- Nick Sabalausky (8/41) Feb 04 2009 Agreed. This is what I had always been ultimately hoping for. I'd be hap...
- BCS (5/54) Feb 04 2009 Why use this:
- Bill Baxter (6/60) Feb 04 2009 I was about to say the same thing, but I think Yigal was just mixing
- BCS (5/10) Feb 04 2009 I don't like that
- Nick Sabalausky (28/39) Feb 04 2009 Then we're agreed on that part :)
- Nick Sabalausky (6/11) Feb 04 2009 This one has the added benefit of making it easy to distinguish between ...
- Bill Baxter (11/23) Feb 04 2009 I agree. Putting the args inside the { } is much more readable to me to...
- Bill Baxter (4/18) Feb 04 2009 Oh, and last semicolon of a function should be optional :-)
- Nick Sabalausky (15/43) Feb 04 2009 I'd be fine with that. Actually, I think I like that a little better (fo...
- Bill Baxter (7/15) Feb 04 2009 Well the nice thing about it was you could do this:
- Jarrett Billingsley (5/11) Feb 04 2009 Psh! All that has to happen grammatically is that instead of using a
- BCS (6/19) Feb 04 2009 I have used bare block statements on occasion and a missing ';' in the w...
- Nick Sabalausky (43/63) Feb 04 2009 I think I see what you mean. Although, that does create an inconsistency...
- BCS (4/8) Feb 05 2009 I think that way can be made even stronger my making the delegate/block ...
- Yigal Chripun (18/81) Feb 04 2009 not exactly. the reason why I changed the syntax like that is because of...
- Chris Nicholson-Sauls (8/18) Feb 05 2009 While I know the compiler could (should) know the difference easily
- BCS (5/13) Feb 05 2009 and then pull in those names implicitly
- Robert Fraser (3/22) Feb 05 2009 Ew, no. Aside from the technical issues, this distances the names from
- Chris Nicholson-Sauls (4/27) Feb 05 2009 While I fundamentally agree, it could also be nice to /allow/ the names
- hsyl20 (9/18) Feb 04 2009 In Scala :
- bearophile (6/8) Feb 04 2009 There's a subtle line between "no boilerplate" and "magic (variables)", ...
- Nick Sabalausky (8/25) Feb 04 2009 I like that very much, especially since you can use either the implicit ...
- hsyl20 (13/23) Feb 04 2009 You can use several "_", for instance:
- Yigal Chripun (8/30) Feb 05 2009 this seems counter-intuitive to me. Nemerle uses this syntax for
- Kagamin (2/12) Feb 05 2009 Yeah, C# lambdas are the killer feature. Slick, readable, C-compatible. ...
- Denis Koroskin (16/32) Feb 05 2009 I don't like C# lambda syntax (although it is not half as bad as C++ lam...
- Andrei Alexandrescu (13/63) Feb 05 2009 What if you wanted to just execute one expression and return void? This
- Denis Koroskin (26/77) Feb 05 2009 No problem:
- Kagamin (4/10) Feb 09 2009 Holy shi-
- Denis Koroskin (4/14) Feb 09 2009 That was just an example. Those short lambdas are often used as predicat...
- Andrei Alexandrescu (15/30) Feb 05 2009 Without knowing the person, I disagree you could infer that from C#.
- bearophile (18/20) Feb 05 2009 Andrei Alexandrescu>Beyond that, I don't feel that changes like moving t...
- Bartosz Milewski (4/5) Feb 09 2009 I also believe that, for readability reasons, lambdas should have some d...
- Jarrett Billingsley (18/22) Feb 09 2009 of a (){ return ;} (or with the =3D> of C#) helps the eye see a single ...
- bearophile (10/18) Feb 09 2009 This looks better to me (but I don't know if this is the best syntax, it...
- grauzone (3/6) Feb 09 2009 Note the -> instead of the =>, to avoid any ambiguities with the
- bearophile (13/18) Feb 09 2009 Let's play more; then what do you think about (all the following are leg...
- bearophile (6/7) Feb 09 2009 Better:
- grauzone (6/28) Feb 09 2009 Agreed.
- Nick Sabalausky (5/22) Feb 09 2009 I'd rather have everything use "::" (consistent), and then say that the
- grauzone (3/6) Feb 05 2009 I find this statement rather ironic, because you also seem to be quite
- Andrei Alexandrescu (12/21) Feb 05 2009 I do understand you dislike strings as lambdas, but please do not use
- BCS (6/10) Feb 05 2009 I have never met the man, but it is my impression that Anders didn't mis...
- Christopher Wright (9/10) Feb 05 2009 C# delegates in C# 2.0 are annoying. I try not to use them. The reason:
- Nick Sabalausky (24/37) Feb 05 2009 C# provided my first introduction to delegates (not counting
- Robert Fraser (2/5) Feb 05 2009 Ugh, don't remind me!
- hsyl20 (14/41) Feb 06 2009 "_" is used for currying in Scala too.
- Kagamin (4/13) Feb 09 2009 C# got anough rope for this :)
- Christopher Wright (2/17) Feb 09 2009 Eugh! Just eugh!
- Kagamin (3/11) Feb 10 2009 auto r = find(range, {a -> a.Weight <- 100});
- bearophile (4/5) Feb 10 2009 Take a look at how the Fortress language manages spaces inside expressio...
- Kagamin (2/6) Feb 10 2009 There is no error here, since there's no <- operator, the construct is u...
- Kagamin (2/7) Feb 10 2009 well, every construct can look weird in some environment.
- bearophile (8/9) Feb 10 2009 In Fortress the syntax of this expression is OK:
I've taken a look at the syntax for lambda in other C-like languages. This is from Functional Java: http://functionaljava.org/examples#Array.filter In Functional Java you can write this D syntax: (int i, int j) { return i % 3 == j; } as: { int i, int j => i % 3 == j } It's shorter and less cluttered/noisy than the D syntax, and it doesn't require more type inferencing (but I think you can't put statements there, so it's less powerful). With that Java syntax extension you can write: final Array<Integer> a = array(97, 44, 67, 3, 22, 90, 1, 77, 98, 1078, 6, 64, 6, 79, 42); final Array<Integer> b = a.filter({int i => i % 2 == 0}); In D (with dlibs) it is: auto a = [97, 44, 67, 3, 22, 90, 1, 77, 98, 1078, 6, 64, 6, 79, 42]; auto b = a.filter((int i){return !(i % 2);}); With std.algorithm it may be a bit shorter. In Python: a = [97, 44, 67, 3, 22, 90, 1, 77, 98, 1078, 6, 64, 6, 79, 42] b = [x for x in a if not(i % 2)] supports the following syntaxes: To define a delegate o delegate closure: Func<int> foo = i => { return i % 3 == 1; }; Func<int> foo = i => i % 3 == 1; Func<int> bar = () => 2; But this isn't allowed: Func<void> bar = () => 2;for the closure depending on if the function needs to close over the local scope or not.<When such an expression is evaluated, it produces a function-object which can be called with the arguments implied by the LambdaList, and whose body expressions have access to all the lexical variables that are visible at that point. The ones that are outside of the expression, whose bindings were established before it was created, are captured. This is why the resulting object is called a LexicalClosure.<Even when the code uses the closure more than once, the compiler creates only one instance of the closure. That environment is reused each time.<Bye, bearophile
Feb 04 2009
Hello bearophile,I've taken a look at the syntax for lambda in other C-like languages. This is from Functional Java: http://functionaljava.org/examples#Array.filter In Functional Java you can write this D syntax: (int i, int j) { return i % 3 == j; } as: { int i, int j => i % 3 == j }That syntax, and a few of the below, show the one major gripe I have with ultra-compact lambdas: it's hard to *quickly* spot the args/code transition. [...]To define a delegate o delegate closure: Func<int> foo = i => { return i % 3 == 1; }; Func<int> foo = i => i % 3 == 1; Func<int> bar = () => 2;
Feb 04 2009
BCS wrote:Hello bearophile,Strings are immune from the problem. :o) Also they make for readily recognizable code because they all use the same argument names. AndreiI've taken a look at the syntax for lambda in other C-like languages. This is from Functional Java: http://functionaljava.org/examples#Array.filter In Functional Java you can write this D syntax: (int i, int j) { return i % 3 == j; } as: { int i, int j => i % 3 == j }That syntax, and a few of the below, show the one major gripe I have with ultra-compact lambdas: it's hard to *quickly* spot the args/code transition.
Feb 04 2009
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message news:gmclr4$2q30$1 digitalmars.com...BCS wrote:I would be all for the string-style, *if* things like the following were fixed: int foo1(int i) { /*stuff*/ } void bar(int[] ints) { int foo2(int i) { /*stuff*/ } auto x = ints.map!("foo1(a)+foo2(a)")(); }Hello bearophile,Strings are immune from the problem. :o) Also they make for readily recognizable code because they all use the same argument names. AndreiI've taken a look at the syntax for lambda in other C-like languages. This is from Functional Java: http://functionaljava.org/examples#Array.filter In Functional Java you can write this D syntax: (int i, int j) { return i % 3 == j; } as: { int i, int j => i % 3 == j }That syntax, and a few of the below, show the one major gripe I have with ultra-compact lambdas: it's hard to *quickly* spot the args/code transition.
Feb 04 2009
Andrei Alexandrescu wrote:BCS wrote:Personally I prefer to have syntax for "blocks" like Ruby/smalltalk. given the following example function: int func(int a, delegate int(int) dg) { .. } // call func with [something in this spirit is my favorite]: func(someInt) { | int a, int b | return a+b; }; compare with the current D syntax: func( someInt, (int a, int b) {return a+b;} ); compare with a lamda syntax: func(someInt, { int a, int b => a+b } ); blocks are more useful - they are not limited to just one expression, and I think are a more general construct. lamdas/array comps, are just special cases.Hello bearophile,Strings are immune from the problem. :o) Also they make for readily recognizable code because they all use the same argument names. AndreiI've taken a look at the syntax for lambda in other C-like languages. This is from Functional Java: http://functionaljava.org/examples#Array.filter In Functional Java you can write this D syntax: (int i, int j) { return i % 3 == j; } as: { int i, int j => i % 3 == j }That syntax, and a few of the below, show the one major gripe I have with ultra-compact lambdas: it's hard to *quickly* spot the args/code transition.
Feb 04 2009
"Yigal Chripun" <yigal100 gmail.com> wrote in message news:gmd0u8$fg7$1 digitalmars.com...Andrei Alexandrescu wrote:Agreed. This is what I had always been ultimately hoping for. I'd be happy with the string stuff if that "wrong scope" issue gets fixed (that I mentioned in another branch of this thread), but I'd still prefer this (especially if the types for the params could somehow be inferred and omitted like this: "func(someInt) { |a,b| return a+b; };" ) ).BCS wrote:Personally I prefer to have syntax for "blocks" like Ruby/smalltalk. given the following example function: int func(int a, delegate int(int) dg) { .. } // call func with [something in this spirit is my favorite]: func(someInt) { | int a, int b | return a+b; }; compare with the current D syntax: func( someInt, (int a, int b) {return a+b;} ); compare with a lamda syntax: func(someInt, { int a, int b => a+b } ); blocks are more useful - they are not limited to just one expression, and I think are a more general construct. lamdas/array comps, are just special cases.Hello bearophile,Strings are immune from the problem. :o) Also they make for readily recognizable code because they all use the same argument names. AndreiI've taken a look at the syntax for lambda in other C-like languages. This is from Functional Java: http://functionaljava.org/examples#Array.filter In Functional Java you can write this D syntax: (int i, int j) { return i % 3 == j; } as: { int i, int j => i % 3 == j }That syntax, and a few of the below, show the one major gripe I have with ultra-compact lambdas: it's hard to *quickly* spot the args/code transition.
Feb 04 2009
Reply to Nick,"Yigal Chripun" <yigal100 gmail.com> wrote in message news:gmd0u8$fg7$1 digitalmars.com...Why use this: "func(someInt) { |a,b| return a+b; };" when you can reuse syntax and get this for the same amount of typeing "func(someInt) (a,b){ return a+b; };"Andrei Alexandrescu wrote:Agreed. This is what I had always been ultimately hoping for. I'd be happy with the string stuff if that "wrong scope" issue gets fixed (that I mentioned in another branch of this thread), but I'd still prefer this (especially if the types for the params could somehow be inferred and omitted like this: ) ).BCS wrote:Personally I prefer to have syntax for "blocks" like Ruby/smalltalk. given the following example function: int func(int a, delegate int(int) dg) { .. } // call func with [something in this spirit is my favorite]: func(someInt) { | int a, int b | return a+b; }; compare with the current D syntax: func( someInt, (int a, int b) {return a+b;} ); compare with a lamda syntax: func(someInt, { int a, int b => a+b } ); blocks are more useful - they are not limited to just one expression, and I think are a more general construct. lamdas/array comps, are just special cases.Hello bearophile,Strings are immune from the problem. :o) Also they make for readily recognizable code because they all use the same argument names. AndreiI've taken a look at the syntax for lambda in other C-like languages. This is from Functional Java: http://functionaljava.org/examples#Array.filter In Functional Java you can write this D syntax: (int i, int j) { return i % 3 == j; } as: { int i, int j => i % 3 == j }That syntax, and a few of the below, show the one major gripe I have with ultra-compact lambdas: it's hard to *quickly* spot the args/code transition.
Feb 04 2009
On Thu, Feb 5, 2009 at 7:26 AM, BCS <ao pathlink.com> wrote:Reply to Nick,I was about to say the same thing, but I think Yigal was just mixing two distinct suggestions together: 1) the trailing delegates proposal (aka ruby block) and 2) A ruby-like syntax for delegate literals : {|a,b| return a+b;} --bb"Yigal Chripun" <yigal100 gmail.com> wrote in message news:gmd0u8$fg7$1 digitalmars.com...Why use this: "func(someInt) { |a,b| return a+b; };" when you can reuse syntax and get this for the same amount of typeing "func(someInt) (a,b){ return a+b; };"Andrei Alexandrescu wrote:Agreed. This is what I had always been ultimately hoping for. I'd be happy with the string stuff if that "wrong scope" issue gets fixed (that I mentioned in another branch of this thread), but I'd still prefer this (especially if the types for the params could somehow be inferred and omitted like this: ) ).BCS wrote:Personally I prefer to have syntax for "blocks" like Ruby/smalltalk. given the following example function: int func(int a, delegate int(int) dg) { .. } // call func with [something in this spirit is my favorite]: func(someInt) { | int a, int b | return a+b; }; compare with the current D syntax: func( someInt, (int a, int b) {return a+b;} ); compare with a lamda syntax: func(someInt, { int a, int b => a+b } ); blocks are more useful - they are not limited to just one expression, and I think are a more general construct. lamdas/array comps, are just special cases.Hello bearophile,Strings are immune from the problem. :o) Also they make for readily recognizable code because they all use the same argument names. AndreiI've taken a look at the syntax for lambda in other C-like languages. This is from Functional Java: http://functionaljava.org/examples#Array.filter In Functional Java you can write this D syntax: (int i, int j) { return i % 3 == j; } as: { int i, int j => i % 3 == j }That syntax, and a few of the below, show the one major gripe I have with ultra-compact lambdas: it's hard to *quickly* spot the args/code transition.
Feb 04 2009
Reply to Bill,I like thatI was about to say the same thing, but I think Yigal was just mixingtwo distinct suggestions together: 1) the trailing delegates proposal (aka ruby block) and2) A ruby-like syntax for delegate literals : {|a,b| return a+b;}I don't like thatvoid DoIt(int delegate(int) dg...)D laready has this syntax for Typesafe Variadic Functions http://www.digitalmars.com/d/1.0/function.html
Feb 04 2009
"BCS" <ao pathlink.com> wrote in message news:78ccfa2d39bdc8cb54edb3210678 news.digitalmars.com...Reply to Bill,Then we're agreed on that part :)I like thatI was about to say the same thing, but I think Yigal was just mixingtwo distinct suggestions together: 1) the trailing delegates proposal (aka ruby block) andThe thing I like about that is that it makes it much more clear at a glance that the "a,b" or "int a, int b" is associated with the code block (but without the problem some languages have of making it hard to distinguish from the block's body). For the sake of syntax-consistency I would be perfectly willing to allow (or even require) functions to be defined the same way: int add { |int x, int y| return x+y; } Or: // "func" used to disambiguate between function call and function declaration func add { |int <- int x, int y | return x+y; } Or maybe parens instead of pipes (this is similar to K&R C, isn't it?): int add { (int x, int y) return x+y; } Although I'm sure any of those would be prohibitively unpopular.2) A ruby-like syntax for delegate literals : {|a,b| return a+b;}I don't like thatI'm not quite convinced either way on this. For what reasons do you think the function header should be required to indicate "this uses block syntax"? What's wrong with just saying "If the last arg a function takes is a delegate, then that delegate can optionally be specified with block syntax."?void DoIt(int delegate(int) dg...)D laready has this syntax for Typesafe Variadic Functions http://www.digitalmars.com/d/1.0/function.html
Feb 04 2009
"Nick Sabalausky" <a a.a> wrote in message news:gmdtjl$2f4j$1 digitalmars.com...// "func" used to disambiguate between function call and function declaration func add { |int <- int x, int y | return x+y; }This one has the added benefit of making it easy to distinguish between an attribute of the function and an attribute of the function's return value (Although I guess that's not much of an issue with the current versions of D2).
Feb 04 2009
On Thu, Feb 5, 2009 at 2:30 PM, Nick Sabalausky <a a.a> wrote:I agree. Putting the args inside the { } is much more readable to me too. Even just putting the parens inside rather than outside seems an improvement. Or how about { int x; int y :: return x+y; }The thing I like about that is that it makes it much more clear at a glance that the "a,b" or "int a, int b" is associated with the code block (but without the problem some languages have of making it hard to distinguish from the block's body).2) A ruby-like syntax for delegate literals : {|a,b| return a+b;}I don't like thatOr maybe parens instead of pipes (this is similar to K&R C, isn't it?): int add { (int x, int y) return x+y; }K&R was like int add(x,y) int x; int y; { return x+y } --bb
Feb 04 2009
On Thu, Feb 5, 2009 at 2:56 PM, Bill Baxter <wbaxter gmail.com> wrote:On Thu, Feb 5, 2009 at 2:30 PM, Nick Sabalausky <a a.a> wrote:Oh, and last semicolon of a function should be optional :-) { int x; int y :: return x+y } --bbI agree. Putting the args inside the { } is much more readable to me too. Even just putting the parens inside rather than outside seems an improvement. Or how about { int x; int y :: return x+y; }The thing I like about that is that it makes it much more clear at a glance that the "a,b" or "int a, int b" is associated with the code block (but without the problem some languages have of making it hard to distinguish from the block's body).2) A ruby-like syntax for delegate literals : {|a,b| return a+b;}I don't like that
Feb 04 2009
"Bill Baxter" <wbaxter gmail.com> wrote in message news:mailman.651.1233813474.22690.digitalmars-d puremagic.com...On Thu, Feb 5, 2009 at 2:56 PM, Bill Baxter <wbaxter gmail.com> wrote:I'd be fine with that. Actually, I think I like that a little better (for a couple of reasons which I seem to be finding difficult to put into words. It's like, making a clear "split" or division in the block instead of having what looks like this thing that's just kind of floating around, and forever having those two "grouping openers" right next to each other, ie, "{ (" or "{ |" . ) But I'm not sure about replacing the commas with semicolons, unless it meant you could do: { int x, y :: return x+y; } But then, I'm not sure how I feel about that either.On Thu, Feb 5, 2009 at 2:30 PM, Nick Sabalausky <a a.a> wrote:I agree. Putting the args inside the { } is much more readable to me too. Even just putting the parens inside rather than outside seems an improvement. Or how about { int x; int y :: return x+y; }The thing I like about that is that it makes it much more clear at a glance that the "a,b" or "int a, int b" is associated with the code block (but without the problem some languages have of making it hard to distinguish from the block's body).2) A ruby-like syntax for delegate literals : {|a,b| return a+b;}I don't like thatK&R was like int add(x,y) int x; int y; { return x+y }Oh that's right, I knew it was something funky like that. (That would be a "bad redundancy". /me nods to Walter's Dobbs article.)Oh, and last semicolon of a function should be optional :-) { int x; int y :: return x+y }Now there's a language war waiting to happen ;)
Feb 04 2009
On Thu, Feb 5, 2009 at 3:20 PM, Nick Sabalausky <a a.a> wrote:Well the nice thing about it was you could do this: int add(x,y) CrazyLongTypeName x,y; { return x+y } Thereby removing some bad redundancy. --bbK&R was like int add(x,y) int x; int y; { return x+y }Oh that's right, I knew it was something funky like that. (That would be a "bad redundancy". /me nods to Walter's Dobbs article.)
Feb 04 2009
On Thu, Feb 5, 2009 at 1:20 AM, Nick Sabalausky <a a.a> wrote:Psh! All that has to happen grammatically is that instead of using a raw semicolon to terminate statements, you have a StatementTerminator nonterminal which goes to either semicolon or non-consuming right brace. It's trivial to implement in the compiler too.Oh, and last semicolon of a function should be optional :-) { int x; int y :: return x+y }Now there's a language war waiting to happen ;)
Feb 04 2009
Hello Nick,I have used bare block statements on occasion and a missing ';' in the wrong place would be nasty to parse. Another option for killing that problem would be to forbid overloading only on a trailing delegate so Foo(int) and Foo(int, int delegate()) would be considered ambiguous (that argues for the ... as then the rule would be to forbid overloading only on block delegates)I'm not quite convinced either way on this. For what reasons do you think the function header should be required to indicate "this uses block syntax"? What's wrong with just saying "If the last arg a function takes is a delegate, then that delegate can optionally be specified with block syntax."?void DoIt(int delegate(int) dg...)D laready has this syntax for Typesafe Variadic Functions http://www.digitalmars.com/d/1.0/function.html
Feb 04 2009
"BCS" <none anon.com> wrote in message news:a6268ff24108cb552c70a0af6c news.digitalmars.com...Hello Nick,I think I see what you mean. Although, that does create an inconsistency that bothers me a bit, because then some functions with trailing delegate params could be called with block syntax and others couldn't. And then the ones that can be called that way have a restriction on overloading and the ones that can't, don't have that restriction. Just seems messy to me. Maybe instead of requiring anything in the declaration, any use of the block statement style could be required to include a paramater list (and disallowing block statement style for varargs): void foo(int a) {/*stuff*/} void foo(int a, void dg(void)) {/*stuff*/} // Ok foo(5, { writefln("hi"); } ); // Ok, calls foo(int) foo(5); { writefln("hi"); } // Illegal (because of [1]) *even* if the // "foo(int)" overload doesn't exist foo(5) { writefln("hi"); } // Ok, calls foo(int, void delegate(void)) foo(5) (void) { writefln("hi"); } // Illegal, because of [2] foo(5); (void) { writefln("hi"); } // [1]: Already Illegal: // (However, this would become ambiguous with [3], // but that could be solved by block-statement-style // being disallowed for varargs) writefln("hi") { writefln("hi"); } // [2]: Already Illegal? (Or is it a "verb-less" // delegate literal expression statement?): (int a) { writefln("hi"); } // [3] writefln("hi", {writefln("hi");} ); This way, it's impossible to take valid code, add or remove a semicolon, and still have valid code (which I think was your main concern?).I have used bare block statements on occasion and a missing ';' in the wrong place would be nasty to parse. Another option for killing that problem would be to forbid overloading only on a trailing delegate so Foo(int) and Foo(int, int delegate()) would be considered ambiguous (that argues for the ... as then the rule would be to forbid overloading only on block delegates)I'm not quite convinced either way on this. For what reasons do you think the function header should be required to indicate "this uses block syntax"? What's wrong with just saying "If the last arg a function takes is a delegate, then that delegate can optionally be specified with block syntax."?void DoIt(int delegate(int) dg...)D laready has this syntax for Typesafe Variadic Functions http://www.digitalmars.com/d/1.0/function.html
Feb 04 2009
Reply to Nick,This way, it's impossible to take valid code, add or remove a semicolon, and still have valid code (which I think was your main concern?).I think that way can be made even stronger my making the delegate/block need a trailing ';' (it's a function call after all) where a bare block statement does not.
Feb 05 2009
Bill Baxter wrote:On Thu, Feb 5, 2009 at 7:26 AM, BCS<ao pathlink.com> wrote:not exactly. the reason why I changed the syntax like that is because of templates. for example: void func(T, int i)(T a, delegate int(int) dg) {...} with your and BCS' proposal the above would be called like so: func!(SomeType, 15)(someVar)(a,b){ return a+b; }; this is less clear, IMO. besides, I really like Ruby's (and before that Smalltalk's) syntax to handle this. <g> to Nick - you mentioned the scoping problem with strings. Personally I *HATE* this use of strings. it has many issues which I already mentioned in previous posts. to specifically address your point - what your looking for is called "Hygienic Macros" - http://en.wikipedia.org/wiki/Hygienic_macros basically you want to control which arguments to your AST macro are evaluated at which scope. This i'd like to see implemented in D when AST macros are added.Reply to Nick,I was about to say the same thing, but I think Yigal was just mixing two distinct suggestions together: 1) the trailing delegates proposal (aka ruby block) and 2) A ruby-like syntax for delegate literals : {|a,b| return a+b;} --bb"Yigal Chripun"<yigal100 gmail.com> wrote in message news:gmd0u8$fg7$1 digitalmars.com...Why use this: "func(someInt) { |a,b| return a+b; };" when you can reuse syntax and get this for the same amount of typeing "func(someInt) (a,b){ return a+b; };"Andrei Alexandrescu wrote:Agreed. This is what I had always been ultimately hoping for. I'd be happy with the string stuff if that "wrong scope" issue gets fixed (that I mentioned in another branch of this thread), but I'd still prefer this (especially if the types for the params could somehow be inferred and omitted like this: ) ).BCS wrote:Personally I prefer to have syntax for "blocks" like Ruby/smalltalk. given the following example function: int func(int a, delegate int(int) dg) { .. } // call func with [something in this spirit is my favorite]: func(someInt) { | int a, int b | return a+b; }; compare with the current D syntax: func( someInt, (int a, int b) {return a+b;} ); compare with a lamda syntax: func(someInt, { int a, int b => a+b } ); blocks are more useful - they are not limited to just one expression, and I think are a more general construct. lamdas/array comps, are just special cases.Hello bearophile,Strings are immune from the problem. :o) Also they make for readily recognizable code because they all use the same argument names. AndreiI've taken a look at the syntax for lambda in other C-like languages. This is from Functional Java: http://functionaljava.org/examples#Array.filter In Functional Java you can write this D syntax: (int i, int j) { return i % 3 == j; } as: { int i, int j => i % 3 == j }That syntax, and a few of the below, show the one major gripe I have with ultra-compact lambdas: it's hard to *quickly* spot the args/code transition.
Feb 04 2009
BCS wrote:Why use this: "func(someInt) { |a,b| return a+b; };" when you can reuse syntax and get this for the same amount of typeing "func(someInt) (a,b){ return a+b; };"While I know the compiler could (should) know the difference easily enough, my eyes want to parse that as a chained call followed bizarrely by a naked block, rather than a block. That said, I've always found blocks to be one of Ruby's niftiest features (I do a fair bit of Ruby hackage on the side), and would love to see something like it in D2. -- Chris Nicholson-Sauls
Feb 05 2009
Reply to Yigal,Personally I prefer to have syntax for "blocks" like Ruby/smalltalk. given the following example function: int func(int a, delegate int(int) dg) { .. } // call func with [something in this spirit is my favorite]: func(someInt) { | int a, int b | return a+b; };how about require that the block arg in the called function name the argsint func(int a, delegate int(int val, int thing) dg) { .. }and then pull in those names implicitlyfunc(someInt) { return val+thing; };This would have implication in overloading and what not but it would be syntactically clean.
Feb 05 2009
BCS wrote:Reply to Yigal,Ew, no. Aside from the technical issues, this distances the names from the use thereof (i.e. they'd likely be in separate files)Personally I prefer to have syntax for "blocks" like Ruby/smalltalk. given the following example function: int func(int a, delegate int(int) dg) { .. } // call func with [something in this spirit is my favorite]: func(someInt) { | int a, int b | return a+b; };how about require that the block arg in the called function name the argsint func(int a, delegate int(int val, int thing) dg) { .. }and then pull in those names implicitlyfunc(someInt) { return val+thing; };This would have implication in overloading and what not but it would be syntactically clean.
Feb 05 2009
Robert Fraser wrote:BCS wrote:While I fundamentally agree, it could also be nice to /allow/ the names in the decleration, as they may be useful for documentation. -- Chris Nicholson-SaulsReply to Yigal,Ew, no. Aside from the technical issues, this distances the names from the use thereof (i.e. they'd likely be in separate files)Personally I prefer to have syntax for "blocks" like Ruby/smalltalk. given the following example function: int func(int a, delegate int(int) dg) { .. } // call func with [something in this spirit is my favorite]: func(someInt) { | int a, int b | return a+b; };how about require that the block arg in the called function name the argsint func(int a, delegate int(int val, int thing) dg) { .. }and then pull in those names implicitlyfunc(someInt) { return val+thing; };This would have implication in overloading and what not but it would be syntactically clean.
Feb 05 2009
In D (with dlibs) it is: auto a = [97, 44, 67, 3, 22, 90, 1, 77, 98, 1078, 6, 64, 6, 79, 42]; auto b = a.filter((int i){return !(i % 2);}); In Python: a = [97, 44, 67, 3, 22, 90, 1, 77, 98, 1078, 6, 64, 6, 79, 42] b = [x for x in a if not(i % 2)]In Scala : val a = List(97, 44, 67, 3, 22, 90, 1, 77, 98, 1078, 6, 64, 6, 79, 42) val b = a filter (_ % 2 == 0) or val b = a filter (e => e % 2 == 0) or val b = a filter (e : Int => e % 2 == 0) or val b = for (e <- a if (e % 2 == 0)) yield e The first notation "_ % 2 == 0" has no boilerplate and Scala is statically typed (unlike Python). Cheers, Sylvain
Feb 04 2009
hsyl20:In Scala : The first notation "_ % 2 == 0" has no boilerplate and Scala is statically typed (unlike Python).There's a subtle line between "no boilerplate" and "magic (variables)", and the Python syntax is less magic there. So thanks but no thanks. I like the type system of Scala, but not every other thing it currently contains. And if you want static typing take a look at ShedSkin, or RPython. Bye, bearophile
Feb 04 2009
"hsyl20" <hsyl20 yahoo.fr> wrote in message news:gmd862$1741$1 digitalmars.com...I like that very much, especially since you can use either the implicit _ or a manually named var. Although I would prefer something like "a", "b", etc, (or maybe "_1", "_2",. etc) instead of "_", because "_" doesn't seem to lend itself well to multi-arg lambdas, for instance, with reduce(). I don't like *needing* to name a var when it's something trivial like in the above examples.In D (with dlibs) it is: auto a = [97, 44, 67, 3, 22, 90, 1, 77, 98, 1078, 6, 64, 6, 79, 42]; auto b = a.filter((int i){return !(i % 2);}); In Python: a = [97, 44, 67, 3, 22, 90, 1, 77, 98, 1078, 6, 64, 6, 79, 42] b = [x for x in a if not(i % 2)]In Scala : val a = List(97, 44, 67, 3, 22, 90, 1, 77, 98, 1078, 6, 64, 6, 79, 42) val b = a filter (_ % 2 == 0) or val b = a filter (e => e % 2 == 0) or val b = a filter (e : Int => e % 2 == 0) or val b = for (e <- a if (e % 2 == 0)) yield e The first notation "_ % 2 == 0" has no boilerplate and Scala is statically typed (unlike Python).
Feb 04 2009
Nick Sabalausky Wrote:You can use several "_", for instance: scala> val a = List(10,5,2,48,75,84,96,85,3,21,52) a: List[Int] = List(10, 5, 2, 48, 75, 84, 96, 85, 3, 21, 52) scala> val b = a reduceLeft (_ + _) b: Int = 481 The only problem is if you want to change arg order. In this case you have to use named parameters. scala> val b = a reduceLeft (_ - _) b: Int = -461 scala> val b = a reduceLeft ((a,b) => b - a) b: Int = -5 Cheers SylvainThe first notation "_ % 2 == 0" has no boilerplate and Scala is statically typed (unlike Python).I like that very much, especially since you can use either the implicit _ or a manually named var. Although I would prefer something like "a", "b", etc, (or maybe "_1", "_2",. etc) instead of "_", because "_" doesn't seem to lend itself well to multi-arg lambdas, for instance, with reduce(). I don't like *needing* to name a var when it's something trivial like in the above examples.
Feb 04 2009
hsyl20 wrote:Nick Sabalausky Wrote:this seems counter-intuitive to me. Nemerle uses this syntax for currying which seems to me a much better meaning to this syntax. for example ( using D like syntax): int func (string a, char b, int c) { ... } auto a = func( "hello", _, 8); the above is syntax sugar for: auto a = int(char b) { return func("hello", b, 8); };You can use several "_", for instance: scala> val a = List(10,5,2,48,75,84,96,85,3,21,52) a: List[Int] = List(10, 5, 2, 48, 75, 84, 96, 85, 3, 21, 52) scala> val b = a reduceLeft (_ + _) b: Int = 481 The only problem is if you want to change arg order. In this case you have to use named parameters. scala> val b = a reduceLeft (_ - _) b: Int = -461 scala> val b = a reduceLeft ((a,b) => b - a) b: Int = -5 Cheers SylvainThe first notation "_ % 2 == 0" has no boilerplate and Scala is statically typed (unlike Python).I like that very much, especially since you can use either the implicit _ or a manually named var. Although I would prefer something like "a", "b", etc, (or maybe "_1", "_2",. etc) instead of "_", because "_" doesn't seem to lend itself well to multi-arg lambdas, for instance, with reduce(). I don't like *needing* to name a var when it's something trivial like in the above examples.
Feb 05 2009
bearophile Wrote:supports the following syntaxes: To define a delegate o delegate closure: Func<int> foo = i => { return i % 3 == 1; }; Func<int> foo = i => i % 3 == 1; Func<int> bar = () => 2; But this isn't allowed: Func<void> bar = () => 2;knows his job. Let's face it: delegate literals suck a little, mixins as delegates suck a lot, the former is too verbose, the latter just sucks.
Feb 05 2009
On Thu, 05 Feb 2009 12:32:15 +0300, Kagamin <spam here.lot> wrote:bearophile Wrote:syntax). I believe D delegate syntax is superior due to its natural and unambiguous syntax. But yes, it could be made shorter by improving type deduction: int delegate(int) inc = (i) { i + 1; } Which would be the same as int delegate(int) inc = (int i) { return i + 1; } where i's type is deduced from inc's type and the only expression (i + 1) made a return value: auto x = inc(5); // yields 6 Here is an another example: void foo(void delegate(ref int i) inc); Could be used as follows: foo( (i) { ++i; } ); as opposed to foo( (ref int i) { ++i; } ); I can put this enhancement request into bugzilla if anyone likes it.To define a delegate o delegate closure: Func<int> foo = i => { return i % 3 == 1; }; Func<int> foo = i => i % 3 == 1; Func<int> bar = () => 2; But this isn't allowed: Func<void> bar = () => 2;Anders knows his job. Let's face it: delegate literals suck a little, mixins as delegates suck a lot, the former is too verbose, the latter just sucks.
Feb 05 2009
Denis Koroskin wrote:On Thu, 05 Feb 2009 12:32:15 +0300, Kagamin <spam here.lot> wrote:What if you wanted to just execute one expression and return void? This is relevant when e.g. large objects are involved that shouldn't be copied unwittingly.bearophile Wrote:lambda syntax). I believe D delegate syntax is superior due to its natural and unambiguous syntax. But yes, it could be made shorter by improving type deduction: int delegate(int) inc = (i) { i + 1; } Which would be the same as int delegate(int) inc = (int i) { return i + 1; }To define a delegate o delegate closure: Func<int> foo = i => { return i % 3 == 1; }; Func<int> foo = i => i % 3 == 1; Func<int> bar = () => 2; But this isn't allowed: Func<void> bar = () => 2;C-compatible. Anders knows his job. Let's face it: delegate literals suck a little, mixins as delegates suck a lot, the former is too verbose, the latter just sucks.where i's type is deduced from inc's type and the only expression (i + 1) made a return value: auto x = inc(5); // yields 6 Here is an another example: void foo(void delegate(ref int i) inc); Could be used as follows: foo( (i) { ++i; } ); as opposed to foo( (ref int i) { ++i; } );Aha! So here you are using a void-returning function. Now what if there was another overload of foo in place: void foo(int delegate(ref int i) inc); Which foo is to be called? The one that infers a return type of int or the one that assumes the code just returns void?I can put this enhancement request into bugzilla if anyone likes it.It would be great to add the parameter type deduction stuff; that is already talked about and doesn't seem to have many issues. It does have one, which I'm sure people here will see rather quickly. Andrei
Feb 05 2009
On Thu, 05 Feb 2009 17:25:38 +0300, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Denis Koroskin wrote:No problem: void delegate(int) inc = (i) { i + 1; }; which would be transformed into void delegate(int) inc = (int i) { i + 1; }; or void delegate(int) inc = (int i) { return i + 1; }; Both are valid D code according to specs[1]. The second one doesn't compile as of now, but this is a DMD bug, I assume.On Thu, 05 Feb 2009 12:32:15 +0300, Kagamin <spam here.lot> wrote:What if you wanted to just execute one expression and return void? This is relevant when e.g. large objects are involved that shouldn't be copied unwittingly.bearophile Wrote:lambda syntax). I believe D delegate syntax is superior due to its natural and unambiguous syntax. But yes, it could be made shorter by improving type deduction: int delegate(int) inc = (i) { i + 1; } Which would be the same as int delegate(int) inc = (int i) { return i + 1; }To define a delegate o delegate closure: Func<int> foo = i => { return i % 3 == 1; }; Func<int> foo = i => i % 3 == 1; Func<int> bar = () => 2; But this isn't allowed: Func<void> bar = () => 2;C-compatible. Anders knows his job. Let's face it: delegate literals suck a little, mixins as delegates suck a lot, the former is too verbose, the latter just sucks.1) Compiler can flag an ambiguity error at compile time so that user resolve it: foo((i){ ++i; }); // error foo((i){ ++i; return;}); // unambiguous foo((i){ return ++i;}); // unambiguous 2) (The one I prefer) Make (i) { ++i; } return int. The following could be used to force void return type: foo((i){ ++i;; }); // note the double semicolon. It returns void for two reasons: a) second ; evaluates to void b) it is not a single-statement delegate anymore. Implicit return should only be allowed for single statement delegates that are very frequently used (mostly as a predicate) and almost never return void. I doubt it will lead to errors. The very example is rather artificial.where i's type is deduced from inc's type and the only expression (i + 1) made a return value: auto x = inc(5); // yields 6 Here is an another example: void foo(void delegate(ref int i) inc); Could be used as follows: foo( (i) { ++i; } ); as opposed to foo( (ref int i) { ++i; } );Aha! So here you are using a void-returning function. Now what if there was another overload of foo in place: void foo(int delegate(ref int i) inc); Which foo is to be called? The one that infers a return type of int or the one that assumes the code just returns void?--- [1]statement.html: ReturnStatement: return; return Expression; Expression is allowed even if the function specifies a void return type. The Expression will be evaluated, but nothing will be returned.I can put this enhancement request into bugzilla if anyone likes it.It would be great to add the parameter type deduction stuff; that is already talked about and doesn't seem to have many issues. It does have one, which I'm sure people here will see rather quickly. Andrei
Feb 05 2009
Denis Koroskin Wrote:Could be used as follows: foo( (i) { ++i; } );Holy shi- Now feel some real power, Luke. :) foo( i => ++i );foo((i){ ++i; }); // error foo((i){ ++i; return;}); // unambiguous foo((i){ return ++i;}); // unambiguous
Feb 09 2009
On Mon, 09 Feb 2009 13:24:46 +0300, Kagamin <spam here.lot> wrote:Denis Koroskin Wrote:That was just an example. Those short lambdas are often used as predicates. Compare: findAll(array, (i) { i > 3; }); findAll(array, (int i) { return i > 3; });Could be used as follows: foo( (i) { ++i; } );Holy shi- Now feel some real power, Luke. :) foo( i => ++i );foo((i){ ++i; }); // error foo((i){ ++i; return;}); // unambiguous foo((i){ return ++i;}); // unambiguous
Feb 09 2009
Denis Koroskin Wrote:That was just an example. Those short lambdas are often used as predicates. Compare: findAll(array, (i) { i > 3; }); findAll(array, (int i) { return i > 3; });well... you pwnd me :)
Feb 09 2009
Denis Koroskin Wrote:array.filter((x){x>3}) array.filter(x => x>3) array.map(dep => dep.director) convertion, so operations working with such convertions look rather natural and expressive.That was just an example. Those short lambdas are often used as predicates. Compare: findAll(array, (i) { i > 3; }); findAll(array, (int i) { return i > 3; });Could be used as follows: foo( (i) { ++i; } );Holy shi- Now feel some real power, Luke. :) foo( i => ++i );foo((i){ ++i; }); // error foo((i){ ++i; return;}); // unambiguous foo((i){ return ++i;}); // unambiguous
Feb 19 2009
Kagamin wrote:bearophile Wrote:What I see above is a smörgåsbord of syntaxes that shoot all over the proverbial barn door in the hope that one of them would strike someone's fancy. That strikes me as a rather lousily done job. Also, it is my power of templates and generative programming.supports the following syntaxes: To define a delegate o delegate closure: Func<int> foo = i => { return i % 3 == 1; }; Func<int> foo = i => i % 3 == 1; Func<int> bar = () => 2; But this isn't allowed: Func<void> bar = () => 2;knows his job.Let's face it: delegate literals suck a little, mixins as delegates suck a lot, the former is too verbose, the latter just sucks.The logic doesn't quite ring, but passons :o). For what it's worth Walter has got positive feedback left and right from his talk discussing the matter. A simplification in defining function literals is being discussed (omitting the type from the parameters) that would simplify template definitions considerably. Beyond that, I don't feel that changes like moving the parameters on one side or the other of "{" would be Earth-shattering. Andrei
Feb 05 2009
Andrei Alexandrescu>Beyond that, I don't feel that changes like moving the parameters on one side or the other of "{" would be Earth-shattering.< As you have seen there are several possible syntaxes for anonymous functions/delegates/closures. And the current syntax already works, so I think none of such changes can be Earth-shattering. On the other hand, extensive usage of lambdas with my dlibs has shown me that having an uncluttered and un-noisy syntax is quite important if you want to use such functional style a lot, because otherwise noise builds up quickly and in production code you are forced to split things in several lines, otherwise no one can read and debug the code you write. Regarding such noise I can show you an almost extreme example, this is an easy programming task: http://projecteuler.net/index.php?section=problems&id=4Find the largest palindrome made from the product of two 3-digit numbers<With Python:906609 D1 with my dlibs: import d.all; void main() { putr( max(select(i*j, i, xrange(100,1000), j, xrange(100,1000), str(i*j) == str(i*j).reverse)) ); } Notice in this case Python is clearly better, not just because it's more readable, but also because that select() generates items eagerly, while the Python oneliner contains a lazy generator expression. dlibs contain xmap too, but that code is so much more noisy that I don't want to show it :-) I know this isn't an example of code that's normal in production, but sometimes you need extreme example to show your point :-) Now, back to the topic: putting arguments into a single () or {} instead of a isntead of two, this helps the human parsing of the code, improving visual chunking and reducing noise. Bye, bearophilemax(i*j for i in xrange(100,1000) for j in xrange(100,1000) if str(i*j) == str(i*j)[::-1])
Feb 05 2009
bearophile Wrote:Now, back to the topic: putting arguments into a single () or {} instead of a isntead of two, this helps the human parsing of the code, improving visual chunking and reducing noise.I also believe that, for readability reasons, lambdas should have some distinct distinct =>. I like the Haskell syntax that uses a backslash, which looks very much like lambda. Here's an example of such syntax: auto r = find!( \(a) { return a.Weight > 100; })(range); It goes without saying that any decent D editor would display the backslash as a Greek lambda.
Feb 09 2009
On Mon, Feb 9, 2009 at 3:19 AM, Bartosz Milewski <bartosz relisoft.com> wro= te:bearophile Wrote:ual object isntead of two, this helps the human parsing of the code, improv= ing visual chunking and reducing noise.Now, back to the topic: putting arguments into a single () or {} instead=I also believe that, for readability reasons, lambdas should have some di=has the distinct =3D>. I like the Haskell syntax that uses a backslash, whi= ch looks very much like lambda. Here's an example of such syntax:auto r =3D find!( \(a) { return a.Weight > 100; })(range);Far too noisy. auto r =3D find!(\a -> a.Weight > 100)(range); Of course I _may_ be a bit biased in this regard, considering this is the syntax MiniD uses ;) And of course, for multi-statement lambdas: something(\a, b { stmt1; stmt2; });
Feb 09 2009
Jarrett Billingsley:auto r = find!(\a -> a.Weight > 100)(range); [...] something(\a, b { stmt1; stmt2; });This looks better to me (but I don't know if this is the best syntax, it's just an idea): // syntax for lambda that contains a single expression, implicit return (this is the most common case): auto r = find!(a => a.Weight > 100)(range); // syntax for lambda that contains one or more statements, no return, side effects only: something({ a, b :: stmt1; stmt2; }); // syntax for lambda that contains one or more statements, with side effects and return: something({ a, b :: stmt1; return foo(); }); Bye, bearophile
Feb 09 2009
// syntax for lambda that contains a single expression, implicit return (this is the most common case): auto r = find!(a => a.Weight > 100)(range);I really like this one, but I'd prefer something likeauto r = find(range, {a -> a.Weight > 100});Note the -> instead of the =>, to avoid any ambiguities with the comparison operator.
Feb 09 2009
grauzone Wrote:I really like this one, but I'd prefer something like > auto r = find(range, {a -> a.Weight > 100}); Note the -> instead of the =>, to avoid any ambiguities with the comparison operator.Let's play more; then what do you think about (all the following are legal): auto r1 = range.find({ x -> x.weight > 100 }); auto r2 = range.find({ x :: return x.weight > 100; }); auto r3 = range.find({ x :: stmt1(x); stmt2; }); auto r4 = range.find({ x, y :: stmt1; return foo(y); }); I like those enough, they seem balanced, uniform, not too much error-prone, they have only one visual chunk, short enough and easy to write :-) Note that this syntax: auto r1 = range.find({ x -> x.weight > 100 }); using my dlibs is equivalent to the following: auto r1 = range.find((ArrayType1!(typeof(range)) x) { return x.weight > 100; }); Bye, bearophile
Feb 09 2009
bearophile:auto r1 = range.find((ArrayType1!(typeof(range)) x) { return x.weight > 100; });Better: auto r1 = range.find((BaseType1!(typeof(range)) x) { return x.weight > 100; }); Of course, you have to specify range twice there, and that's not good. Bye, bearophile
Feb 09 2009
bearophile wrote:grauzone Wrote:Agreed. Especially I like that "normal" and "functional" uses have distinct syntax. This is much better than the proposal, to allow omission of the return statement, and to return last value of the last expression statement instead (like in (x){if(x>0) x+=1; x;}).I really like this one, but I'd prefer something like > auto r = find(range, {a -> a.Weight > 100}); Note the -> instead of the =>, to avoid any ambiguities with the comparison operator.Let's play more; then what do you think about (all the following are legal): auto r1 = range.find({ x -> x.weight > 100 }); auto r2 = range.find({ x :: return x.weight > 100; }); auto r3 = range.find({ x :: stmt1(x); stmt2; }); auto r4 = range.find({ x, y :: stmt1; return foo(y); }); I like those enough, they seem balanced, uniform, not too much error-prone, they have only one visual chunk, short enough and easy to write :-)Note that this syntax: auto r1 = range.find({ x -> x.weight > 100 }); using my dlibs is equivalent to the following: auto r1 = range.find((ArrayType1!(typeof(range)) x) { return x.weight > 100; }); Bye, bearophile
Feb 09 2009
"grauzone" <none example.net> wrote in message news:gmpgod$fej$1 digitalmars.com...bearophile wrote:I'd rather have everything use "::" (consistent), and then say that the right-hand side of :: can be either A: one or more statements ("normal") or B: an expression ("functional").Let's play more; then what do you think about (all the following are legal): auto r1 = range.find({ x -> x.weight > 100 }); auto r2 = range.find({ x :: return x.weight > 100; }); auto r3 = range.find({ x :: stmt1(x); stmt2; }); auto r4 = range.find({ x, y :: stmt1; return foo(y); }); I like those enough, they seem balanced, uniform, not too much error-prone, they have only one visual chunk, short enough and easy to write :-)Agreed. Especially I like that "normal" and "functional" uses have distinct syntax. This is much better than the proposal, to allow omission of the return statement, and to return last value of the last expression statement instead (like in (x){if(x>0) x+=1; x;}).
Feb 09 2009
What I see above is a smörgåsbord of syntaxes that shoot all over the proverbial barn door in the hope that one of them would strike someone's fancy. That strikes me as a rather lousily done job. Also, it is myI find this statement rather ironic, because you also seem to be quite happy with your code-as-string-literal approach. Your approach doesn't even enforce any syntax, instead, everyone is free to invent his own.
Feb 05 2009
grauzone wrote:I do understand you dislike strings as lambdas, but please do not use that dislike as a presupposition of a truth. Besides, there is no correlation. D offers two syntaxes, a decent lambda syntax (that is being improved) and a string syntax for short predicates. They have clear and distinct tradeoffs and charters. In store.What I see above is a smörgåsbord of syntaxes that shoot all over the proverbial barn door in the hope that one of them would strike someone's fancy. That strikes me as a rather lousily done job. Also, it is myI find this statement rather ironic, because you also seem to be quite happy with your code-as-string-literal approach.Your approach doesn't even enforce any syntax, instead, everyone is free to invent his own.There's only so many ways to write an expression involving one or two given symbols. Andrei
Feb 05 2009
Reply to Andrei,Kagamin wrote: Also, missed the power of templates and generative programming.I have never met the man, but it is my impression that Anders didn't miss the power, he just doesn't care for the paradigm. I would speculate that because there is nothing that it adds that can't be done at runtime (ignoring as you can" approach across the board.
Feb 05 2009
Kagamin wrote:knows his job. Let's face it: delegate literals suck a little, mixins as delegates suck a lot, the former is too verbose, the latter just sucks.D: void foo(void delegate(int) dg); delegate void SomeName(int i); void foo(SomeName dg); not for using them.
Feb 05 2009
"Christopher Wright" <dhasenan gmail.com> wrote in message news:gmfsqa$311e$1 digitalmars.com...Kagamin wrote:function-pointers in C), and that oddity actually made it harder for me to really wrap my head around them. Once I did though, I came around to D and delegates better. My only issue with D's delegate-declaration syntax is the semi-messy ordering of "return type, delegate keyword, paramaters, name". Something closer to following would seem much more intuitive to me: void foo(delegate void(int) dg); //or void foo(void dg(int)); //or void foo(delegate(void <- int) dg); //etc... Although, I realize the current way is done to be consistent with function definitions. But, as I mentioned in another branch of the thread, I wouldn't mind function definitions like this: func foo(int <- int x) {return x+1;} //or func foo {(int <- int x) return x+1;} //or func foo {int <- int x :: return x+1;}Anders knows his job. Let's face it: delegate literals suck a little, mixins as delegates suck a lot, the former is too verbose, the latter just sucks.D: void foo(void delegate(int) dg); delegate void SomeName(int i); void foo(SomeName dg); not for using them.
Feb 05 2009
Christopher Wright wrote:delegate void SomeName(int i); void foo(SomeName dg);Ugh, don't remind me!
Feb 05 2009
"_" is used for currying in Scala too. scala> def func (a:Int)(b:String) = {} func: (Int)(String)Unit Unit is the same thing as void in Scala. scala> func (5) _ res7: (String) => Unit = <function> scala> func (_:Int) ("blah") res15: (Int) => Unit = <function> scala> func (_) ("blah") <console>:6: error: missing parameter type for expanded function ((x$1) => func(x$1)("blah")) func (_) ("blah") (I don't know why I have to specify "Int" type. Maybe it has been corrected in the last versions.) Cheers, SylvainYou can use several "_", for instance: scala> val a = List(10,5,2,48,75,84,96,85,3,21,52) a: List[Int] = List(10, 5, 2, 48, 75, 84, 96, 85, 3, 21, 52) scala> val b = a reduceLeft (_ + _) b: Int = 481 The only problem is if you want to change arg order. In this case you have to use named parameters. scala> val b = a reduceLeft (_ - _) b: Int = -461 scala> val b = a reduceLeft ((a,b) => b - a) b: Int = -5 Cheers Sylvainthis seems counter-intuitive to me. Nemerle uses this syntax for currying which seems to me a much better meaning to this syntax. for example ( using D like syntax): int func (string a, char b, int c) { ... } auto a = func( "hello", _, 8); the above is syntax sugar for: auto a = int(char b) { return func("hello", b, 8); };
Feb 06 2009
Christopher Wright Wrote:D: void foo(void delegate(int) dg); delegate void SomeName(int i); void foo(SomeName dg); not for using them.http://msdn.microsoft.com/en-us/library/bb534303.aspx http://msdn.microsoft.com/en-us/library/bb534803.aspx
Feb 09 2009
Kagamin wrote:Christopher Wright Wrote:Eugh! Just eugh!D: void foo(void delegate(int) dg); delegate void SomeName(int i); void foo(SomeName dg); not for using them.http://msdn.microsoft.com/en-us/library/bb534303.aspx http://msdn.microsoft.com/en-us/library/bb534803.aspx
Feb 09 2009
grauzone Wrote:auto r = find(range, {a -> a.Weight <- 100}); :)// syntax for lambda that contains a single expression, implicit return (this is the most common case): auto r = find!(a => a.Weight > 100)(range);I really like this one, but I'd prefer something like > auto r = find(range, {a -> a.Weight > 100}); Note the -> instead of the =>, to avoid any ambiguities with the comparison operator.
Feb 10 2009
Kagamin:auto r = find(range, {a -> a.Weight <- 100});Take a look at how the Fortress language manages spaces inside expressions. It can find a syntax error there, because the spacing is misleading. Bye, bearophile
Feb 10 2009
bearophile Wrote:Kagamin:There is no error here, since there's no <- operator, the construct is unabiguous, it just looks weird.auto r = find(range, {a -> a.Weight <- 100});Take a look at how the Fortress language manages spaces inside expressions. It can find a syntax error there, because the spacing is misleading.
Feb 10 2009
Kagamin Wrote:well, every construct can look weird in some environment.There is no error here, since there's no <- operator, the construct is unabiguous, it just looks weird.auto r = find(range, {a -> a.Weight <- 100});Take a look at how the Fortress language manages spaces inside expressions. It can find a syntax error there, because the spacing is misleading.
Feb 10 2009
Kagamin:There is no error here, since there's no <- operator, the construct is unabiguous, it just looks weird.In Fortress the syntax of this expression is OK: x + 2 * 3 x + 2*3 This is a syntax error, because the spaces are misleading: x+2 * 3 Bye, bearophile
Feb 10 2009