code below
int factor = 2;
Transformer sqr = x => x * factor;
Console.WriteLine(sqr(3)); // 6
factor = 4;
Console.WriteLine(sqr(3)); // 12
I think lambda should capture factor in the compile time, so the result should be the same for the two writeline.
However, when I run, I get 6 and 12, so does the C# lambda use dynamic scoping? I thought lambda should use something called "lexical scope"
First of all you cannot capture anything at compile time. The environment for the lambda can only be captured at runtime, because that's the only time when it exists.
When a variables is captured by a lambda then the lambda has in effect direct access to that variable for the entirety of its lifetime; changes to the value from outside will be seen by the lambda (google "access to modified closure") and the reverse is also true.
It follows that if you want to isolate the lambda from outside interference you have to make it capture something that noone from the "outside" will have access to -- that means a variable whose scope has been sufficiently limited.
Consider:
int factor = 2;
Func<int, Func<int, int>> generateTransformer = f => x => x * f;
Func<int, int> sqr = generateTransformer(factor);
Console.WriteLine(sqr(3)); // 6
factor = 4;
Console.WriteLine(sqr(3)); // 6
What happens here is that sqr
is the result of calling generateTransformer
and it is capturing the value of the local variable f
inside the body of generateTransformer
. That value can never be changed by anyone because it cannot be seen by anyone outside the body of generateTransformer
. Calling generateTransformer
makes a copy of the current value of factor
and gives that "frozen" copy to sqr
to use.
It does capture factor
. It captures it as a member variable of a hidden closure class, along with a method for the lambda. You end up with something approximately similar to
private class sqrClosure
{
public int factor;
public int srq(int x)
{
return x * factor;
}
}
...
var c = new sqrClosure();
c.factor = 2;
Console.Writeline(c.sqr(3));
c.factor = 4;
Console.Writeline(c.sqr(3));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With