|
From: Robert D. <rob...@gm...> - 2019-05-15 15:37:07
|
On Tue, May 14, 2019 at 5:10 PM Gregor Stefnoski <mat...@gm...> wrote:
> f(x) := sum(i*x, i, 1, 5);
> f(i); /* output: 55 (!!!) */
> The result of f(i) should be 15*i, but it is not. Am I doing something wrong? I see this as a clear scoping bug in Maxima.
The basic problem is that variables in Maxima have dynamic scope, not
lexical. So the i which appears at the top level is the same i which
is inside of the function f. Dynamic scope quite easily leads to
problems with variables which should be distinct getting mixed up, as
you have experienced.
sum is a bit of a special case, since the loop index is conceptually
local to sum, while that's not usually the case for ordinary
functions. An attempt was made some years ago (by me) to strengthen
the local-ness of the summation index, which as you have observed, was
not entirely successful. I apologize, I think if I worked on it again,
I could do better.
Note that other Maxima functions which might make use of
conceptually-local variables, such as integrate, do not. That's a
missed opportunity, or a welcome consistency, depending on how one
looks at it.
> One workaround I have is to use apply("+", ...) and makelist instead. The function g below is equivalent to f, except it does not have this problem with argument i.
A simpler workaround is to say sum(i_foo*x, i_foo, 1, 5), i.e. give
the summation index a name which is unlikely to collide with a
user-assigned name. In fact that could be carried out automatically,
with the sum function automatically substituting a made-up symbol
(called a gensym) for the summation index ... I thought that I had
done that, in the afore-mentioned revision from years ago, but on
looking at the code again, it appears that I did not, or did not do it
correctly.
best,
Robert Dodier
|