ruricolist / serapeum

Utilities beyond Alexandria
MIT License
415 stars 41 forks source link

Consider constraining return types in -> #160

Closed ruricolist closed 8 months ago

ruricolist commented 9 months ago

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:

(-> myfun (t) t)
(-> myfun (t) (values t &optional))

(-> myfun (t) (values t t))
(-> myfun (t) (values t t &optional))

;; Unchanged
(-> myfun (t) (values t t &rest t))
(-> myfun (t) (values t t &rest t))

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:

;; This function takes a binary function and returns a unary function.
(-> ((-> (t t) t)) (-> (t) t))

But I suspect this is uncommon.

ruricolist commented 9 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.

ruricolist commented 9 months ago

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.

ruricolist commented 9 months ago
(-> 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.

ruricolist commented 8 months ago

A "con": SBCL wil tell you to consider declaring functions with (values ... &optional). So people would end up using the old syntax anyway.