Consider
v.FindAll(x => x > 5)
We could use an implicit parameter in order to supress the parameter list. So we need a keyword to refer to the undeclared parameter, for instance "it" or "_1". The previous code would be equivalent to:
v.FindAll( => it > 5)
or mayby:
v.FindAll( it > 5)
For an unnamed second parameter we could use it2 or _2 etc.
Is there any problem with this new simplification

Implicit parameters in lambda expressions
Michael Patrick
MartinNorfolk
Potentially
In general, I think "=> expr" would have an ambiguity with lambdas that take void. If it were limited to extension methods (which by definition always take at least one parameter), it may be possible but that's a fairly narrow field on which to create an alternative syntax.
Perhaps, however, v.FindAll(`this > 5`) would be suitable. I don't know off-hand of any use of the ` character in C#. In this case, I think `expr(this)` syntax would translate to the lambda:
(typeof(this) x) => { return expr(x); }
DieZeL
Well. Do not introduce new keywords; use #1, #2 instead.< xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
So, if any expression contains #1 etc. it is considered a lambda expression and
v.FindAll(#1 > 5)
is considered equivalent to
v.FindAll(anonimous => anonimous > 5)
and
v.F(#1 > #2)
is
v.F( (anon1, anon2) => anon1 > anon2 )
The parser can be unhappy with this new work, so if the parser writer complains we can help him forcing us to write '=>' in front of the "pure lambda expression":
v.FindAll(=> #1 > 5)
This fits well with 0-argument lambdas
v.F( => generateRandomNumber() )
so the "unary => operator" is considered always the start of a pure lambda expression with 0 or more unnamed parameters.
Yes, it's just syntactic sugar but the additions to C#3.0 are all very sweet.
MKU
With some mistakes, a program won't compile. In this case, I think it's worse -- the program will compile but behave incorrectly, and that could be very costly.
Giotto
Given
1: Func<T1, T2, .., T(n-1), R> f -> R f(#1, #2, .., #(n-1))
2: Func<T1, T2, .., T(n), R> f -> R f(#1, #2, .., #(n))
Ambiguity arises with
=> f(#1, #2, .., #(n-1))
Just because a lambda may be able to take n parameters doesn't mean it has to make use of all of them. In such a case, the body of the lambda is indistinguishable from an m-parameter function, where m >= (n-1), including functions which have the same number of parameters, but differ in the types of the unused parameters:
(x, y) => f(x, y) -> g(x, y) { return f(x, y); }
(x, y, z) => f(x, y) -> g(x, y, z) { return f(x, y); }
(x, y, w) => f(x, y) -> g(x, y, w) { return f(x, y); } // differs in type of param 3
=> f(x, y) -> g(x, y) or g(x, y, z) or g(x, y, w)
So if you have a function Foo which is overloaded with cases 1 and 2, and if those overloads happen to do radically different things (one returns the value of f, the other writes the result to every sector on your system drive), you've got a problem.
To save your system drive from an embarassing programming snafu, you would have to disambiguate by providing an indication of the number of parameters to use:
(x1, x2, .., x(n-1)) => f(x1, x2, .., x(n-1)) // case 1
(x1, x2, .., x(n)) => f(x1, x2, .., x(n)) // case 2
.. and perhaps even the types.
Note that the number of arguments accepted by f() is irrelevant: the lambda wraps f() within a different function, and it's that function that we need to determine the type of.
Cory S.
Consider Foo(op(#1, #2)) .. what are the values assigned to #1 and #2
In the specific case of an extension method, we can presume that #1 is the instance of the type being extended. But outside of that case (lambdas are a feature to themselves, independent of Linq) we can't make that determination. For #2, it doesn't matter if it's an extension method or not. There's also the problem of the types involved. #1 is typed implicitly in an extension method, but possibly not in general for either #1 or #2.
Further, consider nested lambdas:
v.Foo(y, #1 + w.Bar(z, #1 > #2)) .. do Bar's #1 and #2 refer to the Bar-scope, or the Foo-scope Disambiguation is needed, and you'll probably end up either resorting back to (params) => expr(params), or just explicitly writing the code as Foo(y, v + Bar(z, w > z)) or Foo(y, v + Bar(z, v > y), or ... you get my meaning.
I see this as being a reasonably common case if lambdas catch on in the way they ought (eg, lambda composition -- something done all the time with the Linq pattern). If the unambiguous cases are that limited, it may not be worth confusing the syntax just to save a couple keystrokes (even if, aesthetically, that one case looks much more pleasing). A better solution would need to be found that avoids these problems.
Rafie
>Foo(op(#1, #2)) .. what are the values assigned to #1 and #2
#1 is not a legal identifier, it's used only in these pure lambda expressions.
The => operator can't be ommited. So:
=> Foo(op(#1, #2)) is always
(anon1, anon2) => Foo(op(anon1, anon2))
and
Foo( => op(#1, #2)) is always:
Foo( (anon1, anon2) => op(anon1, anon2) )
Pure lambdas can't be nested. If you like
x => (y=> Foo(op(x, y)))
you can write
=>(y => Foo(op(#1, y)))
or
x => => Foo(op(x, #1))
Composed lambdas are interesting, of course, but normal lambdas are very used too.
For example
w = BinaryTransform(v1, v2, => #1 * #2);
//w[ i ] = v1[ i ] * v2[ i ] for each i
is very clear and elegant, more than
w = BinaryTransform(v1, v2, (op1, op2) => op1 * op2);
ps0118mj
Misto
Here are a few of the other problems we faced.
The big desire we had for implicitly named parameters was to reduce the syntactic overhead. For example, some of us would have preferred for query operators to be written like this:
customers.Where(Name == "Bob").
In this case, you wouldn't even have had to say the name of the parameter, and the identifier 'Name' would have automatically resolved to something like 'it.Name'. This would have been more familiar to those using SQL today.
And this seemed to work fine (we were able to convince ourselves that the other flaws it introduced were not insurmountable), as long as the query operators where limited to fixed, baked-in syntax. When we decided to open them up to programmer extensions we had to contend with other uses of lambda expressions and conflicts with methods that already took delegates as arguments.
For example, assume you had the following generic delegate defined, one that takes no arguments and returns some type T.
delegate T MyDelegate<T>();
Now also, assume you have the following generic method.
void DoMyThing<T>(MyDelegate<T> md) { ... }
All perfectly naturally, at least in 2.0.
You might be tempted to believe the following code would be easily understood by the compiler.
int x = ...;
int y = ...;
myObject.DoMyThing(x + y);
Assuming we figured out how to determine the overloading for DoMyThing without needing to know the actual type of x + y first (an exteremly difficult thing to begin with) the compiler can then go ahead and assume that 'x + y' is the body of a no-arg lambda function
Not really.. It's easier to see with this example.
int x = ... ;
int y = ... ;
MyDelegate<int> del = delegate { return x + y; }
myObject.DoMyThing(del);
Hmm. Now there is a problem. How should the compiler understand this Should it become a call to DoMyThing<int>(del)
Or is it really a call to DoMyThing<MyDelegate<int>>(del)
You be the judge. The compiler obviously cannot.
We tried to work this one for months on end. In the end, we could not escape needing a syntactic way to distinguish between the lambda case and the ordinary argument case.
So we came up with '=>'. Actually, there were a variety of alternatives to '=>' suggested, used and joked over before we ever settled on it.
Now, you still might think that I've not actually answered the original question. Since, it was suggested that the syntax could have been something similar to customers.Where(=> it.Name == "Bob"), and that certainly would have been syntactic enough.
Okay, you are right. I haven't answered the question, but it was fun to digress anyway.
The real reasons were already pointed out by Keith. However another problem that arises on the ambiguity front is nested lambdas. For example, I might have written this
customers.Where(=> it.Name == "Bob" && Orders.Sum(=> it.Totals * thatotherit.Discount) > 200.00)
Nested lambdas introduce additional implicitly defined names that either make them ambiguous with each other or hide the outer ones making it impossible to ever refer back to them.
Of course, if the implicit parameter syntax was only optional, you could always go back and give your lambda parameters names, but then you'd also have to go back and rewrite all references to them in the expression, which would be error prone. Therefore, best practices would end up suggesting you give lamdba's arguments good names to begin with.
Bistesh
customers.Where(=> #1.Name == "Bob")
is
customers.Where( anon => anon.Name=="Bob")
customers.MyGetMin( (p1, p2) => p1.age < p2.age)
is
customers.MyGetMin( => #1.age < #2.age)
and so on
Could you write a non nested lambda example such a:
-That example be ok with named parameters and implicit types
-That example be wrong with unnamed parameters, using #1 #2... instead
Mayby (x,y)=>2*x
LI Engineer
A pure lambda (or a lambda with implicit parameter names) is:
=> Expression of(#1opt,#2opt,...,#n)
with n>=0, and it's considered equals to
(anon1, anon2, ... anonn) => Expression of(anon1,...,anonn)
So the greatest #i determines the number of arguments.
Nested lambdas can have one pure lambda at most.
(I don't know the ideal precedence of the unary =>)
_________
Given
=> 2 * #1
The only suitable meaning is:
x => 2 * x
and not
(x,y) => 2 * x
The last can't be expressed without names
So these "pure" lambdas can't be used if the last argument doesn't appear in the expression.
Too many restrictions . Mayby, but I think that the porcentage of (untyped) lambdas expressable without names is big yet. (Let's look at real code to confirm or not).
The exceptions are: lambdas that don't use the last parameter and the case of two 'pure' lambdas nested.
If there are more restrictions I resign.
Regards, Keith.
Phillip Shentu
Guaranteed-correct behavior should be the default. It should take an explicit action to solve an ambiguity. I'm increasingly of the opinion that while it looks pretty, it's too dangerous.
MKRaghu
Brad Bass
I'd like to jump over to C# 3.0 to see if there are language features that might be useful in my project. I thought about Lambda expressions in particular, but I haven't started experimenting with it (I haven't even d/l C# 3.0 yet).
But it's interesting how Juan's suggestions seem to come from Mathematica, since it uses the #1, #2... syntax for lambda expressions. Have you guys done a comparative analysis with this software package
Brian