【问题标题】:Maxima: Force a function to run with local-variables only? / How to Avoid Local Operations Affecting Global-Variables?Maxima:强制函数仅使用局部变量运行? / 如何避免影响全局变量的局部操作?
【发布时间】:2020-11-23 22:19:48
【问题描述】:

我刚刚发现我对 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[ ] 内被分配了 ab 的值,这给出了全局设置值,所以 ab 的内部分配有对输出没有影响。

让我惊讶的是第二次运行该函数:

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

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


我如何理解我的一个例子是,我定义了一个变量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 的赋值移动到正文时,它将该值保存到了全局上下文中。 除了了解这个特殊案例之外,我还不清楚哪些最佳做法可以防止此类问题。有没有办法将函数的范围限制为仅本地定义的变量?

【问题讨论】:

    标签: function global-variables local-variables maxima wxmaxima


    【解决方案1】:

    有几件事正在发生;我会努力解决的。

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

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

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

    【讨论】:

    • 非常感谢您抽出时间如此清楚地解释事情,罗伯特。您的解释非常宝贵,确实帮助我初步了解了 Maxima,我非常感谢。我们刚刚启动我们的 NPO 并且目前正在使用个人信用额度,但我们将寻找一位可以帮助解决我们遇到的编程问题的 Maxima 顾问。如果您对此感兴趣,请告诉我,因为很高兴与您合作。
    • 我很乐意就此谈一谈。我可以请您向我的个人邮箱发送消息吗?我的电子邮件地址是 gmail dot com 的名字 dot last name。
    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-05
      • 2022-08-02
      • 2012-12-19
      • 2019-07-24
      • 2017-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多