Perform lexical binding of $0 in functions#240
Conversation
This binding is created when a function is looked up by name. Works for settor functions as well. Should be a minimal performance impact, as functions tend to be short lists (typically a single lambda term) and this implementation appends the arguments to the call in the same pass.
|
Found a sufficiently pathological example that gives me a little pause. The idea is that the function Granted, it's a very strange function, but I also don't know if this behavior is the most reasonable way to handle it. When run with current es at HEAD, this does Not so surprising. When run with this PR's es, it does More surprising. |
|
Okay, I figured out what's going on with my script above and I think that the current implementation is basically fine, the script is just pathological and inconsistent. A super minimal repro is here: When we refer to I think this is all basically reasonable on the shell's part; we just found a sharp edge. In theory we could bind |
|
Here is another case to worry about: This can be prevented in the shell by scanning through existing bindings and replacing the top I'm not sure that extra stuff is worthwhile, though. You have to go pretty out of sensible code to get the above behavior. Given the virtue of less-magic mechanisms in es, we might just say that this is fine until somebody trips over it in real life. |
Fixes #239.
Es' historical behavior with
$0is to bind it, dynamically, when invoking a lambda invoked via a function name. This creates confusion, as most obviously demonstrated bybut also illustrated by a number of other examples in #239.
This PR changes the binding of
$0from dynamic to lexical, such that when we look up a function, we bind$0to the function name within the lexical scope of the looked-up definition. This creates good, intuitive behavior in basically all cases, particularly with respect to functions which take other code as arguments. It also removes the behavioral differences betweenfn-x = @ {}andfn-x = $&noreturn @ {}.$0in settor functions also uses this new behavior.$0is still a bit unpredictable, as functions invoked as$fn-Xdo not get$0set toX. But within the body of a function, you're at least now ~guaranteed to have$0set to the function's name, the script you're running, or the es binary.QUESTION: some hook functions are not invoked in a way where
$0is set to the function name.Is this unexpected? Should we scan through these cases and replace
varlookups withfnlookups? It is inconsistent that the syntax-expanded hook functions like%backquoteget$0set to the function name but shell-lookup hook functions like%homedon't.