Last active
July 6, 2020 15:42
-
-
Save aumouvantsillage/22b96f2b41f7a849ee21dfebde28ae0d to your computer and use it in GitHub Desktop.
Syntactic sugar to access Racket struct fields without prefixing them with the struct type name.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#lang racket | |
(require | |
syntax/parse/define | |
(for-syntax racket/syntax)) | |
; Define an instance of a structure: | |
; - name: the name of the instance | |
; - sname: the name of the struct type | |
; - arg ...: the arguments for the struct type constructor | |
; | |
; This will create a macro that provides access to the instance and its fields: | |
; - (name) returns the struct instance | |
; - (name fname) returns the value of the field fname in the instance | |
; - (name fname ...) returns as many values as field names | |
(define-simple-macro (define-instance name:id (sname:id arg ...)) | |
(begin | |
; Create a hidden instance of the struct type. | |
(define inst (sname arg ...)) | |
; Create a macro with the given instance name | |
(define-syntax-parser name | |
; With no argument, return the instance. | |
[(_) | |
#'inst] | |
; With one argument, call the accessor for the given field name. | |
[(_ fname:id) | |
#:with acc (format-id #'fname #:source #'fname "~a-~a" #'sname #'fname) | |
#'(acc inst)] | |
; With more than one argument, expand this macro for each field name. | |
[(_ fname:id (... ...)) | |
#'(values (name fname) (... ...))]))) | |
; Example: a 2D point type. | |
(struct point (x y) #:transparent) | |
(define-instance p (point 10 20)) | |
; Print p and its fields. | |
(printf "p=~a~np.x=~a~np.y=~a~n" (p) (p x) (p y)) | |
; Get both fields in the same expression. | |
(define-values (x y) (p x y)) | |
(printf "x=~a~ny=~a~n" x y) | |
; Accessing an undefined field generates a syntax error with appropriate location. | |
; (printf "p.z=~a~n" (p z)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment