Suppose I have a struct with many fields:
(struct my-struct (f1 f2 f3 f4))
If I am to return a new struct with f2
updated, I have
Alexis's macro is fantastic, and Greg's rightly pointed out struct-copy
and match+struct*
, but since you specifically mentioned lenses in your example I'll point out that there is now a lens package for Racket (disclaimer: I wrote a lot of it). It provides struct/lens
and define-struct-lenses
macros for your use case:
> (struct/lens foo (a b c))
> (lens-view foo-a-lens (foo 1 2 3))
1
> (lens-set foo-a-lens (foo 1 2 3) 'a)
(foo 'a 2 3)
> (lens-transform foo-a-lens (foo 1 2 3) number->string)
(foo "1" 2 3)
define-struct-lenses
lets you define the lenses seperately from the structs:
> (struct foo (a b c))
> (define-struct-lenses foo)
The above is equivalent to (struct/lens foo (a b c))
. If you're only operating on structs in isolation from other kinds of structs, using define-struct-updaters
is simpler. But if you have a lot of nested data structures of various flavors, the ability to compose lenses makes them a powerful tool for the job.