(x, y) => x.AddYears(int.Parse(y.ToString()) + z * k)
Fig. 1.1: A lambda expression in C#
There is a lot we don't know for certain about this lambda expression. We can infer that x is a DateTime, but that isn't necessarily the case, and y could be almost anything. This lambda expression at least needs type declarations for these variables, so let's provide them:
Func<DateTime, int, DateTime> f =
(x, y) => x.AddYears(int.Parse(y.ToString()) + z * k);
Fig. 1.2: A lambda expression in C#, partially disambiguated by its environment
Here, we have implicitly defined the types of x and y by assigning the lambda expression to a delegate whose type has been made explicit. Now, we have a lambda expression with two open variables, z and k. In order to create a closure, we need to close the variables z and k using the lexical environment of the expression.
Suppose the expression appears in the following environment:
DateTime g() {
int z = DateTime.Now.Year;
int k = 13;
Func<DateTime, int, DateTime> f =
(x,y) => x.AddYears(int.Parse(y.ToString()) + z * k);
}
Fig. 1.3: A lamba expression in its lexical environment
In this environment, we now have all of the information we need to populate the closure. In Landin's terms, a closure has an "environment part" and a "control part". Using those terms, our closure record (for the lambda expression only) could look like this:
Environment Part {
Symbol {
Name: z;
Type: int;
Value: DateTime.Now.Year;
}
Symbol {
Name: k;
Type: int;
Value: 13;
}
}
Control Part {
Parameter {
Name: x;
Type: DateTime;
}
Parameter {
Name: y;
Type: string;
}
Value Expression: x.AddYears(int.Parse(y.ToString()) + z * k);
}
Fig. 1.4: A preliminary mockup of a closure record
In the next post, I'll unpack the structure of the value expression.
[1] P. J. Landin (1964), The mechanical evaluation of expressions
No comments:
Post a Comment