From: Robert D. <rob...@gm...> - 2024-02-17 22:09:29
|
While working through fixing up the share test suite to correct results the lexical symbols branch, I observed a few different ways of using nonlexical symbols in the various share packages. I am guessing that we may bump into similar examples when people are writing code for a hypothetical lexically-equipped Maxima. (1) use of global variables to communicate between functions aside from function arguments, e.g. f() := block([y: ...], g()); g() := h(y); (2) calling a global function and assigning the return value to a local variable of the same name, e.g. block([length], length: length(...), ...) (3) calling assoc with a first argument which is a local variable and the second argument contains global variables, e.g. f([a]) := block([foo], assoc('foo, a)); f(foo = 123); (4) substitution of a local variable into an expression containing global variables, e.g. f(e) := block([x], subst ('x = ..., e)); f(x + 1); Other variations are certainly possible, these are just the ones I remember seeing. Item 1 was probably the most common. There are workarounds for all of these. For (1), make the global variables into function arguments, or, more hackishly, declare them nonlexical. For (2), give the local variable a different name, e.g. my_length instead of length. For (3), give the local variable a different name, e.g. foo_value instead of foo, or just don't make it a local variable if its value is never used. For (4), supply the name of the variable of interest along with the expression to obviate the need to guess the variable, e.g. f(e, var) := subst(var = ..., e); These are all (with the exception of the nonlexical declaration) a good idea anyway. These are not too important in themselves but I think they're useful to talk about since they represent existing programming constructs which work differently in the presence of lexical symbols. best Robert |