I am trying to understand the best approach to pass an array of user input data into a function and make sure that this array is NEVER modified inside the function.
An example of what I would like to do is below:
julia> struct UserStruct
data::Array{Float64}
end
julia> test=UserStruct([1.0 2.0 3.0]) ## The idea is to have these values fixed always
UserStruct([1.0 2.0 3.0])
julia> println(test.data)
[1.0 2.0 3.0]
julia> function TestFun( x::UserStruct)
x.data[1] = 10.0 ## I don't this to be allowed here
end
TestFun (generic function with 1 method)
julia> TestFun(test)
10.0
julia> println(test.data)
[10.0 2.0 3.0]
Could someone provide some comments / resources on how to achieve this goal ? Thanks in advance !
This doesn’t prevent modification absolutely, but the intention (I believe) is to prevent accidental modification. For example, given a ReadOnlyArrays view, a function could use parent to get the original array which it could then modify.
You can wrap an array with a struct and define AbstractArray interface with custom setindex! to disallow mutation but this will never guarantee immutability because someone can still access fields of the struct directly. Then, also, suppress getproperty but there is also getfield.
Perhaps a related question is: what exactly are you trying to protect against? Creating a custom AbstractArray with no setindex! will ensure that users cannot accidentally modify the internal data, and overloading getproperty can make it harder for them to accidentally peek at the underlying array, but it is always possible for a sufficiently motivated user to break things.
Ok thanks everyone for the reply. Going through your answers it appears that there is no straightforward way to do what I am looking for (at least is not clear to me).
@rdeits, what I am trying to protect is to introduce unintentional bugs in my code. The user data will be passed into a quite large function that perform several operations using input data. I just thought that it would help to reduce the risk that something gets modified unintentionally.
Are you sure? ReadOnlyArrays.jl seems like it does exactly what you’re looking for:
julia> using ReadOnlyArrays
julia> struct UserStruct
data::ReadOnlyArray{Float64, 1, Array{Float64, 1}}
end
julia> test = UserStruct(ReadOnlyArray([1.0, 2.0, 3.0]))
UserStruct([1.0, 2.0, 3.0])
julia> test.data[1] = 2.0
ERROR: setindex! not defined for ReadOnlyArray{Float64,1,Array{Float64,1}}