Consider the following code:
test(lambda([], X = 2)) :-
X = 7.
While X is used in two separate places, these two X's are distinct. The reason why is that for lambdas, we consider variables introduced in the lambda to be local to the lambda, starting from the clause head to the body. As such, the X in the lambda is encountered first, and it is marked local to the lambda. The body is then traversed, and the X in the body is considered local to the body.
Usually, this behavior reflects intended usage. However, this occasionally leads to some anti-patterns. For example, consider the following:
test :-
X = _,
Y = lambda([], X = 7),
call(Y),
writeln(X).
The seemingly useless X = _ in the above code is necessary to introduce X before the lambda is encountered. Without this, X would be considered local to the lambda, and we'd end up printing out an uninstantiated variable as opposed to 7. Moreover, if we neglected to include the X = _, this wouldn't get flagged as a singleton, as we piggyback off of SWI-PL's singleton checking, which doesn't understand that lambdas introduce a new scope (it sees them only as typical constructors). We should have a version of singleton checking which is aware of the scoping modifications lambdas introduce, to help alleviate this problem.
Consider the following code:
While
Xis used in two separate places, these two X's are distinct. The reason why is that for lambdas, we consider variables introduced in the lambda to be local to the lambda, starting from the clause head to the body. As such, theXin the lambda is encountered first, and it is marked local to the lambda. The body is then traversed, and theXin the body is considered local to the body.Usually, this behavior reflects intended usage. However, this occasionally leads to some anti-patterns. For example, consider the following:
The seemingly useless
X = _in the above code is necessary to introduceXbefore the lambda is encountered. Without this,Xwould be considered local to the lambda, and we'd end up printing out an uninstantiated variable as opposed to7. Moreover, if we neglected to include theX = _, this wouldn't get flagged as a singleton, as we piggyback off of SWI-PL's singleton checking, which doesn't understand that lambdas introduce a new scope (it sees them only as typical constructors). We should have a version of singleton checking which is aware of the scoping modifications lambdas introduce, to help alleviate this problem.