On this page:
1.1 Comparison Predicate Generation
1.2 Struct Utilities
1.2.1 Purely Functional Struct Updaters
struct+  updaters-out
1.2.2 Extracting struct accessors
1.3 Wrapping keyword procedures
define/  wrapped

1 Untyped Utilities

1.1 Comparison Predicate Generation

 (require alexis/util/comparator) package: alexis-util

See also typed/alexis/util/comparator for Typed Racket-compatible forms.


(define-comparison-predicates predicate-base-id comparator-expr
maybe-adapter = 
  | #:adapter adapter-expr
This provides a convenient macro for generating comparison predicates based on a "comparator" function. The provided comparator-expr must evaluate to a function which takes two values and produces either 0, 1, or -1. These values correspond to both parameters being equal, the first parameter being greater, or the second parameter being greater, respectively.

Using this function, a set of functions is generated using predicate-base-id as a base identifer to determine the names of the resulting definitions. This macro produces six functions, their names acquired by appending =?, >?, <?, <>?, >=?, and <=? to predicate-base-id.

If adapter-expr is provided, then it must evaluate to a function that takes a single parameter and returns a single value. If specified, values will be threaded through adapter-expr before being passed to comparator-expr. This allows values to be mapped to other values before being provided to the comparator for additional processing or parsing.

> (struct num-str (num str))
> (define (num-str-compare a b)
    (if (= (num-str-num a) (num-str-num b))
        (let ([a (num-str-str a)]
              [b (num-str-str b)])
            [(string>? a b)  1]
            [(string<? a b) -1]
            [else            0]))
        (let ([a (num-str-num a)]
              [b (num-str-num b)])
            [(> a b)  1]
            [(< a b) -1]
            [else     0]))))
> (define-comparison-predicates num-str num-str-compare
    #:adapter (λ (p) (num-str (car p) (cdr p))))
> (num-str=? '(123 . "abc") '(123 . "abc"))


> (num-str<? '(200 . "aaa") '(100 . "aaa"))



(comparison-predicates-out maybe-renamed)

maybe-renamed = predicate-base-id
  | [original-base-id renamed-base-id]
This is a provide transformer that provides a convenient shorthand for providing predicates generated via define-comparison-predicates. Predicate suffixes are prepended the base identifiers in the same manner as in define-comparison-predicates. If renamed-base-id is provided, the generated provides use the renamed base identifier.

1.2 Struct Utilities

 (require alexis/util/struct) package: alexis-util

1.2.1 Purely Functional Struct Updaters

Racket provides hash-set and hash-update as purely functional ways to modify hashtables without mutation. This provides similar functionality for structures.


(define-struct-updaters struct-id)

Given the name of a struct via struct-id, this form generates functional setter and updater functions for each field of the struct. Functions are only generated for the non-inherited fields for the provided struct; a supertype’s fields are ignored.

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 introduced with the lexical context of struct-id. Each setter function is of the type (-> struct-id? any/c struct-id?). Each updater function is of the type (-> struct-id? (-> any/c any/c) struct-id?). The generated functions have contracts attached to them which ensure that the proper values are recieved.

> (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)


(struct-updaters-out struct-id)

This is a provide transformer that serves as a simple way to provide the setters and updaters generated via define-struct-updaters.


(struct+updaters-out struct-id)

This is a shorthand for providing both (struct-out struct-id) and (struct-updaters-out struct-id).

1.2.2 Extracting struct accessors

 (require (submod alexis/util/struct get-struct-accessors))


(get-struct-accessors struct-info 
(listof identifier?) (listof identifier?)
  struct-info : (and/c struct-info? list?)
  failure-context : syntax?
Extracts the fields belonging to a struct, not including its supertypes. The first value returned includes all accessors, the second value is just the struct’s fields.

This function is provided for-syntax.

1.3 Wrapping keyword procedures

 (require alexis/util/wrap) package: alexis-util

It’s easy to "wrap" existing procedures in order to extend them with additional functionality. For example, the following wraps + to additionally call add1 on the result:

(define (+/add1 . args)
  (add1 (apply + args)))

This is much harder to do, however, if the procedure being wrapped can accept keyword arguments, since they are not accepted in the "rest argument" syntax. Instead, make-keyword-procedure and keyword-apply must be used. This module provides some macros to make wrapping these procedures easier.


(wrap-keyword-procedure [result-id original-proc-expr]
  body-expr ...+)
  original-proc-expr : procedure?
Creates a new procedure that wraps original-proc-expr. Each application of the resulting procedure calls original-proc-expr with the provided arguments and binds result-id to the result, which is available to the body-exprs. The return value of the resulting procedure is the result of the final body-expr.

> (define check-duplicates+add1
    (wrap-keyword-procedure [v check-duplicates]
      (add1 v)))
> (check-duplicates+add1 #:key positive? '(1 1))



(define/wrapped name-id [result-id original-proc-expr]
  body-expr ...+)
  original-proc-expr : procedure?
An abbreviation for defining functions using wrap-keyword-procedure. Equivalent to:

(define name-id
  (wrap-keyword-procedure [result-id original-proc-expr]
    body ...))