[racket] hack: implicit function arguments
I came up with this little hack that lets you avoid giving an explicit
argument list to functions. Arguments are discovered by usages of
underscores followed by a number, like _1 and _2. Partly inspired by
scala; sure to make your blood boil if you love hygiene.
;;; usage
(define/implicit foo1 (printf "~a ~a ~a\n" _8 _9 _8))
(foo1 5 12)
;;; code
#lang racket/base
(require (for-syntax racket/base
racket/list
syntax/parse
)
racket/stxparam)
(define-syntax-rule (implicits all thing ...)
(begin
(define-syntax-parameter thing (lambda (stx)
(raise-syntax-error #f (format "~a
can only be used in a
define/implicit function" 'thing))))
...
(provide thing ...)
(define-for-syntax all (list #'thing ...))))
(implicits all-implicits _1 _2 _3 _4 _5 _6 _7 _8 _9 _10)
(provide define/implicit lambda/implicit)
(define-syntax (lambda/implicit stx)
(define (find-implicits stx)
(define-syntax-class implicit
[pattern x:identifier
#:when (ormap (lambda (y)
(free-identifier=? y
#'x))
all-implicits)])
(remove-duplicates
(filter values
(syntax-parse stx
[x:implicit (list #'x)]
[(x ...) (apply append (map find-implicits
(syntax->list #'(x ...))))]
[else (list #f)]))
free-identifier=?))
(syntax-parse stx
[(_ body ...)
(define implicit-arguments (find-implicits stx))
(with-syntax ([(new-arg ...) (generate-temporaries
implicit-arguments)]
[(implicit ...) implicit-arguments])
#'(lambda (new-arg ...)
(syntax-parameterize ([implicit (make-rename-transformer
#'new-arg)] ...)
body ...)))]))
(define-syntax-rule (define/implicit name body ...)
(define name (lambda/implicit body ...)))