|
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)
|
|
Re: Splitting foreign-error:code for SRFI 198, Foreign Errors
John Cowan
(27 Jul 2020 23:22 UTC)
|
|
Re: Splitting foreign-error:code for SRFI 198, Foreign Errors
hga@xxxxxx
(27 Jul 2020 23:40 UTC)
|
|
Re: Splitting foreign-error:code for SRFI 198, Foreign Errors
Lassi Kortela
(27 Jul 2020 23:59 UTC)
|
|
Re: Splitting foreign-error:code for SRFI 198, Foreign Errors
Lassi Kortela
(27 Jul 2020 23:44 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 00:29 UTC)
|
|
Re: Splitting foreign-error:code for SRFI 198, Foreign Errors
Lassi Kortela
(28 Jul 2020 09:10 UTC)
|
|
Re: Splitting foreign-error:code for SRFI 198, Foreign Errors
hga@xxxxxx
(28 Jul 2020 14:15 UTC)
|
> From: Lassi Kortela <xxxxxx@lassi.io>
> Date: Monday, July 27, 2020 6:44 PM
>
>> I have a *very* strong preference for keeping the number of top level
>> exposed interfaces small.
>
> Where does your preference come from - is it a particular school of
> thought in design, or just from personal experience that it tends to
> works better?
Personal experience in designing many APIs, and some user interfaces
as well, which in their own way are APIs. I like a rule of thumb of 3s,
ideally no more than 3 choices at every level, and they nest no more
than 3 deep.
> Over time I've developed almost the opposite preference. IMHO the key
> metric is not the number of functions but the number of
> interdependencies. If the functions do not depend on each other, none of
> them complicates the others. Rich Hickey discusses this in one of his talks.
>
> On a related note, when you have a data structure, adding more functions
> to work on that data structure makes it stronger. Perlis: "It is better
> to have 100 functions operate on one data structure than 10 functions on
> 10 data structures." <http://www.cs.yale.edu/homes/perlis-alan/quotes.html>
This is perhaps a difference between an API, *of which there are
many*, and pretty much each with its own organization, and a language.
In the latter, it's reasonable make the Perlis argument as Clojure does.
On the other hand, I prefer quite a bit less choice in both, one major
reason I'm back to Scheme after several years with Clojure.
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 other factor: by inclination, I'm a scientist, external factors
plus not being bad at software and systems is why I'm here today.
So arranging things into hierarchies is more natural to me than
making them flat lists.
>> [ Stuff we agree on. ]
>
> Even more importantly, not all errno numbers are the same across
> operating systems. The C identifiers like EINVAL are the stable
> interface enshrined by POSIX. The numeric values are per OS.
John mentioned the lower numbers have been stable for decades. Not
that we can depend on that....
>> 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.
>
> Good point. This is worth thinking more about.
>
>> The proposed repository for error-sets, as well as library specific
>> foreign interfaces, should tell you the keys to expect.
>
> That's a good idea.
>
> Also, similar keys across different error sets should strive to have the
> same key symbols to ease people's cognitive load.
That, shall we say, is a key idea ^_^.
>> But they can be discovered simply by triggering an error in a REPL
>> and noting all the keys in foreign-error:code.
>
> True - at least if all keys are filled in for all errors of that type.
You should at minimum start to get a feel for the shape of the
error-set by doing that. I'm a BIG proponent of REPLs, which have
enabled some of my biggest time constrained programming feats.
>> 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.
>
> I would try to avoid nested alists, and have all keys in one flat
> top-level alist. No hard principle for this either, just that nested
> things are more complicated than flat things.
Agreed, but I claim your example below doesn't fit that antipattern:
> So the example from the current draft:
>
> (make-foreign-error
> '((error-set . errno)
> (code . ((number . 2)
> (symbol . errno/ENOENT)))
> (scheme-procedure . open-file)
> (foreign-interface . open)
> (message . "open-file called open: ...")
> (data . ((arguments . ("not-a-valid-filename" 0 428))
> (heritage . "SRFI 170")))))
I claim the above two levels are OK because the first level
simply tells make-foreign-error which slot to put the following
data in. If a key other than error-set is missing, it gets #f.
This is something only the programmer using SRFI 198 has to master,
the user of his library will only see one flat level per slot.
Something I've been doing implicitly, since as you note it's the
right thing, but that we should probably make explicit in the SRFI.
Except:
> I would prefer to write as something like this:
>
> (make-foreign-error
> '((error-set . errno)
> (code . 2)
> (symbol . ENOENT)
> (scheme-procedure . open-file)
> (foreign-interface . open)
> (message . "open-file called open: ...")
> (arguments . ("not-a-valid-filename" 0 428))
> (heritage . "SRFI 170")))
>
> Accessor functions will be simpler: (foreign-error:data ferr 'code)
> instead of (foreign-error:data ferr 'code 'number) or something like it.
Hmmm, here you're proposing to collapse the entire error record into
one slot. My first instinct is to not like that.
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. Are their cases where two or more
items are logically tightly bound, and should be grouped together??
I'm not sure that's a real issue, or at least it's subsumed by having
conventions require a certain order for human consumption of the
resultant single alist. We could add that to the API fairly easily,
for example have the symbol that's the value of the error-set
contain a list of top level symbols in the correct order.
> If the value for that alist key is a lambda, extra arguments to
> `foreign-error:data` can be passed to that lambda. We don't have to use
> them to do nested alist lookups if we have no nested alists.
See above, the end resulting error object has nesting of slots
containing alists, but no nested alists.
> If we specify keys in the error-set registry, that will also be simpler
> if there is only one level of keys.
Indeed. No having to decide logically in which key a slot goes. And
I've already decided all slots are optional except error-set....
I predict I'm going to like this.
>> [ More convincing arguments along this line, and, hey, it's your
>> API design you're throwing in the trash can ^_^. ]
- Harold