"functional" update of structures?

#1

I’m almost sure I’ve seen this addressed before, but my intertube search skills have failed me.

i’m looking for something that will let me do:

struct S1 a; b; c end

function f1(s::S1, new_b)
  s(b=new_b)
end

s2 = f1(s, 5)

i.e., f1 will actually return a new copy of s with the b field updated, i.e. s2 will be a new instance of S1. This allows me to keep struct S1 immutable, and of course not have to type out all of the other fields which are not being updated.

I’m sure i’ll find the post that addressed this approximately 10 minutes after I press “Create Topic”

1 Like
#2

maybe this?

struct S1 a; b; c end

function f1(s::S1, new_b)
  return S1(s.a,b_new,s.c)
end

s2 = f1(s, 5)
#3

There’s a proposal to create a language feature for this: https://github.com/JuliaLang/julia/pull/21912 and I think SetField.jl will let you do something similar right now.

3 Likes
#4

Setfield.jl ! (lowercase F) That was it. I knew there was something…
I think it would be a terrific feature.

I wonder if it could be morphed into a destructuring feature also, a la Haskell

function foo(s(a=a, b=b, c=c))
...

it really is handy.

and an example…

julia> using Setfield
[ Info: Precompiling Setfield [efcf1570-3423-57d1-acb7-fd33fddbac46]

julia> struct S1 a;b;c end

julia> s=S1(1,2,3)
S1(1, 2, 3)

julia> foo(s) = @set s.a=10
foo (generic function with 1 method)

julia> s2=foo(s)
S1(10, 2, 3)

julia> s2
S1(10, 2, 3)

julia> s
S1(1, 2, 3)
1 Like
#5

Yeah, Setfield is the way to go :slight_smile:

I use @unpack from Parameters.jl for this purpose.

2 Likes
#6

I use this function:

assoc(o::T, key, value) where T = T(map(f -> f ≡ key ? value : getproperty(o, f), propertynames(o))...)