Initial comments Marc Nieper-Wißkirchen (04 Nov 2022 06:59 UTC)
Re: Initial comments Lassi Kortela (04 Nov 2022 09:59 UTC)

Re: Initial comments Lassi Kortela 04 Nov 2022 09:59 UTC

> - If numbers are unreliable, don't expose them to the user but wrap
> them in opaque objects.  Only necessarily system-dependent low-level
> implementations of libraries should deal with them.

The SRFI is mainly intended to be a bridge between high and low level
code. I think the level of abstraction is appropriate for that purpose.

When dealing with codesets where the symbols are primary and the numbers
are an implementation detail, the FFI wrapper should use a codeset to
translate numbers from C and only pass symbols to high level code.

> - Use macros instead of procedures to catch typos and use unsupported
> symbols early.  In particular, write (codeset errno) instead of
> 'errno.  Write (errno eperm) instead of 'eperm.  (See R6RS
> enumerations that use the same technique, for example.)

A codeset according to this SRFI is meant to imperfectly capture a
codeset in reality. The set foo in reality has _at least_ the codes in
(codset-symbols 'foo) but may have more.

The SRFI's rationale says (perhaps not as clearly as it could) that it's
generally impossible to be sure that you have fully enumerated the set.
E.g. errno is specified in standard C, in POSIX, in the errno.h of
different kernels, etc. Which is authoritative, and which version?

SQLite has a known set of result codes, but new versions of SQLite may
add new codes.

Since the set of possible values is "open", it's not prudent to use a
R6RS style enum.

The problem becomes even clearer when you consider union types in ML.

datatype errno = EPERM | ENOENT | ESRCH;

The above is not a sensible definition of errno (not even in principle,
and not even if you populate it with all the latest values from POSIX
and Linux). In fact, the SML Basis Library specifies errno as an
abstract datatype. SML/NJ implements it as an integer:

- OS.syserror "intr";
val it = SOME 4 : OS.syserror option

- 4;
val it = 4 : int

- 4 : OS.syserror;
val it = 4 : OS.syserror

I sympathize with the concern of catching typos. IMHO that's best done
by writing macros to generate code akin to this:

(define EPERM 'EPERM)
(define ENOENT 'ENOENT)
(define ESRCH 'ESRCH)
...

Then you get more generality and it works well with an "open" set.

(The mathematical term "open set" means something different but I can't
think of a better term at the moment.)