I ran into this toy example recently that has me a bit confused. Suppose I define a simple variable-arity function as below. Then, we are totally within our rights to run this both on one argument and on two.
(define (my-func . a) a)
(my-func 1) ; evals to '(1)
(my-func 1 2) ; evals to '(1 2)
The weird bit I've run into is if I try to pass it multiple arguments in one go using values
as below:
(my-func (values 1 2))
I'd expect this to evaluate to the same thing as (my-func 1 2)
, but instead throws an arity-mismatch error, namely that it expected 1 argument but got 2.
Why is it expecting one argument if my-func
is variable-arity? Does this have to do with the number of syntactic objects as arguments or is it something else?
In Racket, values
construct multiple return values (often abbrev. as multiple values or values). Except the case where it's a single value, values cannot be passed as argument(s). Values can't be kept in a variable. Values are mostly useful when returned from a function, and when used in forms like define-values
, etc. See this section of the Racket Reference for more details.
To use the terminology from the above link, (my-func [])
is a continuation that only accepts a single value. That's why in your program, it errors with the message "expects one, got two".
What you are trying to do can be accomplished with call-with-values
:
(call-with-values (lambda () (values 1 2)) my-func)