Skip to content

Instantly share code, notes, and snippets.

@cky
Last active June 21, 2022 02:25
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save cky/8500450 to your computer and use it in GitHub Desktop.
Save cky/8500450 to your computer and use it in GitHub Desktop.
Guile implementation of Clojure's `#(...)` reader macro, but using `##(...)` instead to avoid conflicting with vectors.
(use-srfis '(1 69))
(read-hash-extend #\#
(lambda (c port)
(define ht (make-hash-table eqv?))
(define (ht-ref key)
(hash-table-ref ht key (lambda ()
(define sym (gensym))
(hash-table-set! ht key sym)
sym)))
(define (hash-key x)
(case x
((% %1) 1)
((%2) 2)
((%3) 3)
((%&) 0)
((#{}#) #f)
(else (and (symbol? x)
(symbol-interned? x)
(let ((str (symbol->string x)))
(and (char=? #\% (string-ref str 0))
(char<=? #\1 (string-ref str 1) #\9)
(string->number (substring/shared str 1))))))))
(define (process x)
(cond ((hash-key x) => ht-ref)
((list? x) (map process x))
(else x)))
(define body (process (read port)))
(define max-arg (apply max 0 (hash-table-keys ht)))
(define lambda-list (list-tabulate max-arg (compose ht-ref 1+)))
`(lambda (,@lambda-list . ,(hash-table-ref/default ht 0 '()))
,body)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment