Closed ruricolist closed 8 months ago
The safest way to do this would be to introduce a new syntax. One possibility is another arrow:
(-> myfun (t) -> t)
(-> myfun (t) -> (values t &optional))
(-> myfun (t) -> (values t t))
(-> myfun (t) -> (values t t &optional))
That still looks like a function signature, although the extra arrow isn't doing what it does in an ML.
Another is just making variadic signatures imply an exact number of arguments:
(-> myfun (t) t t)
(-> myfun (t) (values t t &optional))
That’s nice for multiple values, but doesn’t help with returning one value, which is the more common case.
If you had a variadic version that allowed values
as the first entry, you could do:
(-> myfun (t) . (values t))
(-> myfun (t) . (values t t))
Which looks like a specialized syntax, but isn't.
(-> myfun (t) -> t)
(-> myfun (t) -> t t)
(-> myfun (t) -> t t t)
(declare (ftype (-> (t) -> t t t) myfun))
Clean, but not having `values' in the signature decreases greppability.
A "con": SBCL wil tell you to consider declaring functions with (values ... &optional)
. So people would end up using the old syntax anyway.
It would be more ergonomic and more elegant (especially on SBCL) if
->
(the type and the macro) implicitly constrained the return type of a function to exactly the number of values declared.This change is made on the constrain-return-types branch. On that branch, the following pairs are equivalent:
But this would be a breaking change. I'm experimenting to quantify the impact. So far the only effects I've seen are when
->
is used for parameter types, like:But I suspect this is uncommon.