Created
November 8, 2012 14:28
-
-
Save greghendershott/4039102 to your computer and use it in GitHub Desktop.
Using make-keyword-procedure in a macro
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 | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
;; | |
;; Scenario 1: Plain function | |
;; | |
(define (def-proc ks) | |
;; Proc that takes a dict? | |
(define (f/dict d) | |
(displayln d)) | |
;; Wrap f/dict in a proc that takes keyword arguments, instead. | |
(define symbol->keyword (compose1 string->keyword symbol->string)) | |
(define keyword->symbol (compose1 string->symbol keyword->string)) | |
(define (keyword<=? a b) (string<=? (keyword->string a) (keyword->string b))) | |
(define f/kw (make-keyword-procedure | |
(lambda (kws vs . rest) | |
(f/dict (map cons | |
(map keyword->symbol kws) | |
vs))))) | |
f/kw) | |
(define foo (def-proc '(a b c))) | |
(foo #:a 1 #:b 2 #:c 3) | |
;; => | |
;; ((a . 1) (b . 2) (c . 3)) | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
;; | |
;; Scenario 2: Using a macro | |
;; | |
(begin-for-syntax | |
(define (def-proc ks) ;; This is EXACTLY the same as above | |
;; Proc that takes a dict? | |
(define (f/dict d) | |
(displayln d)) | |
;; Wrap f/dict in a proc that takes keyword arguments | |
(define symbol->keyword (compose1 string->keyword symbol->string)) | |
(define keyword->symbol (compose1 string->symbol keyword->string)) | |
(define (keyword<=? a b) (string<=? (keyword->string a) (keyword->string b))) | |
(define f/kw (make-keyword-procedure | |
(lambda (kws vs . rest) | |
(f/dict (map cons | |
(map keyword->symbol kws) | |
vs))))) | |
f/kw)) | |
(define-syntax (def stx) | |
(syntax-case stx () | |
[(_ name keys) | |
(let ([ks (syntax->list #'keys)]) | |
#`(begin | |
(define name #,(def-proc ks))))])) | |
(def foo2 '(a b c)) | |
(foo2 #:a 1 #:b 2 #:c 3) | |
;; => | |
;; application: procedure does not accept keyword arguments | |
;; procedure: ...t/private/kw.rkt:191:14 | |
;; given arguments: | |
;; #:a 1 | |
;; #:b 2 | |
;; #:c 3 | |
;; Huh ???? |
@samth what I ended up with is here: https://github.com/greghendershott/gapi/blob/c5e3e844c441623030c9af4307e3a03fa4321328/macro.rkt#L49
It works, but creating the syntax for a struct
literal seems much more complicated than I expected. I have the feeling I went down the wrong fork in the road.
(BTW the background for this is that I had a lot of nearly-duplicated code in GAPI lib for using it in a dynamic/runtime way vs. a compiled/macro way. I wanted to refactor it.)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks!
I'd intuited it had something to do with phases, but I was having a hard time seeing specifically how.
Ah right. That's actually a artifact of distilling it down to an example (my "real" def-proc did return syntax).