Whether a variable is free or bound is relative; it depends on the fragment of code you are looking at.
In this fragment, x
is bound:
function(x) {return x + x;};
And here, x
occurs free:
return x + x;
In other words, freeness is a property of the context. You don't say "x is a free variable" or "x is a bound variable," but instead identify the context you are talking about: "x is free in the expression E." For this reason, the same variable x can be either free or bound depending on which fragment of code you are talking about. If the fragment contains the variable's binding site (for example, it is listed in the function arguments) then it is bound, if not, it is free.
Where the free/bound distinction is important from an implementation perspective is when you are implementing how variable substitution works (e.g. what happens when you apply arguments to a function.) Consider the evaluation steps:
(function(x) {return x + x;})(3);
=> 3 + 3
=> 6
This works fine because x
is free in the body of the function. If x
was bound in the body of the function, however, our evaluation would need to be careful:
(function(x) {return (function(x){return x * 2;})(x + x);})(3);
=> (function(x){return x * 2;})(3 + 3); // careful to leave this x alone for now!
=> (function(x){return x * 2;})(6);
=> 6 * 2
=> 12
If our implementation didn't check for bound occurrences, it could have replaced the bound x for 3
and given us the wrong answer:
(function(x) {return (function(x){return x * 2;})(x + x);})(3);
=> (function(x){return 3 * 2;})(3 + 3); // Bad! We substituted for a bound x!
=> (function(x){return 3 * 2;})(6);
=> 3 * 2
=> 6
Also, it should be clarified that free vs. bound is a property of the syntax (i.e. the code itself), not a property of how a the code is evaluated at run-time. vz0 talks about dynamically scoped variables, which are somewhat related to, but not synonymous with, free variables. As vz0 correctly describes, dynamic variable scope is a language feature that allows expressions that contains free variables to be evaluated by looking at the run-time call-stack to find the value of a variable that shares the same name. However, It still makes sense to talk about free occurrences of variables in languages that don't allow dynamic scope: you would just get an error (like "x is not defined") if you were to try to evaluate an such expression in these languages.
And I can't restrain myself: I hope one day you can find the strength to put your revolvers away when people mention lambda calculus! Lambda calculus is a good tool for thinking about variables and bindings because it is an extremely minimal programming language that supports variables and substitution and nothing else. Real-world programming languages contain a lot of other junk (like dynamic scope, for example) that obscures the essence.
f()
, X isn't actually 'variable'? Does that mean that 'bound variable' is equivalent to a constant in 'ancient' languages? I guess my next question is "why is this useful?" – Cyndy