Julia中的变异函数(修改其参数的函数)

Julia中的变异函数(修改其参数的函数),julia,Julia,如何在Julia中定义一个变异函数,希望将结果写入其中一个输入 我知道函数的存在就像推!(列表,a),它们改变了它们的输入,但如何使用感叹号定义自己的输入。代码>只是一种惯例;这不是变异函数的要求 任何函数都可以改变其输入。 但是为了清楚地表明它正在这样做,我们在它后面加了一个 但是,要变异的输入必须是可变的。 它不包括Strings、元组、Int64s、Float32s等。 以及在没有可变关键字的情况下定义的自定义类型 许多类型是可变的,比如向量。 但你需要确保改变它们的内容, 而不是对它们的

如何在Julia中定义一个变异函数,希望将结果写入其中一个输入


我知道函数的存在就像推!(列表,a),它们改变了它们的输入,但如何使用感叹号定义自己的输入。

代码>只是一种惯例;这不是变异函数的要求

任何函数都可以改变其输入。 但是为了清楚地表明它正在这样做,我们在它后面加了一个

但是,要变异的输入必须是可变的。 它不包括
String
s、元组、
Int64
s、
Float32
s等。 以及在没有
可变
关键字的情况下定义的自定义类型

许多类型是可变的,比如向量。 但你需要确保改变它们的内容, 而不是对它们的引用

比方说,我们想做一个函数,用数字2替换向量的所有元素。 (
fill!(v,2)
是实现这一点的基本方法。但举个例子)

什么有效 更改
v
包含的内容:

function right1_fill_with_twos!(v::Vector{Int64})
    v[:]=[2 for ii in 1:length(v)]
end
这与:

function right2_fill_with_twos!(v::Vector{Int64})
    for ii in 1:length(v)
        v[ii]=2
    end
    v 
end
function wrong2_fill_with_twos!(v::Vector{Int64})
    u = Vector{Int64}(length(v))
    for ii in 1:length(v)
        u[ii]=2
    end
    v = u 
end
那么什么不起作用呢 这个名字所指的改变是什么

function wrong1_fill_with_twos!(v::Vector{Int64})
    v=[2 for ii in 1:length(v)]
end
这与:

function right2_fill_with_twos!(v::Vector{Int64})
    for ii in 1:length(v)
        v[ii]=2
    end
    v 
end
function wrong2_fill_with_twos!(v::Vector{Int64})
    u = Vector{Int64}(length(v))
    for ii in 1:length(v)
        u[ii]=2
    end
    v = u 
end
无法修改不可变变量(如
Int64
s)的原因, 因为它们没有可修改的内容——它们是它们自己的内容

在许多编程语言中,必须更改传递给函数的变量的内容,而不是更改名称绑定到的内容(替换对象)这一概念是相当标准的。它来自传递值,其中一些值是引用。
我听说它在Java中被称为黄金法则(引用规则)

如果您愿意将与常量对应的符号作为参数提供给函数,则可以为函数中的常量指定新值,尽管我认为有些人可能会认为这不符合Julia编程最佳实践:

function modify_constant!(constant_symbol::Symbol, other_arg)
    new_val = eval(constant_symbol) + other_arg
    eval(Main, Expr(:(=), constant_symbol, new_val))
end

y = 2
modify_constant!(:y, 3)

julia> y
5
或者,如果你愿意的话,更简洁一点:

function modify_constant!(constant_symbol::Symbol, other_arg)
    eval(Expr(:(+=), constant_symbol, new_val))
end

有关相关问题的更多讨论,请参见此

对于结构类型,您可以使用
setfield!(value,name::Symbol,x)
getfield(value,name::Symbol)
在函数内部


调用函数时,需要传递struct obj/name(值)和字段符号(名称)。(x) 是struct字段的新值。

是常见问题解答中的一个简明示例。那么这是否意味着只有当需要修改的变量类型本身可变时,才会发生这种情况?@a.Yazdiha是的,这是正确的。请注意,即使它是可变的,并且您在函数中为该变量指定了一个新值(而不是简单地通过索引指定来对其进行变异),您也会得到一个新对象。@TasoSpapStylianou好吧,我认为这基本上是正确的。如果您愿意使用符号和表达式,请参阅下面我的回答,了解一点相反的观点。:)哈哈。美好的嗯,是的,如果你可以通过不安全的指针操作(例如,
unsafe\u store!
)存储新值,你也可以强制改变对象,但这完全是绕过预期行为的黑客行为,而不是应该发生的事,嘿嘿。引用的黄金法则?从没听说过,你确定吗?更不用说,我不认为Java具有与Julia相同的“可变/不可变”对象……所谓的“黄金法则”不是关于不可变,而是关于更改通过引用传递的变量的内容,而不是它们的绑定。我编辑了这篇文章来澄清。“黄金法则”这个名字可能并不常见——它可能是我第一年的Java讲师为它命名的,这样他的学生就不会再犯同样的错误了。在这种情况下,它完全起作用了,因为我今天还记得它。要修改字典,你可以做一些类似于
foreach(x->delete!(orig,x),keys(orig))
然后是
merge!(orig,new)
而不是
orig=new
@phyatt你建议我的answr的哪一部分需要更改?我找到了你的答案,它帮助我了解了代码中的问题所在,但我不是在处理变异的
向量
,我是在变异
Dict
。所以,如果你想做一个Dict变异的例子,我最后的评论会让你开始。