Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I thought C# has lexical scoping, but why this example shows dynamic scoping behavior?

Tags:

scope

c#

    var x = 1;
    Func<int,int> f = y => x + y;
    x = 2;
    Console.WriteLine(f(1));

The output is 3. I would assume it is 2, according to https://web.archive.org/web/20170426121932/http://www.cs.cornell.edu/~clarkson/courses/csci4223/2013sp/lec/lec12.pdf

like image 240
colinfang Avatar asked Apr 25 '13 17:04

colinfang


1 Answers

There's a subtlety concerning lexical scoping that PDF doesn't fully explain. Its example actually has two different variables named x, it does not reassign the value of the first x (and indeed functional languages may not allow mutation).

C# is lexically scoped -- it looks up x at the point of definition of the lambda, not when the delegate is invoked. But: x resolves to a variable, not a value, and it reads the variable's value at the time of invocation.

Here is a more complete example:

int InvokeIt( Func<int, int> f )
{
   int x = 2;
   return f(1);
}

Func<int, int> DefineIt()
{
   int x = 1;
   Func<int, int> d = (y => x + y);
   x = 3;  // <-- the PDF never does this
   return d;
}

Console.WriteLine(InvokeIt(DefineIt()));

The lambda binds to the x variable that exists inside DefineIt. The value (x = 1) at the point of definition is irrelevant. The variable is later set to x = 3.

But it is clearly not dynamic scope either, because the x = 2 inside InvokeIt is not used.

like image 66
Ben Voigt Avatar answered Oct 06 '22 08:10

Ben Voigt