Open uranusjr opened 3 years ago
In that case, what is the mechanism that variable modifications are propagated back to the parent namespace (the one that runs eval
)? And would it be possible for functions and variables to behave the same?
I think the main issue I’m having is less about the functions not being copied back, but more that the behaviour is confusing.
I don't really understand why this is happening, but maybe @xiaq can clarify.
What I did notice is that if you assign a value to the x~
variable, then the change gets reflected in the current namespace:
> /bin/cat x.elv
x~ = []{ echo 'x inside' }
y = 'y inside'
> eval (slurp < x.elv)
> x
x inside
Variable names are statically checked. This is why eval
is not allowed to create or delete names.
Variable values are dynamic. This is why eval
can reassign existing variables.
The namespace eval
gets is a copy of the local scope it is invoked from, but it's a shallow copy - the variables in the namespaces themselves are aliased.
@uranusjr wrote
eval
can set value variables, but not functions.
What your example does is set variables visible (i.e., aliased) in the eval
scope and define functions in the eval
lexical scope. The fn
keyword does not just "set" a function variable; i.e., assign a lambda to a function variable. It also defines (i.e., creates) the function variable. Which, because of the eval
lexical scope, is not visible in the callers scope. That's why @zzamboni's approach "works". TBD is how to modify the documentation to make this subtle point easier to discover.
P.S., @uranusjr your original problem statement is a great example of how such issues should be written. It was concise and unambiguous. I look forward to many more questions and bug reports from you and suspect the same is true for much of the Elvish community.
What your example does is set variables visible (i.e., aliased) in the
eval
scope and define functions in theeval
lexical scope. Thefn
keyword does not just "set" a function variable; i.e., assign a lambda to a function variable. It also defines (i.e., creates) the function variable. Which, because of theeval
lexical scope, is not visible in the callers scope. That's why @zzamboni's approach "works". TBD is how to modify the documentation to make this subtle point easier to discover.
Thanks for the clear explaination! This makes more sense to me now. Some documentation on this would be awesome 🙂 (Also to make clear whether @zzamboni’s approach would be guaranteed to work while Elvish’s implementation progresses.)
eval
can set value variables, but not functions. This makes it difficult to implement something like Bash’sactivate
.