digitalmars.D - Lambda syntax, etc
- bearophile <bearophileHUGS lycos.com> Feb 04 2009
- BCS <none anon.com> Feb 04 2009
- Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> Feb 04 2009
- "Nick Sabalausky" <a a.a> Feb 04 2009
- Yigal Chripun <yigal100 gmail.com> Feb 04 2009
- "Nick Sabalausky" <a a.a> Feb 04 2009
- BCS <ao pathlink.com> Feb 04 2009
- Yigal Chripun <yigal100 gmail.com> Feb 04 2009
- Chris Nicholson-Sauls <ibisbasenji gmail.com> Feb 05 2009
- Bill Baxter <wbaxter gmail.com> Feb 04 2009
- BCS <ao pathlink.com> Feb 04 2009
- "Nick Sabalausky" <a a.a> Feb 04 2009
- "Nick Sabalausky" <a a.a> Feb 04 2009
- BCS <none anon.com> Feb 04 2009
- "Nick Sabalausky" <a a.a> Feb 04 2009
- BCS <ao pathlink.com> Feb 05 2009
- Bill Baxter <wbaxter gmail.com> Feb 04 2009
- Bill Baxter <wbaxter gmail.com> Feb 04 2009
- "Nick Sabalausky" <a a.a> Feb 04 2009
- Bill Baxter <wbaxter gmail.com> Feb 04 2009
- Jarrett Billingsley <jarrett.billingsley gmail.com> Feb 04 2009
- BCS <ao pathlink.com> Feb 05 2009
- Robert Fraser <fraserofthenight gmail.com> Feb 05 2009
- Chris Nicholson-Sauls <ibisbasenji gmail.com> Feb 05 2009
- hsyl20 <hsyl20 yahoo.fr> Feb 04 2009
- bearophile <bearophileHUGS lycos.com> Feb 04 2009
- "Nick Sabalausky" <a a.a> Feb 04 2009
- hsyl20 <hsyl20 yahoo.fr> Feb 04 2009
- Yigal Chripun <yigal100 gmail.com> Feb 05 2009
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)] C#2 has lambdas, and C#3 adds closures and more type inferencing, so C#3+ supports the following syntaxes: (int i) => { return i % 3 == 1; } // C#2 i => i % 3 == 1 // C#3 i => { return i % 3 == 1; } // C#3, with statements too 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; Few comments I have copied relative to C#3:C# it automatically generates either an anonymous class or an anonymous method 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. [...]i => i % 3 == 1 // C#3 i => { return i % 3 == 1; } // C#3, with statements too 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,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.
Strings are immune from the problem. :o) Also they make for readily recognizable code because they all use the same argument names. Andrei
Feb 04 2009
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message news:gmclr4$2q30$1 digitalmars.com...BCS wrote: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.
Strings are immune from the problem. :o) Also they make for readily recognizable code because they all use the same argument names. Andrei
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)")(); }
Feb 04 2009
Andrei Alexandrescu wrote:BCS wrote: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.
Strings are immune from the problem. :o) Also they make for readily recognizable code because they all use the same argument names. Andrei
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.
Feb 04 2009
"Yigal Chripun" <yigal100 gmail.com> wrote in message news:gmd0u8$fg7$1 digitalmars.com...Andrei Alexandrescu wrote:BCS wrote: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.
Strings are immune from the problem. :o) Also they make for readily recognizable code because they all use the same argument names. Andrei
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.
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; };" ) ).
Feb 04 2009
Reply to Nick,"Yigal Chripun" <yigal100 gmail.com> wrote in message news:gmd0u8$fg7$1 digitalmars.com...Andrei Alexandrescu wrote:BCS wrote: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 }
have with ultra-compact lambdas: it's hard to *quickly* spot the args/code transition.
recognizable code because they all use the same argument names. Andrei
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.
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: ) ).
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; };"
Feb 04 2009
Bill Baxter wrote:On Thu, Feb 5, 2009 at 7:26 AM, BCS<ao pathlink.com> wrote:Reply to Nick,"Yigal Chripun"<yigal100 gmail.com> wrote in message news:gmd0u8$fg7$1 digitalmars.com...Andrei Alexandrescu wrote:BCS wrote: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 }
have with ultra-compact lambdas: it's hard to *quickly* spot the args/code transition.
recognizable code because they all use the same argument names. Andrei
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.
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; };" when you can reuse syntax and get this for the same amount of typeing "func(someInt) (a,b){ return a+b; };"
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
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.
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
On Thu, Feb 5, 2009 at 7:26 AM, BCS <ao pathlink.com> wrote:Reply to Nick,"Yigal Chripun" <yigal100 gmail.com> wrote in message news:gmd0u8$fg7$1 digitalmars.com...Andrei Alexandrescu wrote:BCS wrote: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.
recognizable code because they all use the same argument names. Andrei
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.
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: ) ).
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; };"
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
Feb 04 2009
Reply to Bill,I was about to say the same thing, but I think Yigal was just mixing
1) the trailing delegates proposal (aka ruby block) and
I like that2) A ruby-like syntax for delegate literals : {|a,b| return a+b;}
I don't like that One #1 I'd be inclined to requier that the function be defined likevoid 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,I was about to say the same thing, but I think Yigal was just mixing
1) the trailing delegates proposal (aka ruby block) and
I like that
Then we're agreed on that part :)2) A ruby-like syntax for delegate literals : {|a,b| return a+b;}
I don't like that
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). 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.One #1 I'd be inclined to requier that the function be defined likevoid DoIt(int delegate(int) dg...)
D laready has this syntax for Typesafe Variadic Functions http://www.digitalmars.com/d/1.0/function.html
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."?
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
Hello Nick,One #1 I'd be inclined to requier that the function be defined likevoid DoIt(int delegate(int) dg...)
http://www.digitalmars.com/d/1.0/function.html
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."?
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)
Feb 04 2009
"BCS" <none anon.com> wrote in message news:a6268ff24108cb552c70a0af6c news.digitalmars.com...Hello Nick,One #1 I'd be inclined to requier that the function be defined likevoid DoIt(int delegate(int) dg...)
http://www.digitalmars.com/d/1.0/function.html
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."?
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 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?).
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
On Thu, Feb 5, 2009 at 2:30 PM, Nick Sabalausky <a a.a> wrote:2) A ruby-like syntax for delegate literals : {|a,b| return a+b;}
I don't like that
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).
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; }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; }
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:2) A ruby-like syntax for delegate literals : {|a,b| return a+b;}
I don't like that
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).
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; }
Oh, and last semicolon of a function should be optional :-) { int x; int y :: return x+y } --bb
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:On Thu, Feb 5, 2009 at 2:30 PM, Nick Sabalausky <a a.a> wrote:2) A ruby-like syntax for delegate literals : {|a,b| return a+b;}
I don't like that
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).
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; }
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.K&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:K&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.)
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. --bb
Feb 04 2009
On Thu, Feb 5, 2009 at 1:20 AM, Nick Sabalausky <a a.a> wrote: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 ;)
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.
Feb 04 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,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.
Ew, no. Aside from the technical issues, this distances the names from the use thereof (i.e. they'd likely be in separate files)
Feb 05 2009
Robert Fraser wrote:BCS wrote: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.
Ew, no. Aside from the technical issues, this distances the names from the use thereof (i.e. they'd likely be in separate files)
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-Sauls
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...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).
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
Nick Sabalausky Wrote:The 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.
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 Sylvain
Feb 04 2009
hsyl20 wrote:Nick Sabalausky Wrote:The first notation "_ % 2 == 0" has no boilerplate and Scala is statically typed (unlike Python).
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.
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 Sylvain
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); };
Feb 05 2009









"Nick Sabalausky" <a a.a> 