如何在Julia中定义变异函数,您希望将结果写入其中一个输入。
我知道函数就像push!(list, a)
一样,它会改变它们的输入,但是如何使用感叹号定义我自己的一个。
答案 0 :(得分:14)
!
只是一个惯例;它不是变异函数的必要条件。
任何函数都可以改变其输入。
但是很明显它正在这样做,我们用!
后缀。
但要变异的输入确实必须是可变的。
其中不包括String
,元组,Int64
,Float32
等。
以及使用immutable
关键字定义的自定义类型。
大多数类型都是可变的,比如Vectors。 但你确实需要确保更改他们的内容, 而不是引用给他们。
比如说,我们想要创建一个用数字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
正在改变名称v
指向
function wrong1_fill_with_twos!(v::Vector{Int64})
v=[2 for ii in 1:length(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),
是因为他们没有要修改的内容 - 他们是他们自己的内容。
这个概念必须更改传入函数的变量的内容,而不是更改名称绑定的内容(替换对象)在许多编程语言中是相当标准的。它来自pass by value,其中一些值是引用。 我听说它在Java中称为黄金法则(参考文献)
答案 1 :(得分:2)
如果您愿意为该函数提供与常量相对应的符号作为参数,则可以为函数中的常量赋值新值,尽管我认为有些人可能会认为这并不是函数。满足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
有关相关问题的详细讨论,请参阅此Github discussion
答案 2 :(得分:1)
对于结构类型,可以在函数内使用setfield!(value, name::Symbol, x)
和getfield(value, name::Symbol)
。
调用该函数时,需要传递struct obj / name(值)和字段符号(名称)。 (x)是struct字段的新值。