Macro
Make a sequence of definitions - similar to let*.
(define-syntax-parser define*
[(_ (~or [id:id expr:expr]
[(idv:id ...+) expr:expr]) ...+)
#'(begin
(~? (define id expr)
(define-values (idv ...) expr)) ...)])
Example
(define*
[x 4]
[y 18]
[(quot rem) (quotient/remainder x y)])
quot rem
; -> 0
; -> 4
Definitions are automatically dispatched either to define or define-values depending on the manner in which identifiers are supplied (define-values is used if the identifiers are contained within a set of parenthesis)
Before and After
This macro saves a lot of unneccesary code when laying out a sequence of definitions
(define-values (pos1-x pos1-y) (values 14 32))
(define-values (pos2-x pos2-y) (values -24 5))
(define-values (x-diff y-diff) (values (- pos2-x pos1-x) (- pos2-y pos1-y)))
(define sqr (curryr expt 2))
(define distance (sqrt (+ (sqr x-diff) (sqr y-diff))))
;; Would become...
(define*
[(pos1-x pos1-y) (values 14 32)]
[(pos2-x pos2-y) (values -24 5)]
[(x-diff y-diff) (values (- pos2-x pos1-x) (- pos2-y pos1-y))]
[sqr (curryr expt 2)]
[distance (sqrt (+ (sqr x-diff) (sqr y-diff)))])
;; Which is much less visually noisy
Inner workings
The macro works by accepting either type of clause (single or multiple values)
(~or [id:id expr:expr]
[(idv:id ...+) expr:expr]) ...+
Resulting in a sequence of patterns, each of which bind either id or a list of idv - as well as expr
The macro then uses the ~? fallthrough syntax to choose which syntax to produce in response.
(~? (define id expr)
(define-values (idv ...) expr)) ...
If id is not bound then the syntax containing idv will be produced instead.
The ellipsis syntax then repeats this for the whole list of patterns.
Previous iterations
I've unearthed an older version of this macro, which made use of recursive expansion
(define-syntax-parser define*
[(_ (id:id expr:expr) next ...+)
#'(begin
(define id expr)
(define* next ...))]
[(_ (id:id expr:expr))
#'(define id expr)])
Of course this macro does not support definitions that bind multiple identifiers at once - although it does handily demonstrate recursive macros.
Licence
Please confirm that you are submitting this code under the same MIT License that the Racket language uses. https://github.com/racket/racket/blob/master/racket/src/LICENSE-MIT.txt
Please confirm that the associated text is licensed under the Creative Commons Attribution 4.0 International License http://creativecommons.org/licenses/by/4.0/
I confirm that the code is under the same license as the Racket language, and associated text is under Creative Commons Attribution 4.0 International License
Contact
I've already submit a macro, but I'd like to continue contributing to this resource!
Macro
Make a sequence of definitions - similar to let*.
Example
Definitions are automatically dispatched either to
defineordefine-valuesdepending on the manner in which identifiers are supplied (define-valuesis used if the identifiers are contained within a set of parenthesis)Before and After
This macro saves a lot of unneccesary code when laying out a sequence of definitions
Inner workings
The macro works by accepting either type of clause (single or multiple values)
(~or [id:id expr:expr] [(idv:id ...+) expr:expr]) ...+Resulting in a sequence of patterns, each of which bind either
idor a list ofidv- as well asexprThe macro then uses the
~?fallthrough syntax to choose which syntax to produce in response.If
idis not bound then the syntax containingidvwill be produced instead.The ellipsis syntax then repeats this for the whole list of patterns.
Previous iterations
I've unearthed an older version of this macro, which made use of recursive expansion
Of course this macro does not support definitions that bind multiple identifiers at once - although it does handily demonstrate recursive macros.
Licence
I confirm that the code is under the same license as the Racket language, and associated text is under Creative Commons Attribution 4.0 International License
Contact
I've already submit a macro, but I'd like to continue contributing to this resource!