Special properties of the 'set key
John Cowan
(12 Aug 2020 12:50 UTC)
|
Re: Special properties of the 'set key
hga@xxxxxx
(12 Aug 2020 13:18 UTC)
|
Re: Special properties of the 'set key
Lassi Kortela
(13 Aug 2020 06:58 UTC)
|
Re: Special properties of the 'set key
hga@xxxxxx
(13 Aug 2020 10:55 UTC)
|
Re: Special properties of the 'set key
Lassi Kortela
(14 Aug 2020 07:37 UTC)
|
Sub-set key and zero/nonzero success/failure status sets
Lassi Kortela
(14 Aug 2020 08:47 UTC)
|
Re: Special properties of the 'set key
John Cowan
(14 Aug 2020 04:28 UTC)
|
Re: Special properties of the 'set key Lassi Kortela (14 Aug 2020 08:20 UTC)
|
> The rationale for a general classification property, call it type or > whatever, is that it gives the exception handler an indication of what > other properties it can expect to find. We need to put on our math student hats and respect the zero case. A status object with zero properties gives you the zero value #f for the 'set property by default. That zero value implies you have zero guarantees about what else to find in the object :) Please note that a mandatory 'set property can still be #f which will give no more information about anything. If we mandate it to be non-#f then people can still create status objects where all the other properties are either missing or have useless or misleading values. We are exhibiting a textbook case of spec writer's disease. Thinking we can coerce future strangers into good behavior by anticipating their use cases. Instead, we should build the spec from the bottom up, starting from what we know and not going further than we can find concrete evidence for. The status object is a tagged collection with symbols for keys. We know a lot about collections. Think about Scheme's hash-table abstraction. A hash-table can have zero values, it has particular enumerators but nothing to return a plist, hides the concrete representation. We have concrete evidence about what errno values and SQLSTATE codes exist in the wild. Hence we can design something for those. There are many other future use cases for status objects that we know nothing about, and to misappropriate Wittgenstein (because what could be more fun), "Whereof one cannot speak, thereof one must be silent." > If a foreign-status object is a > Posix error, it will have an errno and a #define name. If it is a > database engine error, it will have a SQL state and possibly a > proprietary number and symbol too. Mandating a 'set property does not mandate a 'code property so you still won't know which error occurred (if any; most error sets reserve a code for success). > If it is a libsodium-style system, > it will have none of these, only a message. We can specify that 'message is expected to be a string -- a convention we can expect everyone to follow out of simple self-interest. A message is usable even without the set. > The bare minimum is all properties optional with #f defaults. > > I think that's subminimal. It's the zero case. > If there are no keys at all, all we know is > what a baby tells us when it howls: "Something's wrong". We don't even know that something's wrong since a status object can also represent success. We know just as little about success or failure with an empty status object as with one that has only 'set. > If there are keys but no classifier key, we don't know how to interpret > what we are told, because the same keys inevitably mean different things > in different contexts. In that case both 'set and 'code should be mandatory. Or should it be 'set AND ('code OR 'message)? Does that cover everything? Etc... It never ends. This is how those bizarre laws about throwing moose off airplanes get started. > > We have to decide if we're going to have a foreign-status-plist. > > There's an argument for having both it and foreign-status-keys. > > I agree that we should have both. IMHO two iterators (which they in effect are) is a sign that we're not being coherent about what we really want with the abstraction. > Even Python programmers deal with concrete types like lists, sets, > dicts, etc. But I agree that it's a minor point. My reason for wanting > the type to be first is so that pattern matching can provide a first-cut > analysis of foreign-status objects. Ah, that makes sense. But I would recommend: (case (foreign-status-ref st 'set) ((errno) (do-something-to (foreign-status-ref st 'code)) ...) ((windows) ...)) If you want: (let ((plist (foreign-status-plist st))) (case (cadr plist) ((errno) (do-something-to (plist-ref/default st 'code #f)) ...) ((windows) ...))) Then you just admitted that our would-be abstraction is just indirection in disguise. We've become Java experts :) Note how the benefits of abstraction are lost. We need to care that it's a plist, and give our own #f default in plist-ref instead of relying on defaults of the error object. If we add transparent lambdas... it looks like we're precluded from adding any with this approach, unless they are all called by `foreign-status-plist` in an indeterminate order. Draft #2 of a contentious SRFI is coming up and we're already painting ourselves into a corner, making some kind of postmodern mash-up of abstract and concrete that doesn't really give the benefits of either. Perlis: "Functions delay binding; data structures induce binding. Moral: Structure data late in the programming process." <http://www.cs.yale.edu/homes/perlis-alan/quotes.html> > We shouldn't be abstract for the sake of being abstract. We should be > abstract only when there is a substantial gain from having more than one > representation. I agree, but I think there are gains. If we want a concrete representation, I suggest (cons 'foreign-status plist); no need for a SRFI.