Hi there,
I want to use a struct and related methods from the package ProximalOperators.jl. Specifically, I want to change the field lambda
of an immutable struct.
MWE:
using ProximalOperators
function foo(g::T) where T <: ProximableFunction
g.lambda = 1.0
end
foo(NormL1())
which gives an ERROR: type is immutable
. Makes sense, since NormL1 is immutable…
How do I proceed from here?
I tried changing the struct NormL1
from immutable to mutable inside my own module:
module mymodule
import ProximalOperators: NormL1, ProximableFunction
export NormL1
mutable struct NormL1{T <: Union{Real, AbstractArray}} <: ProximableFunction
lambda::T
function NormL1{T}(lambda::T) where {T <: Union{Real, AbstractArray}}
if !(eltype(lambda) <: Real)
error("λ must be real")
end
if any(lambda .< 0)
error("λ must be nonnegative")
else
new(lambda)
end
end
end
NormL1{R <: Real}(lambda::R=1.0) = NormL1{R}(lambda)
end
Now I can do foo(mymodule.NormL1())
without errors. However, I cannot see how to overload all existing methods in ProximalOperators that make use of NormL1
, see e.g., prox!, without copy-pasting all of them to mymodule
and changing the relevant function signatures from ProximalOperators.NormL1
to mymodule.NormL1
.
Links and tips for handling this, would be very much appreciated.
Best,
Oliver
You can’t redefine a type. Also, unless it is exported, your definition inside another module (possibly Main
) will be different from the one in the original module, since they are different namespaces.
Perhaps you should simply create a new NormL1
instance with the desired value? It seems to be just a wrapper with some check, should not be too costly.
Thanks,
I agree that it is not too costly for this MWE, but if I wanted more methods and related functions from that package, I would end up with a lot of redundant code, right?
Furthermore, I actually want to iterate over different lambda, not just the 1.0 I set above…
Perhaps you misunderstand my suggestion, I was not recommending that you duplicate any code, just create new instances, eg NormL1(1.0)
, since you cannot change existing ones.
It is possible that you are not using this package as it was intended (I cannot say as I am not familiar with it). It appears to be superbly documented, so if something is not clear after reading the docs, perhaps ask the author.
Why not create different instances of NormL1
inside your loop as in:
using ProximalOperators
function foo(g::T) where T <: ProximableFunction
# g.lambda = 1.0
# simply use g
end
for lambda in linspace(0, 10, 100)
foo(NormL1(lambda))
end
In the end, NormL1
is constructed either via a scalar or some array. Arrays are passed by pointer, and neither of the constructions should result in a huge penalty in performance.
1 Like
Thanks @Tamas_Papp and @aytekinar. That’s exactly what I needed.
1 Like