
Keyword functions are a little tricky. This PR addresses issues checking the body of kw functions. Basically, a function with keyword arguments such as inc: (define (inc x #:n [n 1]) (+ x n)) actually expands into a more complex function with 3 arguments that looks something resembling the following: (define (inc-expanded n* n-given? x) (let ([n (if n-given? n* 1)]) (+ x n))) and calls to inc are converted to match this form: (inc 42) => (inc-expanded #f #f 42) (inc 42 #:n 2) => (inc-expanded 2 #t 42) Note that each optional keyword argument has a boolean flag argument that signals whether or not the caller provided that keyword argument. This PR takes advantage of the observation that the value for the n* argument in inc is only reachable in code when n-given? is #t, and so, assuming the kw-expansion protocol always only accesses n* if n-given? is #t, we can actually safely check the body of the function against the following simple but correct type: (-> Number Boolean Number Number) An alternative previous approach expanded the function type into every possible combination of optional argument and optional argument flag, but this was prohibitively expensive.
6 lines
141 B
Racket
6 lines
141 B
Racket
#lang typed/racket
|
|
|
|
(: f (Number [#:y Boolean] -> Number))
|
|
(define (f x #:y [y #f] #:z [z 'this-can-be-anything])
|
|
(if y "y is truthy" x))
|