Maxima:仅使用局部变量强制函数 运行? / 如何避免局部操作影响全局变量?

Maxima: Force a function to run with local-variables only? / How to Avoid Local Operations Affecting Global-Variables?

我刚刚发现我对 block 函数的工作原理有一些基本的误解。

总的来说,我认为“在函数中发生的事情,留在函数中(除非返回);”然而,情况似乎并非如此,所以我希望有人能帮助我解决这个问题。

一个简单的例子:

/* Define & Initialize Variables */
[a,b]:[7,-5];

aFunction():= block([c:a, d:b], a:1, b:2,[c,d]);

现在,如果我们 运行 函数,我们得到:

result1 : aFunction(); 
>>> [7, -5]

这是有道理的:cd被赋予了a的值,[ ]中的b给出了全局设置值,所以ab 的内部分配对输出没有影响。

让我吃惊的是,运行第二次使用这个函数:

result2 : aFunction();
>>> [1,2]

我只能得出结论,在 aFunction() 块中发生的赋值 a:1b:2 实际上会影响全局变量。如果这是真的,你如何组织你的工作,这样这种行为就不会回来咬你?我现在看到的唯一完全安全的方法是每次都开始一个新文档,这有点乏味。 是否有另一种方法可以确保函数内的工作不会影响函数外发生的事情?我在下面提供了我遇到的问题类型的示例,获取更多上下文。


一个让我感到痛苦的例子是,我在块的 [ ] 部分定义了一个变量 defaultValue,该变量以前未在文档的其他地方声明过:

newFunction():=block( [ defaultValue : 10, a : defaultValue ] random(a) );

函数没有按预期运行,因为在 [ ] 部分并行分配变量(因为 defaultValue 没有全局定义,它试图计算 random(defaultValue)).

那时我不知道并行赋值,所以我尝试将赋值移动到块的主体。

newFunction():=block( [ a : defaultValue ], defaultValue : 10, random(a) );

当然,第一个 运行 也没有用,所以我认为问题不在于分配的位置。然后我发现了我认为一定是错误的其他东西,因此,在解决该问题之后,我尝试将作业放回 [ ] 部分:

newFunction():=block( [ defaultValue : 10, a : defaultValue ] random(a) );

当然,因为我已经执行了函数,与此同时,defaultValue 已经全局定义(我也不知道)。

我只是意识到有些地方出了问题,因为我不相信 Maxima 的黑魔法,总的来说,我想确保它按预期工作,所以尝试更改 defaultValue 的值,仅看到它没有效果(谢谢并行赋值...)。

如前所述,我相信代码正在执行的原因是,当我将 defaultValue 的赋值移动到正文时,它将该值保存到全局上下文中。 除了了解这种特殊情况外,我还不清楚哪些最佳做法可以防止出现此类问题。有没有办法将函数的范围限制为仅本地定义的变量?

虽然我无意 post 问答,但经过更多实验后,我注意到一个解决方案是 'self-assign' 所有变量,在函数的开头,在块的 [ ] 部分内。例如:

bFunction():=block([c:a, d:b],a:1,b:2,[c,d]);
cFunction():=block([A:A, B:B, C:A, D:B],A:1,B:2,[C,D]);

如果这些中的每一个都是 运行 在已分配 none 个变量的环境中,那么 bFunction() 的后续执行将改变:

  1. bResult1 : bFunction(); >>> [a,b];
  2. bResult2 : bFunction(); >>> [1,2];

多次执行 cFunction() 不会:

  1. cResult1 : bFunction(); >>> [A,B];
  2. cResult2 : bFunction(); >>> [A,B];

发生了几件事;我会尽力解决的。

一个是区分块中局部变量和全局变量的问题。事实证明答案是这样的:块中的变量是局部变量当且仅当它在封闭块开头的变量列表中被命名时,否则它是全局变量。请注意,这涵盖了嵌套块。一个变量是全局的,当且仅当它没有在任何封闭块开头的变量列表中命名。

另一个问题是使用什么值来初始化。答案只是赋值的右侧是块外表达式的值。例如,在 block([a: foo(a)], ...) 中,表达式 foo(a) 在块外用 a 的值求值,然后赋值给块内的 a

顺便说一句,([a, b, c], ...)不把a、b、c当作局部变量。您必须说 block([a, b, c], ...) 才能获取局部变量 a、b 和 c。