Consider this example:
If we want to substitute away the type definition, we might naively get:class C.<T> {
type A = T
function f.<T>() {
var x : A = ...
}
}
But then x's type annotation is referring to the wrong T! This corresponds exactly to the notion from hygienic macros (commonly referred to as referential transparency) that references in a macro definition should retain their meaning from the macro definition environment, never the macro use environment.class C.<T> {
function f.<T>() {
var x : T = ...
}
}
In other words, the above program should really be resolved to:
Now consider another example, this time with a parameterized typedef:class C.<T> {
function f.<T'>() {
var x : T = ...
}
}
A naive substitution would producetype A.<X> = function.<T>():[X,T]
class C.<T> {
var a : A.<T> = ...
}
This time the bug is that we've allowed a type definition to introduce a binding that captured a binding in the context of the use of the typedef. This is an example of the hygiene condition, which states that bindings introduced by a macro should not capture variables in the macro application site. The proper expansion of the typedef would instead be:class C.<T> {
var a : function.<T>():[T,T] = ...
}
These are exactly the same conditions that hygienic macro expanders must meet in order to prevent unintended variable capture; the only difference is that here we're concerned with type variables rather than program variables.class C.<T> {
var a : function.<T'>():[T,T'] = ...
}
No comments:
Post a Comment