如何更新一个函数中使用但在另一个函数中已更新的全局变量?

问题描述 投票:0回答:1

我在 Julia 中有以下代码

global a::Int = 0 #global variable

function f(x)
      return a*x
end

function g(y)
      global a = 2
      b = f(2)
      return b
end

这不是确切的代码,但想法是相同的。在这段代码中,当计算 g(y) 中的 f(2) 时,使用的 a 值是原始 a = 0,而不是更新后的值 a = 2。你知道如何解决这个问题吗? ?

我尝试传递 a 作为参数并且它有效,但我想保留函数 f 而不需要额外的参数作为输入。

julia global-variables
1个回答
0
投票

考虑到需要全局变量的情况,经过语法和打印行编辑的代码似乎可以正常工作。要检查这一点,请在

GLOBALVAR
中写入全局变量
g(...)
重新分配之前和之后。

#set the global variable to zero.
global GLOBALVAR = Int(0)

#f(x) references the global variable, but doesn't modify it.
function f(x)
      return GLOBALVAR*x
end

#g(x) modifies the global variable.
function g(y)
      global GLOBALVAR = 2
      b = f(2)
      return b
end

println("Before g(x) call: \n GLOBALVAR = $GLOBALVAR \n f(2) = $(f(2))")
g(2);
println("After g(x) call: \n GLOBALVAR = $GLOBALVAR \n f(2) = $(f(2))")

julia>
Before g(x) call: 
 GLOBALVAR = 0
 f(2) = 0
After g(x) call:
 GLOBALVAR = 2
 f(2) = 4

全局变量已更新。

全局变量会给你带来一些麻烦。它们通常可读性较差,有时性能也较差。我们可能想要重构以排除它们的使用。

一个显着的区别是,在 Julia 中,数字是“不可变的”。像这样的函数 function setToZero!(n::Int) n = 0 return n end num = 10 println("before: $num") setToZero!(num) println("after: $num") julia> before: 10 after: 10

无法按预期运行,因为分配 n 不会改变原始变量。有许多可变类型,一个简单的解决方法是 Vector 
中的值是可变的。

请记住,有很多解决方案,例如 Ref 或完全创建新的可变结构。这样,我们就可以用以下方法重构您的原始代码:

f(x, val::Vector) = val[1]*x

function g!(y, val::Vector)
    val[1] = 2
    return f(2, val)
end

changingVal = [0]

println("Before g!(...) call: \n changingVal = $changingVal \n f(2,changingVal) = $(f(2,changingVal))")
g!(2, changingVal);
println("Before g!(...) call: \n changingVal = $changingVal \n f(2,changingVal) = $(f(2,changingVal))")

julia>
Before g!(...) call: 
 changingVal = [0]
 f(2,changingVal) = 0
Before g!(...) call:
 changingVal = [2]
 f(2,changingVal) = 4

当然,与仅创建单个全局 Int 相比,创建向量的空间和时间效率会更低,因此在这个简化的示例中,“非全局”版本将“显着”变慢。在较大的程序中这可能是也可能不是,但这两种方式都是有效的。

© www.soinside.com 2019 - 2024. All rights reserved.