Re: SRFI 283: (Type-)Check Introspection Artyom Bologov 17 Sep 2026 16:20 UTC

Hi Peter,

> check-of: "Returns the most exact check matching the value, as a
> procedure that this value must satisfy."
>
> I think this procedure is a bit too open-ended to be portably useful:
> `(λ (x) (eq? obj x))` would be a valid return value for any object,
> although it is not very useful.
>
> I would suggest fixing a set of portable return values that this
> procedure will return for standard objects:
>
> 1. list? if the object is a (finite) list
> 2. pair? null? vector? string? boolean? char? bytevector? if the
> object is one of those types
> 3. The most precise combination of exact?/inexact? and
> number?/complex?/real?/rational?/integer? for number types
> 4. The record predicate for an inspectable record type (R6RS/SRFI
> 99/CLOS-like/whatever)

I went with “the most exact check” and didn’t specify it further because
specifying it would be too restrictive. Implementors are free to
interpret the language in whatever sense their aesthetic feelings
suggest, and I trust them in their choices. (eq? obj x) would be
outrageous though, and I doubt anyone would do that.

But I realize your concern here. I might drop the “most exact” language
and suggest returning standard predicates whenever possible. I think
that this might defeat the point of strongly optimizing implementations,
but will give us much more portability. How does that sound?

> procedure-type-of: "Returns an implementation-specific number of
> implementation-specific values"
>
> This seems pretty unwieldy to use, because it is very difficult to
> bind values to it. The only portable way to use it would be
>
>     (let-values ((v (procedure-type-of proc)))
>       ...)
>
> It should return a fixed number of implementation-specific values.

Indeed. I’m leaning ever more strongly towards returning

(values (or pair? #f) (or list? #f))

in procedure-type-of. That’d be most consistent and logical.

> As-is, the type operations are too unspecific to be of portable
> value. Some reasonable things to specify are what it means for two
> types to be eqv?, and to specify a type->check procedure to derive a
> check from a type object. Maybe also procedures to do
> meta-introspection on type objects.

As I responded to Arne, types are under-specified beyond introspection
procedures’ names exactly because they need to stay
implementation-specific beyond that. However, type->check is a really
good idea! I’ll add it and eqv? requirement to my TODOs for draft 2, but
no promises.

> procedure-check-of: "This in particular might mean that procedures
> defined with case-lambda(-checked) only get checks for the required
> arguments. But this glaring under-design of this SRFI is offset by the
> fact that multiple-arity procedures are problematic in many ways when
> it comes to checks."
>
> I was playing around with the idea of adding introspection to
> procedures and thought that the easiest thing to do with case-lambda
> forms is to store argument information as multiple lists, one list for
> each branch of the case-lambda form.

Yes, this is an option too. However, this will significantly complicate
the return values (not much of a problem) and will be quite non-portable
(more of a problem,) as some implementations compile case-lambda-s to a
single variadic procedure, and some compile them to separate procedures
of different arities. I worked hard to make case-lambda-s more
introspectable on Chibi
<https://github.com/ashinn/chibi-scheme/pull/1189> and STklos
<https://github.com/egallesio/STklos/pull/932>, but even there my
results are pretty underwhelming.

Thanks,
--
Artyom Bologov
https://aartaka.me