Streamline and simplify auto-hash-ref/:.
This commit is contained in:
parent
fa015870d0
commit
3918730e1a
1 changed files with 20 additions and 31 deletions
51
utils.rkt
51
utils.rkt
|
@ -67,15 +67,28 @@
|
||||||
(and (not a) b))
|
(and (not a) b))
|
||||||
#f)))
|
#f)))
|
||||||
|
|
||||||
|
;;; Helper functions for auto-hash-ref/:.
|
||||||
|
(begin-for-syntax
|
||||||
|
(define (colon? s)
|
||||||
|
(and (symbol? s)
|
||||||
|
(eq? (string-ref (symbol->string s) 0) #\:)))
|
||||||
|
(define (collect-colons datum)
|
||||||
|
(cond [(colon? datum) (list datum)]
|
||||||
|
[(list? datum)
|
||||||
|
(remove-duplicates (flatten (for/list ([el (in-list datum)])
|
||||||
|
(collect-colons el))))]
|
||||||
|
[else '()]))
|
||||||
|
(define (strip-colon s)
|
||||||
|
(string->symbol (substring (symbol->string s) 1))))
|
||||||
|
|
||||||
(define-syntax (auto-hash-ref/: stx)
|
(define-syntax (auto-hash-ref/: stx)
|
||||||
(syntax-parse stx
|
(syntax-parse stx
|
||||||
[(_ ht:id body)
|
[(_ ht:id body:expr)
|
||||||
(let* ([names/: (collect-colons (syntax->datum #'body))])
|
(define colons (collect-colons (syntax->datum stx)))
|
||||||
#`(let #,(for/list ([x names/:])
|
(define bindings (for/list ([key colons])
|
||||||
;; put x in the same context as body
|
`[,key (hash-ref ,#'ht ',(strip-colon key))]))
|
||||||
#`[#,(datum->syntax #'body x)
|
(with-syntax ([bindings-stx (datum->syntax stx bindings)])
|
||||||
(hash-ref ht '#,(strip-colon x))])
|
#'(let bindings-stx body))]))
|
||||||
body))]))
|
|
||||||
|
|
||||||
(module+ test
|
(module+ test
|
||||||
(test-case "auto-hash-ref/:"
|
(test-case "auto-hash-ref/:"
|
||||||
|
@ -88,30 +101,6 @@
|
||||||
(check-equal? (auto-hash-ref/: ht2 (+ :a (* 2 :b)))
|
(check-equal? (auto-hash-ref/: ht2 (+ :a (* 2 :b)))
|
||||||
5)))
|
5)))
|
||||||
|
|
||||||
;;; The helper functions for auto-hash-ref/:.
|
|
||||||
(begin-for-syntax
|
|
||||||
;; Collect all the symbols starting with a colon in datum.
|
|
||||||
(define (collect-colons datum)
|
|
||||||
(remove-duplicates
|
|
||||||
(flatten
|
|
||||||
(for/list ([token datum])
|
|
||||||
(cond
|
|
||||||
[(symbol? token)
|
|
||||||
(let ([name (symbol->string token)])
|
|
||||||
(if (eq? #\: (string-ref name 0))
|
|
||||||
token
|
|
||||||
'()))]
|
|
||||||
[(list? token)
|
|
||||||
(collect-colons token)]
|
|
||||||
[else '()])))))
|
|
||||||
|
|
||||||
;; Strip the leading colon off x.
|
|
||||||
(define (strip-colon x)
|
|
||||||
(let ([x-str (symbol->string x)])
|
|
||||||
(if (eq? #\: (string-ref x-str 0))
|
|
||||||
(string->symbol (substring x-str 1))
|
|
||||||
x))))
|
|
||||||
|
|
||||||
(: extract-symbols (-> Any (Listof Symbol)))
|
(: extract-symbols (-> Any (Listof Symbol)))
|
||||||
(define (extract-symbols form)
|
(define (extract-symbols form)
|
||||||
(: extract-rec (-> Any (Listof Any)))
|
(: extract-rec (-> Any (Listof Any)))
|
||||||
|
|
Loading…
Reference in a new issue