{"size": 2242, "ext": "scrbl", "max_stars_repo_path": "scribblings/struct-set.scrbl", "max_stars_repo_name": "camoy/struct-set", "max_stars_repo_stars_event_min_datetime": "2021-11-10T21:56:51.000Z", "max_stars_repo_stars_event_max_datetime": "2021-11-10T21:56:51.000Z", "max_issues_repo_path": "scribblings/struct-set.scrbl", "max_issues_repo_name": "camoy/struct-set", "max_issues_repo_issues_event_min_datetime": null, "max_issues_repo_issues_event_max_datetime": null, "max_forks_repo_path": "scribblings/struct-set.scrbl", "max_forks_repo_name": "camoy/struct-set", "max_forks_repo_forks_event_min_datetime": null, "max_forks_repo_forks_event_max_datetime": null}
{"max_stars_count": 1, "max_issues_count": null, "max_forks_count": null, "avg_line_length": 30.7123287671, "max_line_length": 99, "alphanum_fraction": 0.6293487957}
#lang scribble/manual

@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@;; require

@require[@for-label[racket/base
                    struct-set]
         racket/sandbox
         scribble/example]

@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@;; example evaluator

@(define evaluator
   (make-base-eval
     '(require struct-set)))

@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@;; document

@title{Immutable Struct Updates}
@author{Cameron Moy}

@defmodule[struct-set]

@margin-note{
See @hyperlink[SO-POST]{this link} for an explanation of the behavior
of @racket[struct-copy].
}

This module defines helpers for immutably updating structs.
Notably, updating a struct using this package doesn't change its type
like @racket[struct-copy] does. Under the hood, it derives a generic method
for copying structs that is then dispatched to for updating.

@defform[(struct/set id maybe-super (field ...) struct-option ...)]{
  The same as @racket[struct], except the newly defined struct
  supports updating via @racket[struct-set].
}

@examples[#:eval evaluator
  (struct/set fruit (price))
  (struct/set apple fruit (oxidized?))
  (struct/set banana fruit (too-ripe?))]

@defform[(struct-set id struct-expr [fld-id expr] ...)]{
  The same as @racket[struct-copy], except it will
  return the same struct instance as @racket[struct-expr],
  which may not necessarily be the same as @racket[id].
}

@examples[#:eval evaluator
  (define old-apple (apple 1.50 #t))
  (define new-apple (struct-set fruit old-apple [price 1.00]))
  (fruit-price new-apple)
  (apple-oxidized? new-apple)]


@defform[(struct-update id struct-expr [fld-id update-expr] ...)]{
  Like @racket[struct-set], except it will apply the result
  of @racket[update-expr] to the old value of the field
  to yield the new value.
}

@examples[#:eval evaluator
  (define cheap-apple (struct-update fruit old-apple [price sub1]))
  (fruit-price cheap-apple)
  (apple-oxidized? cheap-apple)]

@(define SO-POST
  (string-append "https://stackoverflow.com/questions/52142731/"
                 "how-do-you-get-struct-copy-to-create-a-struct-of-the-same-type-as-the-original"))
