hash-view:   Struct-like Views of Hashes
1 Introduction to Hash Views
2 Hash Views
hash-view
hash-view-out
1.0

hash-view: Struct-like Views of Hashes🔗ℹ

Ryan Culpepper <ryanc@racket-lang.org>

 (require hash-view) package: hash-view-lib

This library provides a form for declaring a struct-like interface to hashes with symbol keys.

1 Introduction to Hash Views🔗ℹ

A hash view is declared like this:
> (hash-view point (x y))

This declares a constructor and match pattern point, a predicate point?, and accessors point-x and point-y.

Instances of points are represented by hashes with symbol keys:
> (point 1 2)

'#hasheq((x . 1) (y . 2))

> (point? (point 1 2))

#t

> (point? 12)

#f

All of the (required) fields must be present to satisfy the predicate. Additional keys are allowed and ignored.
> (point? (hasheq 'x 1))

#f

> (point? (hash 'x 1 'y 2 'z 3))

#t

The hash-view name also acts as a match pattern:
> (match (hasheq 'x 1 'y 2 'z 3)
    [(point x y) (+ x y)])

3

A hash-view declaration can include optional fields with default values. Fields declared with #:default are included by the constructor, but fields declared with #:default/omit are omitted when they have their default values.
> (hash-view location (host [port #:default 80] [proto #:default/omit 'tcp]))
> (location "racket-lang.org")

'#hasheq((host . "racket-lang.org") (port . 80))

> (location "racket-lang.org" 80 'tcp)

'#hasheq((host . "racket-lang.org") (port . 80))

> (location "docs.racket-lang.org" 443)

'#hasheq((host . "docs.racket-lang.org") (port . 443))

> (location "localhost" 20 'udp)

'#hasheq((host . "localhost") (port . 20) (proto . udp))

An optional field’s accessor normally returns the declared default if the field is missing:
> (location-port (hasheq 'host "racket-lang.org"))

80

> (match (hasheq 'host "racket-lang.org")
    [(location host port _) (format "~a:~a" host port)])

"racket-lang.org:80"

But if the accessor is given a second argument, that argument replaces the default failure argument to hash-ref:
> (location-port (hasheq 'host "racket-lang.org")
                 443)

443

> (location-port (hasheq 'host "racket-lang.org")
                 (lambda () (printf "port missing!\n")))

port missing!

2 Hash Views🔗ℹ

syntax

(hash-view view-id (field-decl ...) maybe-mutability)

 
field-decl = field-id
  | [field-id #:default default-expr]
  | [field-id #:default/omit default-expr]
     
maybe-mutability = 
  | #:immutable
  | #:accept-mutable
Similar to (struct view-id (field-id ...)), but represents view-id instances as hashes with symbol keys ('field-id).

Defines view-id as a constructor and match pattern, view-id? as a predicate, and the view-id-field-id identifiers as accessors.

The view-id constructor always creates immutable eq?-based hashes (hasheq), but the predicate and accessors also accept eqv?-based and equal?-based hashes (hasheqv and hash). The predicate and accessors accept hashes that have additional keys.

If a field has a default value, then it is an optional field: the predicate does not check for its presence. An accessor for an optional field takes an optional second argument that is used as the failure argument for the hash-ref call; if the second argument is omitted, the accessor returns the declared default value if the field is absent. If a field is optional and there is no required field after it, then the corresponding constructor argument is also optional. If the field is declared with #:default, the constructor always includes the field in the hash; if the default is declared with #:default/omit, the constructor omits the field when the corresponding argument is the same (equal?) to the default value.

If the #:immutable option is given, then the predicate and accessors accept only immutable hashes as instances of view-id. If the #:accept-mutable option is given, then the predicate and accessors accept both mutable and immutable hashes, and a make-mutable-view-id function is defined that creates mutable instances (using make-hasheq). If neither option is given, the behavior defaults to the #:accept-mutable behavior.

syntax

(hash-view-out hash-view-id)

Like struct-out but provides the identifiers associated with the given hash-view.