我刚刚发现,我对block
如何为函数工作有一些基本的误解。
总的来说,我认为";发生在函数中的内容会停留在函数中(除非返回("然而,情况似乎并非如此,所以我希望有人能帮助我处理好这种情况。
举个简单的例子:
/* Define & Initialize Variables */
[a,b]:[7,-5];
aFunction():= block([c:a, d:b], a:1, b:2,[c,d]);
现在,如果我们运行函数,我们得到:
result1 : aFunction();
>>> [7, -5]
这是有道理的:c
和d
在[ ]
中被分配了a
和b
的值,这给出了全局设置的值,因此a
和b
的内部分配对输出没有影响。
让我惊讶的是,第二次运行该功能:
result2 : aFunction();
>>> [1,2]
我只能得出结论,在aFunction()
的块内发生的分配a:1
和b: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
的赋值移动到主体时,它将该值保存到全局上下文中除了知道这个特殊的案例之外,我还不清楚什么样的最佳实践可以防止这类问题。有没有办法将函数的范围限制为仅本地定义的变量
有几件事正在发生;我会设法解决的。
一个问题是区分块中的局部变量和全局变量。事实证明,答案是这样的:块中的变量是局部的,当且仅当它在封闭块开头的变量列表中命名时,否则它是全局变量。请注意,这包括嵌套块。变量是全局的,当且仅当它没有在任何封闭块开头的变量列表中命名时。
另一个问题是使用什么值进行初始化。答案只是赋值的右侧是块外表达式的值。例如,在block([a: foo(a)], ...)
中,用块外的a
的值来评估表达式foo(a)
,然后将其分配给块内的a
。
顺便说一下,([a, b, c], ...)
不将a、b和c视为局部变量。必须说block([a, b, c], ...)
才能得到局部变量a、b和c。
虽然我无意发布问答;A、 经过更多的实验,我注意到一种解决方案是在块的[ ]
部分中,在函数的开头"自分配"所有变量。例如:
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()
的后续执行将发生变化:
bResult1 : bFunction(); >>> [a,b]
bResult2 : bFunction(); >>> [1,2]
多次执行cFunction()
不会:
cResult1 : bFunction(); >>> [A,B]
cResult2 : bFunction(); >>> [A,B]