Racket: Macro's
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/base | |
(require (for-syntax racket/base)) | |
; Reading Quotes | |
; see: https://docs.racket-lang.org/reference/reader.html | |
; ' quote #' syntax | |
; ` quasiquote #` quasisyntax | |
; , unquote #, unsyntax | |
; ,@ unquote-splicing #,@ unsyntax-splicing | |
; simple literal | |
(define stx0a (syntax (if #t "yes" "no"))) | |
(define stx0b #'(if #t "yes" "no")) | |
; (println (list stx0a stx0b)) | |
; quasisyntax + unsyntax | |
(define stx1 (syntax 42)) | |
(define stx1a | |
(quasisyntax (define answer (unsyntax stx1)))) | |
(define stx1b | |
#`(define answer #,stx1)) | |
; (println (list stx1a stx1b)) | |
; unsyntax-splicing | |
(define stx2 (list (syntax 1300) (syntax 37))) | |
(define stx2a | |
(quasisyntax (sum (unsyntax-splicing stx2)))) | |
(define stx2b | |
#`(sum #,@stx2)) | |
; (println (list stx2a stx2b)) | |
; discards metadata from nested syntax | |
(define datum (syntax->datum (syntax (if #t "yes" "no")))) | |
; specifying #f to create syntax without metadata | |
(define stx (datum->syntax #f (quote (if #t "yes" "no")))) | |
; running arbitrary code at compile time | |
(begin-for-syntax | |
(println "compile time!")) | |
; defining functions for use at compile time | |
(define-for-syntax (macro-helper stx) | |
stx) |
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/base | |
(require (for-syntax racket/base)) | |
(define-syntax (when stx) | |
(let ([condition (cadr (syntax-e stx))] | |
[body (cddr (syntax-e stx))]) | |
#`(if #,condition | |
(begin #,@body) | |
(void)))) | |
; (when (> 1300 37) (display "1300 is greater than ") (displayln "37")) | |
(define-syntax (unless stx) | |
(let ([condition (cadr (syntax-e stx))] | |
[body (cddr (syntax-e stx))]) | |
#`(when (not #,condition) | |
#,@body))) | |
; (unless (> 3.14 42) (display "42 is greater than ") (displayln "3.14")) | |
(define-syntax (while stx) | |
(let ([condition (cadr (syntax-e stx))] | |
[body (cddr (syntax-e stx))]) | |
#`(let while ([last-result (void)]) | |
(cond | |
[#,condition | |
(while (begin #,@body))] | |
[else | |
last-result])))) | |
; (define y 1) (while (< y 9) (println y) (set! y (add1 y)) y) | |
(define-syntax (until stx) | |
(let ([condition (cadr (syntax-e stx))] | |
[body (cddr (syntax-e stx))]) | |
#`(while (not #,condition) | |
#,@body))) | |
; (define x -9) (until (zero? x) (println x) (set! x (add1 x)) x) |
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/base | |
(require (for-syntax racket/base | |
racket/match)) | |
; | |
; define-syntax + match | |
; | |
(define-syntax (if/v0 stx) | |
(match (syntax->list stx) | |
[(list _ condition true-expr false-expr) | |
(datum->syntax stx `(cond [,condition ,true-expr] | |
[else ,false-expr]))])) | |
; (println (if/v0 #t "yes" "no")) | |
; | |
; define-syntax + syntax-case | |
; syntax-case matches a pattern to a syntax object | |
; (no quasi-quoting and unquoting because it's using pattern variables) | |
; (syntax-case <id> () [<pattern> <body>]) | |
; | |
(define-syntax (if/v1 stx) | |
(syntax-case stx () | |
[(_ condition true-expr false-expr) | |
#'(cond [condition true-expr] | |
[else false-expr])])) | |
; (println (if/v1 #t "yes" "no")) | |
(define-syntax (while/v1 stx) | |
(syntax-case stx () | |
[(_ condition body ...) | |
#'(let _while ([last-result (void)]) | |
(cond | |
[condition (_while (begin body ...))] | |
[else last-result]))])) | |
; (define y1 0) (while/v1 (< y1 9) (println y1) (set! y1 (add1 y1)) y1) | |
; | |
; define-syntax + syntax-rules | |
; | |
(define-syntax when/v2 | |
(syntax-rules () | |
[(_ condition body ...) | |
(if condition (begin body ...))])) | |
; (when (> 1300 37) (display "answer: ") 42) | |
; | |
; define-syntax + with-syntax | |
; with-syntax matches and binds all patterns to pattern variables in the body | |
; (with-syntax ([<pattern> <syntax>] ...) <body> ...+) | |
; | |
(define-syntax (until/v3 stx) | |
(with-syntax ([(_ condition body ...) stx]) | |
#'(while/v1 (not condition) body ...))) | |
; (define y3 8) (until/v3 (zero? y3) (println y3) (set! y3 (sub1 y3)) y3) | |
; | |
; define-syntax-rule | |
; (just a shorthand for define-syntax + syntax-case) | |
; | |
(define-syntax-rule (if/v4 condition true-expr false-expr) | |
(cond [condition true-expr] | |
[else false-expr])) | |
; (println (if/v4 #t "yes" "no")) | |
(define-syntax-rule (until/v4 condition body ...) | |
(while/v1 (not condition) body ...)) | |
; (define y4 8) (until/v4 (zero? y4) (println y4) (set! y4 (sub1 y4)) y4) |
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/base | |
(require (for-syntax racket/base) | |
racket/stxparam) | |
(define-syntax-parameter it | |
(lambda (stx) | |
(raise-syntax-error (syntax-e stx) "can only be used inside aif"))) | |
(define-syntax-rule (aif condition true-expr false-expr) | |
(let ([tmp condition]) | |
(if tmp | |
(syntax-parameterize ([it (make-rename-transformer #'tmp)]) | |
true-expr) | |
false-expr))) | |
; (aif ((λ () (+ 1300 37))) (println it) #f) |
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/base | |
(require (for-syntax racket/base | |
syntax/parse)) | |
(define-syntax (when stx) | |
(syntax-parse stx | |
[(_ condition body ...) | |
#'(if condition | |
(begin body ...) | |
(void))])) | |
; (when (> 1300 37) (display "1300 is greater than ") (displayln "37")) | |
(define-syntax (while stx) | |
(syntax-parse stx | |
[(_ condition body ...) | |
#'(let while ([last-result (void)]) | |
(cond | |
[condition | |
(while (begin body ...))] | |
[else | |
last-result]))])) | |
; (define x 1) (while (< x 9) (println x) (set! x (add1 x)) x) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment