# ANN: Setfield.jl Yet another package for working with immutables

**URL:** <https://discourse.julialang.org/t/ann-setfield-jl-yet-another-package-for-working-with-immutables/9267>\
**Category:** General Usage\
**Tags:** package, announcement\
**Created:** [February 22, 2018, 10:26pm UTC](https://discourse.julialang.org/t/ann-setfield-jl-yet-another-package-for-working-with-immutables/9267 "2018-02-22T22:26:46Z")\
**Posts on this page:** 5\
**Page:** 3

<div class="post-metadata">

**Author:** ![jw3126](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jw3126/32/3086_2.png) [@jw3126](https://discourse.julialang.org/u/jw3126)\
**Post date:** [February 25, 2018, 1:04pm UTC](https://discourse.julialang.org/t/ann-setfield-jl-yet-another-package-for-working-with-immutables/9267/42 "2018-02-25T13:04:24Z")

</div>

Okay I was not suggesting to apply this manually to every type under the sun. That is indeed error prone and ugly and what not. Also I was not suggesting this constructor for human use in types with lots of fields.

I think most types should have 0-3 fields and no custom constructor at all. If I apply this pattern I usually use a macro.

You are right, we need a standard constructor for the machine, for packages like `Reconstructables.jl` and `Setfield.jl` to work.  
I think the positional constructor has one killer advantage. Its the default. This means it automatically works for most types. Especially useful for types defined in packages you don’t own.

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [February 26, 2018, 2:36am UTC](https://discourse.julialang.org/t/ann-setfield-jl-yet-another-package-for-working-with-immutables/9267/43 "2018-02-26T02:36:04Z")

</div>

I agree that the positional constructor has a huge advantage in that it is the (only) default at the moment. But keyworded constructor may have language support in the future as well:  
[https://github.com/JuliaLang/julia/issues/10146](https://github.com/JuliaLang/julia/issues/10146)

Anyway, now that constructor lookup can be customized via `Setfield.constructor_of`, I guess I can do whatever I want to do on top of Setfield.jl which is great!

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [February 26, 2018, 2:58am UTC](https://discourse.julialang.org/t/ann-setfield-jl-yet-another-package-for-working-with-immutables/9267/44 "2018-02-26T02:58:14Z")

</div>

I started liking lens-based approach! Now that lens can change type parameters, we have “differentiable lens”!

```julia
using ForwardDiff
using Parameters: @with_kw, @unpack
using Setfield: @lens, Lens, set, get
import Setfield

@with_kw struct Coordinate{X, Y, Z}
    x::X = 1.0
    y::Y = 1.0
    z::Z = 1.0
end

# Since set called via ForwardDiff would specify a dual number, we
# have to ignore type parameters:
Setfield.constructor_of(::Type{<: Coordinate}) = Coordinate

function f(c::Coordinate)
    @unpack x, y, z = c
    return x^2 + y^2 + z^2
end

derivative(f, at, wrt::Lens) =
    ForwardDiff.derivative(
        (x) -> f(set(wrt, at, x)),
        get(wrt, at))

@assert derivative(f, Coordinate(x=1.0), @lens _.x) ≈ 2
@assert derivative(f, Coordinate(x=2.0), @lens _.x) ≈ 4

```

This is actually super useful for building something like bifurcation analysis tool where you need a generic way to let user specify a few parameters in a differentiable manner.

---

<div class="post-metadata">

**Author:** ![jw3126](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jw3126/32/3086_2.png) [@jw3126](https://discourse.julialang.org/u/jw3126)\
**Post date:** [February 26, 2018, 8:22am UTC](https://discourse.julialang.org/t/ann-setfield-jl-yet-another-package-for-working-with-immutables/9267/45 "2018-02-26T08:22:11Z")

</div>

I had still doubts, that allowing to change the type was a good idea, but this example convinces me. Nice!

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [February 26, 2018, 8:32am UTC](https://discourse.julialang.org/t/ann-setfield-jl-yet-another-package-for-working-with-immutables/9267/46 "2018-02-26T08:32:18Z")

</div>

Glad that you like the example 🙂

[Previous page](https://discourse.julialang.org/t/ann-setfield-jl-yet-another-package-for-working-with-immutables/9267.md?page=2)
