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