There was this discussion:
https://github.com/JuliaLang/julia/issues/3706
You could also use keyword constructors for the types. Although keyword
functions are a performance bottleneck.
Anyway, my solution to this problem was to use this function:
@doc """
Make a new instance of a type with the same values as
the input type except for the fields given in the associative
second argument or as keywords.
type A; a; b end
a = A(3,4)
b = reconstruct(a, [(:b, 99)])
""" ->
function reconstruct{T}(pp::T, di)
di = !isa(di, Associative) ? Dict(di) : di
ns = names(pp)
args = Array(Any, length(ns))
for (i,n) in enumerate(ns)
args[i] = get(di, n, getfield(pp, n))
end
T(args...)
end
reconstruct{T}(pp::T; kws...) = copyandmodify(pp, kws)
The non-keyword call may circumnavigate the slowness of keyword
functions (although I have not tested this).
This function is part of https://github.com/mauro3/Parameters.jl which
is very much unfinished.
On Wed, 2015-02-18 at 12:57, Ariel Keselman <[email protected]> wrote:
> I'm working with arrays of immutables each containing several fields. Now
> creating new immutables based on old ones has become a real pain:
>
> old = myarray[i]
> myarray[i].foo = myimmutable(old.foo, bar, old.x, old.y, etc.)
>
> imagine this for 15 fields...!
>
> So I made a macro to ease this, it can be used like this:
>
> @set myarray i bar=newbar x=newx
>
> and the rest of the parameters remain the same. See code below.
>
> The problem is that although I can autogenerate the macro for different types,
> I cannot use the same function name @set for all types. Each type has to have
> its own special macro!
>
> The reason is that this macro requires knowledge of the types it is working
> on,
> something missing at macro "runtime". While stagedfunctions do have type
> information, they miss the array symbol name.
>
> Maybe a "stagedmacro" could help ;)
>
> Do you know how could this be solved?
>
> Thanks!
>
> immutable IM
> aa::Float64
> bb::Float64
> cc::Float64
> dd::Float64
> ee::Float64
> ff::Float64
> gg::Float64
> hh::Float64
> ii::Float64
> jj::Float64
> kk::Float64
> ll::Float64
> end
>
> macro set(ARR, IX, KV...)
> d = [p.args[1]=>p.args[2] for p in KV]
> aa = get(d,:aa,:($ARR[$IX].aa))
> bb = get(d,:bb,:($ARR[$IX].bb))
> cc = get(d,:cc,:($ARR[$IX].cc))
> dd = get(d,:dd,:($ARR[$IX].dd))
> ee = get(d,:ee,:($ARR[$IX].ee))
> ff = get(d,:ff,:($ARR[$IX].ff))
> gg = get(d,:gg,:($ARR[$IX].gg))
> hh = get(d,:hh,:($ARR[$IX].hh))
> ii = get(d,:ii,:($ARR[$IX].ii))
> jj = get(d,:jj,:($ARR[$IX].jj))
> kk = get(d,:kk,:($ARR[$IX].kk))
> ll = get(d,:ll,:($ARR[$IX].ll))
> quote
> @inbounds $ARR[$IX] =
> IM($aa,$bb,$cc,$dd,$ee,$ff,$gg,$hh,$ii,$jj,$kk,$ll)
> end
> end
>
> this is used as follows:
>
> a = [IM(1,1,1,1,1,1,1,1,1,1,1,1),
> IM(1,1,1,1,1,1,1,1,1,1,1,1),
> IM(1,1,1,1,1,1,1,1,1,1,1,1),
> IM(1,1,1,1,1,1,1,1,1,1,1,1),
> IM(1,1,1,1,1,1,1,1,1,1,1,1)]
>
> @set a 1 aa=9 ll=9
>
> # a is now:
> # [
>
> # IM(1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0)
> # IM(9.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,9.0)
> # IM(1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0)
> # IM(1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0)
> # IM(1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0)]