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)
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 (28 Jul 2020 14:15 UTC)

Re: Splitting foreign-error:code for SRFI 198, Foreign Errors hga@xxxxxx 28 Jul 2020 14:14 UTC

> From: Lassi Kortela <xxxxxx@lassi.io>
> Date: Tuesday, July 28, 2020 4:10 AM
>
> [...]
>
>> I like to be able to learn and use as little of an API as possible,
>> the investment in a language is more generally useful.
>
> One of the key discoveries that were enabled by Lisp is that languages
> and APIs are somewhat interchangeable. An API is just a language and a
> language is just an API.

Indeed, but the design of an API for a foreign interface is not
necessarily going to be as good or regular as the language you're
using because it has to conform to the requirements of the foreign
interface.  So my claim here is that if I have to use a messy foreign
interface API, I want "to be able to learn and use as little of" it as
is reasonable.  Learn the high level dangers, then just the parts I
need.  E.g., for libsodium, I need symmetric encryption, don't need
the complexity of how it does the public key type.

> [ SCIENCE! ]
>
>> I'm a BIG proponent of REPLs, which have
>> enabled some of my biggest time constrained programming feats.
>
> Same here. They are indispensable for exploring a new system and new
> problems. Things like (apropos "foo") and a good pretty-printer help a
> lot. That's why the error-set enumeration is nice too -- it's like
> `apropos` for errors.

For various reasons, right now in my Chibi Scheme work I'm almost never
using a pretty-printer....

> [ Stuff that's now obsolete with the new, flat, plist based API. ]
>
>
> A key tenet of interface design is that indirection is not abstraction.
> An interface that offers a choice of things (e.g. different data types
> to put in the error slots) is not more abstract than those things by
> themselves. A good abstraction is conceptually simpler than the things
> it hides. Hence the user has the luxury of keeping fewer things in mind,
> which is what it means to provide a service.

Hmmm, OK.

> For example, (foreign-error:data ferr 'key) -> value or #f is an
> abstraction since missing and false keys are conflated into the same
> return value #f and the caller doesn't need to care which it is.
>
> If lambdas can be stored in error fields and the accessor transparently
> calls those lambdas and returns their return values, that's a further
> abstraction since the user doesn't have to care about lambdas vs
> non-lambdas.

Indeed.  And for the lambdas, make them take zero arguments except for
localization and we have what I want, the price of opaque values is worth
it when needed, especially with only having to know the simple rule that
if you see a procedure in the raw error object that's not got a 'message
key, you call it with no arguments.

> [...]
>
>> One thing this does is place a greater emphasis on the exact alist you
>> feed to make-foreign-error, or having it reorder the alist so for
>> example 'error-set is always first.
>
> Order of keys shouldn't matter; instead of an alist, a hash-table could
> be used internally.

For now I'm advocating requiring key ordered plists, because I
envision them being cheap enough for this SRFI, and because they
provide free reflection, so a user will not necessarily have to do
anything more than display the list, and:

> Maybe it's nice to have a particular order for display, but that should
> be the printer's concern IMHO.

very possibly be in environments without a pretty printer, or that he
doesn't know how to invoke, etc.  I claim we can't assume much about
the user of SRFI 198 using libraries, whatever the ideals are.

>> Are their cases where two or more
>> items are logically tightly bound, and should be grouped together??
>
> Yes, there are. For example, the 'code key is necessarily coupled with
> the 'error-set key. Different error sets can have different meanings for
> the same code (e.g. the number 2 can be a completely different error).

Tightly bound, for sure, but need they be grouped together in any way
besides all being in one flat (p)list?

> [ Other arguments for not grouping them together. ]
>
> [ Good rant; for me, after trying objects for ~ a decade, I decided
>   they're a mistake outside of a few limited problem domains. ]
>
> [ Ordering idea I've given up on. ]
>
> In general, by cultural convention, alist keys are not expected to be in
> a particular order. `assoc` gets the first matching key, but that only
> matters in the rare case that there are duplicate keys. If the order of
> non-duplicate keys matters, that would probably surprise most Lispers.

Sure, but here I want to require that error objects, or their data slot,
be plists and nothing more, and for a simple not pretty print of the
plist to be as useful as possible.  Which should be easy enough in the
make-foreign-error procedure (which is first called by the raise
procedures, something I need to make explicit in the SRFI document).

> [...]
>
>> I've already decided all slots are optional except error-set....
>
> Enthusiastically agreed, "everything optional" is the right principle.
>
> Even error-set can probably be optional. It just makes it hard to
> interpret any other info, but you can still display the message, etc.

In my above scheme of requiring them to be plists and not requiring
pretty printing, it's required for sanity, and that 'error-set, or
something else identifying it as you posited, be first in the list.

> Enforcing things is not that simple in dynamic languages, so forcing
> users to give an error-set might not work in practice anyway.

The way I handle this requirement in my implementation is to turn it
into an 'error error-set, emit a "malformed error" message, and
include all the original arguments in the (now going poof) data slot.

> The principle in static languages is "don't violate the types". The
> equivalent principle in dynamic languages is something like "don't go
> against the grain". When in Rome, do like Romans do, etc. On the whole,
> dynamic languages don't grow good systems by enforcing constraints but
> by building things that have good synergy with existing things.

Here's another area where we may generally disagree.  Ignoring the minor
details my work with industrial strength database servers often starting
from bare metal, I vastly prefer a RDMBS like PostgreSQL, or in times
past Oracle and DB2, that allows me to use normal SQL to enforce
constraints, one way of catching errors in programming, dynamic or not.
See also the stories of the fun people have had in moving a MySQL database
to one that enforces even minimums like column type constraints.

>> I predict I'm going to like this.

I was right.

> Thank you very much for listening to the arguments. We could at least
> see how it goes. At least it has nice synergy with other Lisp customs
> like property lists (as per John's pre-SRFI), which again are somewhat
> symmetrical to keyword arguments.

You're very welcome.

> >>> [ hey, it's your API design you're throwing in the trash can ^_^. ]
>
> "Write one to throw away" is one design principle the Unix and Lisp
> communities happily agree on :) Hindsight is better than foresight.

Indeed.  And a great deal of the first design survives, just in a
different and much simpler organization.

- Harold