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

时间:2016-09-02 13:00:23

标签: julia

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

我知道函数就像push!(list, a)一样,它会改变它们的输入,但是如何使用感叹号定义我自己的一个。

3 个答案:

答案 0 :(得分:14)

!只是一个惯例;它不是变异函数的必要条件。

任何函数都可以改变其输入。 但是很明显它正在这样做,我们用!后缀。

但要变异的输入确实必须是可变的。 其中不包括String,元组,Int64Float32等。 以及使用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字段的新值。