1

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

一般来说,我认为“函数中发生的事情,会留在函数中(除非返回);” 但是,情况似乎并非如此,所以我希望有人可以帮助我处理这种情况。

一个简单的例子:

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

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

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

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

这是有道理的:candd被分配了 的值ab[ ]其中给出了全局设置值,因此aand的内部分配b对输出没有影响。

令我惊讶的是第二次运行该功能:

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

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


我如何理解的一个例子是,我在块的部分中定义了一个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到主体时,它将该值保存到全局上下文中。除了了解这种特殊情况之外,对我来说,哪些最佳实践可以防止此类问题并不明显。有没有办法将函数的范围限制为仅本地定义的变量?

4

2 回答 2

1

虽然我不打算发布问答,但经过更多实验后,我注意到一种解决方案是在函数的开头,在[ ]块的部分内“自行分配”所有变量。例如:

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]);

如果这些中的每一个都在没有分配任何变量的环境中运行,那么随后的执行bFunction()将会改变:

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

多次执行cFunction()将不会:

  1. cResult1 : bFunction(); >>> [A,B];
  2. cResult2 : bFunction(); >>> [A,B];
于 2020-11-23T22:48:30.067 回答
1

有几件事正在发生;我会试着整理一下。

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

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

顺便说一句,([a, b, c], ...)不将 a、b 和 c 视为局部变量。你必须说block([a, b, c], ...)得到局部变量a、b和c。

于 2020-11-28T05:01:09.327 回答