Purely Functional Struct Updaters
struct+  updaters-out

Purely Functional Struct Updaters

 (require struct-update) package: struct-update-lib

Racket encourages programming in a functional style, which in turn encourages immutability. When manipulating immutable data structures, it is important to be able to functionally update those data structures—that is, copy them with certain values replaced. Racket provides functions like hash-set and hash-update for functionally updating data structures, but while the struct form produces immutable structures by default, it does not define any similar updaters automatically.

This library provides a define-struct-updaters form to accomplish that task. For a built-in solution to the same problem, see struct-copy. For a more powerful solution (especially useful for updating nested data structures), consider the lens library.


(define-struct-updaters struct-id)

Given an identifier bound to a structure type transformer binding, generates functional setter and updater functions for each field of the struct.

Two functions are generated for each field. Their names are generated by appending -set and -update onto each of the accessor functions, and they are unhygienically bound using the lexical context of struct-id. Each setter function is protected by the contract (-> struct-id? any/c struct-id?), and each updater functions is protected by the contract (-> struct-id? (-> any/c any/c) struct-id?).

> (struct point (x y) #:transparent)
> (define-struct-updaters point)
> (point-x-set (point 1 2) 10)

(point 10 2)

> (point-y-update (point 1 2) add1)

(point 1 3)

If struct-id is a substruct of a parent struct, super-id, then it generates setters and updaters for the super fields as well. These are generated with the names struct-id-super-id-field-id-set and struct-id-super-id-field-id-update. These will functionally update the fields of the parent struct, but they will produce instances of struct-id instead of super-id.

> (struct object (mass position) #:transparent)
> (struct movable object (velocity) #:transparent)
> (define-struct-updaters object)
> (define-struct-updaters movable)
> (object-mass-set (object 5 (list 1 2)) 10)

(object 10 '(1 2))

> (object-mass-set (movable 5 (list 1 2) (list 0 0)) 10)

(object 10 '(1 2))

> (movable-velocity-set (movable 5 (list 1 2) (list 0 0)) (list -3 -4))

(movable 5 '(1 2) '(-3 -4))

> (movable-object-mass-set (movable 5 (list 1 2) (list 0 0)) 10)

(movable 10 '(1 2) '(0 0))


(struct-updaters-out struct-id)

A provide transformer that provides all of the bindings generated by define-struct-updaters.


(struct+updaters-out struct-id)

Like struct-updaters-out combined with struct-out, provides all of a structure type’s bindings, plus the bindings generated by define-struct-updaters.