Splitting foreign-error:code Lassi Kortela (27 Jul 2020 06:46 UTC)
Re: Splitting foreign-error:code Lassi Kortela (27 Jul 2020 08:26 UTC)
Re: Splitting foreign-error:code Lassi Kortela (27 Jul 2020 08:51 UTC)
Re: Splitting foreign-error:code John Cowan (28 Jul 2020 19:25 UTC)
Re: Splitting foreign-error:code for SRFI 198, Foreign Errors hga@xxxxxx (27 Jul 2020 11:26 UTC)
Flat vs nested alist Lassi Kortela (27 Jul 2020 23:50 UTC)
Re: Flat vs nested alist Lassi Kortela (27 Jul 2020 23:53 UTC)
Re: Flat vs nested alist John Cowan (28 Jul 2020 03:06 UTC)
Pre-SRFI for property list utilities Lassi Kortela (28 Jul 2020 07:35 UTC)
Re: Pre-SRFI for property list utilities hga@xxxxxx (28 Jul 2020 11:00 UTC)
Plist utilities and SRFI 198 Lassi Kortela (28 Jul 2020 11:08 UTC)
Re: Plist utilities and SRFI 198 John Cowan (28 Jul 2020 18:12 UTC)
plist pre-SRFI hga@xxxxxx (12 Aug 2020 15:14 UTC)
Re: plist pre-SRFI John Cowan (12 Aug 2020 15:21 UTC)
Re: plist pre-SRFI John Cowan (12 Aug 2020 15:53 UTC)
Re: plist pre-SRFI hga@xxxxxx (12 Aug 2020 15:58 UTC)
Re: plist pre-SRFI John Cowan (12 Aug 2020 16:59 UTC)
Re: plist pre-SRFI hga@xxxxxx (12 Aug 2020 17:34 UTC)
Re: plist pre-SRFI John Cowan (12 Aug 2020 19:37 UTC)
Use of SRFI 198 in SRFI 170 hga@xxxxxx (12 Aug 2020 20:04 UTC)

Re: Splitting foreign-error:code for SRFI 198, Foreign Errors hga@xxxxxx 27 Jul 2020 11:26 UTC

I have a *very* strong preference for keeping the number of top level
exposed interfaces small.  In this case, foreign-error:code allows for
any error-set to have none, represented by #f, e.g. libsodium and
plenty of other libraries just have functions that signal errors with
no further organization.

errno really only has a number, I've added the C define such as EINVAL
which all the documentation uses for the convenience of the user.  It's
trivial to provide, and it can be very obnoxious for a user to grovel
through a Linux /usr/include to map the number to the name he needs to
interpret it in the documentation.

Whereas databases such a PostgreSQL have an elaborate organization for
their errors.  Having foreign-error:code contain an alist allows for
both the simple display of everything, without having to look at the
whole error object, and programmatic access by key for each value. The
proposed repository for error-set, as well as library specific foreign
interfaces, should tell you the keys to expect.  But they can be
discovered simply by triggering an error in a REPL and noting all the
keys in foreign-error:code.

Another advantage is that having foreign-error:code fan out into an
alist doesn't require us *today* to anticipate every possible way
an error can be classified.  That I've worked with database like
Oracle and PostgreSQL is why I want to layer all this underneath
the single foreign-error:code getter.

Here, in addition to foreign-error:message, which should always be
populated in systems with enough memory to store them, or procure them
in some localization schemes, you add 3 new first class, top level
interfaces to the API in addition to code:

(foreign-error:symbol ferr) -> 'invalid_password
(foreign-error:class-code ferr) -> 28
(foreign-error:class-title ferr) -> "Invalid Authorization Specification"

What's wrong with keeping them in an alist, keyed on 'symbol,
'class-code, and 'class-title?

This also bring up the question of what is your limiting principle for
the first class, top level of the API?

- Harold

----- Original message -----
From: Lassi Kortela <xxxxxx@lassi.io>
Date: Monday, July 27, 2020 1:46 AM

Currently we have:

(foreign-error:code foreign-error-object) → alist or #f

Where alist is e.g.:

((number . 2)
  (c-define . errno/ENOENT))

((class-number . 28)
  (class-title . "Invalid Authorization Specification")
  (code . 28P01)
  (condition-name . invalid_password))

Should we splice these alist entries into the top-level alist somehow? A
simple API like this would be convenient and would probably match the
expectations of most users:

(foreign-error:error-set ferr) -> 'errno
(foreign-error:code ferr) -> 2
(foreign-error:symbol ferr) -> 'ENOENT
(foreign-error:message ferr) -> "No such file or directory"

However, it's also nice that we can represent the comprehensive Postgres
example above. It could be split thus:

(foreign-error:error-set ferr) -> 'postgresql
(foreign-error:code ferr) -> '|28P01|
(foreign-error:symbol ferr) -> 'invalid_password
(foreign-error:message ferr) -> "Invalid password"
(foreign-error:class-code ferr) -> 28
(foreign-error:class-title ferr) -> "Invalid Authorization Specification"

It's great that Harold looked into postgres early, since it has
almost-but-not-quite-numeric error codes. If the world were a simpler
place, it would be nice to have a `foreign-error:number` procedure that
returns an integer or #f. But if we used `foreign-error:symbol` for
almost-numeric codes like '|28P01|, where would we stash the
definitely-not-numeric identifiers like 'invalid_password?

A practical solution is to have `foreign-error:code` which can return
either a number or a symbol or #f, as above. Would this be good enough?

The error class seems quite special to postgres; are there many other
interfaces that group their error codes into classes? If there are, then
`foreign-error:class-code` and `foreign-error:class-title` should
probably be first-class (no pun intended :) If not, perhaps they should
go into the free-form alist `foreign-error:data`.

Harold, what do you think?