Add syntax for defining pseudovariadic functions.
This commit is contained in:
parent
8b838c0b22
commit
8fb5bab803
2 changed files with 76 additions and 0 deletions
|
@ -15,6 +15,7 @@
|
||||||
(for-syntax syntax/parse))
|
(for-syntax syntax/parse))
|
||||||
|
|
||||||
(provide
|
(provide
|
||||||
|
pseudovariadic-lambda pvλ pseudovariadic-define pvdefine
|
||||||
tabulate* tabulate*/strict tabulate tabulate/strict)
|
tabulate* tabulate*/strict tabulate tabulate/strict)
|
||||||
|
|
||||||
(unsafe-provide
|
(unsafe-provide
|
||||||
|
@ -24,6 +25,57 @@
|
||||||
(module+ test
|
(module+ test
|
||||||
(require typed/rackunit))
|
(require typed/rackunit))
|
||||||
|
|
||||||
|
(begin-for-syntax
|
||||||
|
(require racket (for-syntax syntax/parse))
|
||||||
|
|
||||||
|
(define (make-pseudovariadic-core args bodies tag-stx)
|
||||||
|
(define nargs-stx (datum->syntax args (length (syntax->list args))))
|
||||||
|
#`(λ xs
|
||||||
|
(match xs
|
||||||
|
[(list #,@args) #,@bodies]
|
||||||
|
[_ (error #,tag-stx "invalid arity, expected ~a argument(s)" #,nargs-stx)])))
|
||||||
|
|
||||||
|
(define (make-pseudovariadic-lambda stx)
|
||||||
|
(syntax-parse stx
|
||||||
|
[(_ (args:id ...) bodies:expr ...)
|
||||||
|
(make-pseudovariadic-core #'(args ...)
|
||||||
|
#'(bodies ...)
|
||||||
|
(datum->syntax stx ''pseudovariadic-lambda))]))
|
||||||
|
|
||||||
|
(define (make-pseudovariadic-define stx)
|
||||||
|
(syntax-parse stx
|
||||||
|
[(_ (name:id args:id ...) bodies:expr ...)
|
||||||
|
#`(define name
|
||||||
|
#,(make-pseudovariadic-core
|
||||||
|
#'(args ...)
|
||||||
|
#'(bodies ...)
|
||||||
|
(datum->syntax #'name `(quote ,(syntax->datum #'name)))))])))
|
||||||
|
|
||||||
|
(define-syntax (pseudovariadic-lambda stx) (make-pseudovariadic-lambda stx))
|
||||||
|
(define-syntax (pvλ stx) (make-pseudovariadic-lambda stx))
|
||||||
|
|
||||||
|
(module+ test
|
||||||
|
(test-case "pseudovariadic-lambda")
|
||||||
|
(check-false ((pseudovariadic-lambda (x y) (and x y)) #t #f))
|
||||||
|
(check-false ((pvλ (x y) (and x y)) #t #f))
|
||||||
|
(check-exn exn:fail? (λ () ((pseudovariadic-lambda (x y) (and x y)) #t #f #f)))
|
||||||
|
(check-exn exn:fail? (λ () ((pvλ (x y) (and x y)) #t #f #f))))
|
||||||
|
|
||||||
|
(define-syntax (pseudovariadic-define stx) (make-pseudovariadic-define stx))
|
||||||
|
(define-syntax (pvdefine stx) (make-pseudovariadic-define stx))
|
||||||
|
|
||||||
|
(module+ test
|
||||||
|
(test-case "pseudovariadic-define")
|
||||||
|
(: f (-> Boolean * Boolean))
|
||||||
|
(pseudovariadic-define (f x y) (and x y))
|
||||||
|
(check-false (f #t #f))
|
||||||
|
(check-exn exn:fail? (λ () (f #t #f #f)))
|
||||||
|
|
||||||
|
(: g (-> Boolean * Boolean))
|
||||||
|
(pvdefine (g x y) (and x y))
|
||||||
|
(check-false (g #t #f))
|
||||||
|
(check-exn exn:fail? (λ () (g #t #f #f))))
|
||||||
|
|
||||||
(define-syntax (make-tabulate* stx)
|
(define-syntax (make-tabulate* stx)
|
||||||
(syntax-parse stx
|
(syntax-parse stx
|
||||||
[(_ name:id row-op)
|
[(_ name:id row-op)
|
||||||
|
@ -81,6 +133,7 @@
|
||||||
|
|
||||||
(require 'typed)
|
(require 'typed)
|
||||||
(provide
|
(provide
|
||||||
|
pseudovariadic-lambda pvλ pseudovariadic-define pvdefine
|
||||||
tabulate* tabulate*/strict tabulate*/untyped tabulate tabulate/strict
|
tabulate* tabulate*/strict tabulate*/untyped tabulate tabulate/strict
|
||||||
tabulate/untyped)
|
tabulate/untyped)
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,29 @@ when they receive a number of arguments different from a given constant value.
|
||||||
Such functions are called @italic{pseudovariadic functions} in
|
Such functions are called @italic{pseudovariadic functions} in
|
||||||
this documentation.
|
this documentation.
|
||||||
|
|
||||||
|
@deftogether[(@defform[(pseudovariadic-lambda (id ...+) body ...+)]
|
||||||
|
@defform[(pvλ (id ...+) body ...+)])]{
|
||||||
|
|
||||||
|
Define a pseudovariadic anonymous function.
|
||||||
|
|
||||||
|
@examples[#:eval functions-evaluator
|
||||||
|
(: f (-> Boolean * Boolean))
|
||||||
|
(define f (pseudovariadic-lambda (x y) (and x y)))
|
||||||
|
(f #t #f)
|
||||||
|
(eval:error (f #t #f #t))
|
||||||
|
]}
|
||||||
|
|
||||||
|
@deftogether[(@defform[(pseudovariadic-define (name id ...+) body ...+)]
|
||||||
|
@defform[(pvdefine (id ...+) body ...+)])]{
|
||||||
|
|
||||||
|
Define a pseudovariadic function called @racket[name].
|
||||||
|
|
||||||
|
@examples[#:eval functions-evaluator
|
||||||
|
(: g (-> Boolean * Boolean))
|
||||||
|
(pseudovariadic-define (g x y) (and x y))
|
||||||
|
(g #t #f)
|
||||||
|
(eval:error (g #t #f #t))
|
||||||
|
]}
|
||||||
@section[#:tag "tabulating"]{Tabulating functions}
|
@section[#:tag "tabulating"]{Tabulating functions}
|
||||||
|
|
||||||
@defproc[(tabulate [func (-> a ... b)]
|
@defproc[(tabulate [func (-> a ... b)]
|
||||||
|
|
Loading…
Reference in a new issue