I'm not exactly sure what I mean by "overloaded function", but I think you will understand. I'm looking for something that would allow me to write a function contract like
(magic-> [integer? integer? -> integer?]
[string? symbol? -> string?]
[string? ...+ -> string?])
The above contract would mean:
* If the function is given an argument list that satisfies (cons/c integer? (cons/c integer? null?)), then the return value must be an integer?
* Else if the function is given an argument list that satisfies (cons/c string? (cons/c symbol? null?)), then the return value must be a string?
* Else if the function is given an argument list that satisfies (cons/c string? (list/c string?)), then the return value must be a string?
* Else the caller is blamed for not providing correct arguments.
(I don't think I need support for keyword arguments)
Does this already exist in a library somewhere? If not, it doesn't look too hard for me to roll my own but I am (perhaps prematurely) concerned about the performance. Would the following approach be reasonable?
(define-syntax-rule (magic-> [dom ... range-expr] ...)
; We should make sure that every dom and range is a flat-contract?
(make-contract
#:name '(magic-> [dom ... range-expr] ...)
#:first-order procedure?
#:projection
(λ (blame)
(λ (proc)
(λ args
(cond
[((list/c dom ...) args)
(let ([range ((contract-projection range-expr) blame)])
(range (apply proc args)))]
...
[else
(raise-blame-error
(blame-swap blame) args
'(expected "a conforming argument list" given: "~e")
args)]))))))
(define/contract (blah a b)
(magic-> [integer? string? list?]
[string? integer? (list/c string? integer?)]
; This one will throw a contract violation
[integer? integer? integer?])
(list a b))