Top lambda Questions

List of Tags
553
StriplingWarrior

When using lambda expressions or anonymous methods in C#, we have to be wary of the access to modified closure pitfall. For example:

foreach (var s in strings)
{
   query = query.Where(i => i.Prop == s); // access to modified closure

Due to the modified closure, the above code will cause all of the Where clauses on the query to be based on the final value of s.

As explained here, this happens because the s variable declared in foreach loop above is translated like this in the compiler:

string s;
while (enumerator.MoveNext())
{
   s = enumerator.Current;
   ...

... instead of like this:

while (enumerator.MoveNext())
{
   string s;
   s = enumerator.Current;

As pointed out here, there are no performance advantages to declaring a variable outside the loop, and under normal circumstances the only reason I can think of for doing this is if you plan to use the variable outside the scope of the loop:

} // end while
var finalString = s;

However, variables defined in a foreach loop cannot be used outside the loop:

foreach(string s in strings)
{
}
var finalString = s; // won't work: you're outside the scope.

So the compiler declares the variable in a way that makes it highly prone to an error that is often difficult to find and debug, while producing no perceivable benefits.

Is there something you can do with foreach loops this way that you couldn't if they were compiled with an inner-scoped variable, or is this just an arbitrary choice that was made before anonymous methods and lambda expressions were available or common, and which hasn't been revised since then?

Answered By: Eric Lippert ( 670)

The compiler declares the variable in a way that makes it highly prone to an error that is often difficult to find and debug, while producing no perceivable benefits.

Your criticism is entirely justified.

I discuss this problem in detail here:

Closing over the loop variable considered harmful

Is there something you can do with foreach loops this way that you couldn't if they were compiled with an inner-scoped variable? or is this just an arbitrary choice that was made before anonymous methods and lambda expressions were available or common, and which hasn't been revised since then?

The latter. The C# 1.0 specification actually did not say whether the loop variable was inside or outside the loop body, as it make no observable difference. When closure semantics were introduced in C# 2.0, the choice was made to put the loop variable outside the loop, consistent with the "for" loop.

I think it is fair to say that all regret that decision. This is one of the worst "gotchas" in C#, and we are going to take the breaking change to fix it. In C# 5 the foreach loop variable will be logically inside the body of the loop, and therefore closures will get a fresh copy every time.

The for loop will not be changed, and the change will not be "back ported" to previous versions of C#. You should therefore continue to be careful when using this idiom.

248
Remus Rusanu

I am looking at the MvcContrib Grid component and I'm fascinated, yet at the same time repulsed, by a syntactic trick used in the Grid syntax:

.Attributes(style => "width:100%")

The syntax above sets the style attribute of the generated HTML to width:100%. Now if you pay attention, 'style' is nowhere specified, is deduced from the name of the parameter in the expression! I had to dig into this and found where the 'magic' happens:

   Hash(params Func<object, TValue>[] hash)
   {
     foreach (var func in hash)
     {
       Add(func.Method.GetParameters()[0].Name, func(null));
     }
   }

So indeed, the code is using the formal, compile time, name of parameters to create the dictionary of attribute name-value pairs. The resulted syntax construct is very expressive indeed, but at the same time very dangerous. The general use of lambda expressions allows for replacement of the names used without side effect. I see an example in a book that says collection.ForEach(book => Fire.Burn(book)) I know I can write in my code collection.ForEach(log => Fire.Burn(log)) and it means the same thing. But with the MvcContrib Grid syntax here all of the sudden I find code that actively looks and makes decissions based on the names I choose for my variables!

So is this common practice with the C# 3.5/4.0 community and the lambda expressions lovers? Or is a rogue one trick maverick I shouldn't worry about?

Answered By: Brian ( 89)

This has poor interop. For example, consider this C# - F# example

C#:

public class Class1
{
    public static void Foo(Func<object, string> f)
    {
        Console.WriteLine(f.Method.GetParameters()[0].Name);
    }
}

F#:

Class1.Foo(fun yadda -> "hello")

Result:

"arg" is printed (not "yadda").

As a result, library designers should either avoid these kinds of 'abuses', or else at least provide a 'standard' overload (e.g. that takes the string name as an extra parameter) if they want to have good interop across .Net languages.

168
SaaS Developer

I'm using C# on Framework 3.5. I'm looking to quickly sort a Generic List<>. For the sake of this example lets say I have a List of a Person type with a property of lastname. How would I sort this List using a lambda expression?

List<Person> people = PopulateList();
people.OrderBy(???? => ?????)
Answered By: Marc Gravell ( 271)

If you mean an in-place sort (i.e. the list is updated):

people.Sort((x, y) => string.Compare(x.LastName, y.LastName));

If you mean a new list:

var newList = people.OrderBy(x=>x.LastName).ToList(); // ToList optional
161
Michiel de Mare

In Ruby 1.8, there are subtle differences between proc/lambda on the one hand, and Proc.new on the other.

  • What are those differences?
  • Can you give guidelines on how to decide which one to choose?
  • In Ruby 1.9, proc and lambda are different. What's the deal?
Answered By: Joey deVilla ( 184)

Another important but subtle difference is in the way procs created with lambda and procs created with Proc.new handle the return statement:

  • In a lambda-created proc, the return statement returns only from the proc itself
  • In a Proc.new-created proc, the return statement is a little more surprising: it returns control not just from the proc, but also from the method enclosing the proc!

Here's lambda-created proc's return in action. It behaves in a way that you probably expect:

def whowouldwin

mylambda = lambda {return "Freddy"}
mylambda.call

# mylambda gets called and returns "Freddy", and execution
# continues on the next line

return "Jason"

end


whowouldwin
=> "Jason"

Now here's a Proc.new-created proc's return doing the same thing. You're about to see one of those cases where Ruby breaks the much-vaunted Principle of Least Surprise:

def whowouldwin2

myproc = Proc.new {return "Freddy"}
myproc.call

# myproc gets called and returns "Freddy",
# but also returns control from whowhouldwin2!
# The line below *never* gets executed.

return "Jason"

end


whowouldwin2
=> "Freddy"

Thanks to this surprising behaviour (as well as less typing), I tend to favour using lambda over Proc.new when making procs.

Could someone explain? I understand the basic concepts behind them but I often see them used interchangeably and I get confused.

And now that we're here, how do they differ from a regular function?

Answered By: Claudiu ( 158)

A lambda is just an anonymous function - a function defined with no name. In some languages, such as Scheme, they are equivalent to named functions. In fact, function definition is re-written as binding a lambda to a variable internally. In other languages, like Python, there are some (rather needless) distinctions between them, but they behave the same way otherwise.

A closure is any function which closes over the environment in which it was defined. This means that it can access variables not in its parameter list. Examples:

def func(): return h
def anotherfunc(h):
   return func()

This will cause an error, because func does not close over the environment in anotherfunc - h is undefined. func only closes over the global environment. This will work:

def anotherfunc(h):
    def func(): return h
    return func()

Because here, func is defined in anotherfunc, and in python 2.3 and greater (or some number like this) when they almost got closures correct (mutation still doesn't work), this means that it closes over anotherfunc's environment and can access variables inside of it. In Python 3.1+, mutation works too when using the nonlocal keyword.

Another important point - func will continue to close over anotherfunc's environment even when it's no longer being evaluated in anotherfunc. This code will also work:

def anotherfunc(h):
    def func(): return h
    return func

print anotherfunc(10)()

This will print 10.

This, as you notice, has nothing to do with lambda's - they are two different (although related) concepts.

152
meade

I'm just beginning Python and ran head first into Lambda- which took me a while to figure out. Is lambda one of those 'interesting' language items that in real life should be forgotten? I'm sure there are some edge cases where it might be needed, but given the obscurity of it, the potential of it being redefined in future releases (my assumption based on the various definitions of it) and the reduced coding clarity - should it be avoided? This reminds me of overflowing (buffer overflow) of C types - pointing to the top variable and overloading to set the other field values...sort of a techie showmanship but maintenance coder nightmare..

Answered By: David Zaslavsky ( 192)

Are you talking about lambda functions? Like

f = lambda x: x**2 + 2*x - 5

Those things are actually quite useful. Python supports a style of programming called functional programming where you can pass functions to other functions to do stuff. Example:

mult3 = filter(lambda x: x % 3 == 0, [1, 2, 3, 4, 5, 6, 7, 8, 9])

sets mult3 to [3, 6, 9], those elements of the original list that are multiples of 3. This is shorter (and, one could argue, clearer) than

def filterfunc(x):
    return x % 3 == 0
mult3 = filter(filterfunc, [1, 2, 3, 4, 5, 6, 7, 8, 9])

Of course, in this particular case, you could do the same thing as a list comprehension:

mult3 = [x for x in [1, 2, 3, 4, 5, 6, 7, 8, 9] if x % 3 == 0]

(or even as range(3,10,3)) but there are other cases, like constructing functions as return values from other functions, where you can't use a list comprehension and a lambda function may be the shortest way to write something out. Like

def transform(n):
    return lambda x: x + n
f = transform(3)
f(4) # is 7

I use lambda functions on a regular basis. It took a while to get used to them but once I did I'm glad Python has them ;-)

For a person without a comp-sci background, what is a lambda in the world of Computer Science?

Answered By: mk. ( 205)

Lambda comes from the Lambda Calculus and refers to anonymous functions in programming.

Why is this cool? It allows you to write quick throw away functions without naming them. It also provides a nice way to write closures. With that power you can do things like this.

Python

def adder(x):
    return lambda y: x + y
add5 = adder(5)
add5(1)
6

JavaScript

var adder = function (x) {
    return function (y) {
        return x + y;
    };
};
add5 = adder(5);
add5(1) == 6

Scheme

(define adder
    (lambda (x)
        (lambda (y)
           (+ x y))))
(define add5
    (adder 5))
(add5 1)
6

As you can see from the snippet of Python and JavaScript, the function adder takes in an argument x, and returns an anonymous function, or lambda, that takes another argument y. That anonymous function allows you to create functions from functions. This is a simple example, but it should convey the power lambdas and closures have.

150
Tor Haugen

Right, so I have an enumerable and wish to get distinct values from it.

Using System.Linq, there's of course an extension method called Distinct. In the simple case, it can be used with no parameters, like:

var distinctValues = myStringList.Distinct();

Well and good, but if I have an enumerable of objects for which I need to specify equality, the only available overload is:

var distinctValues = myCustomerList.Distinct(someEqualityComparer);

The equality comparer argument must be an instance of IEqualityComparer<T>. I can do this, of course, but it's somewhat verbose and, well, cludgy.

What I would have expected is an overload that would take a lambda, say a Func<T, T, bool>:

var distinctValues
    = myCustomerList.Distinct((c1, c2) => c1.CustomerId == c2.CustomerId);

Anyone know if some such extension exists, or some equivalent workaround? Or am I missing something?

Alternatively, is there a way of specifying an IEqualityComparer inline (embarass me)?

Update

I found a reply by Anders Hejlsberg to a post in an MSDN forum on this subject. He says:

The problem you're going to run into is that when two objects compare equal they must have the same GetHashCode return value (or else the hash table used internally by Distinct will not function correctly). We use IEqualityComparer because it packages compatible implementations of Equals and GetHashCode into a single interface.

I suppose that makes sense..

Answered By: Carlo Bos ( 245)
myCustomerList.GroupBy(cust => cust.CustomerId).Select(grp => grp.First());