For my sdbi I'm doing "engine records" as well, and their ugliness will be visible at this SRFI 167 OKVS level, the sdbi user API level is ~= SRFI 168 Generic Tuple Store Database, which uses OKVSes for its persistence.

Specifically an opaque "chain" record type, which is used to set up your "stack" of "technologies", for instance:

(db-chain-construct alist) -> chain

Where the alist requires at least two entries, one 'connector, currently like 'postgresql-net or 'sqlite3-ffi (because the "net" or "ffi" come after the connector, how it talks to the database, they're always linked).  It's their job to supply a generic interface to the code above them to do database operations.  And one to specify the database, because they have generic behavior as well as quirks to either be homogenized, or deliberately exposed, like SQLite3's functions to convert dates and time to and from text.  E.g.:

(db-chain-construct '((connector . cassandra-ffi)
                      (database . cassandra)))

That chain record is then handed to (db-connection-open chain alist) which returns another opaque type, connection, and subsequent calls to procedures like (db-exec connection statement) will in whatever way use the connection record to know which connector and and database procedures to call.

Amirouche is absolutely correct in noting that naive use of this is ugly, where you call a function that returns a procedure to then invoke it, e.g.: (engine-delete engine) "returns the procedure okvs-delete!" for the specific OKVS engine being used.  From a previous message he gave this explanation and example:

Because engine accessors return a procedure, the user needs to write code that looks like the following

(define (index okvs engine uid string)
   ((engine-set engine) okvs ((engine-pack engine) string uid)
((engine-pack engine) #t))))

I too would like something more elegant, but I was waiting until I had two different naive implementations to then perhaps wave the magic macro wand, I couldn't see how the Chibi Scheme generic library would solve my issues.  Amirouche, how are you now thinking of doing this?

- Harold

----- Original message -----
From: John Cowan <xxxxxx@ccil.org>
Cc: xxxxxx@srfi.schemers.org
Date: Thursday, October 24, 2019 8:39 AM

Put the record in its own little SRFI (that's what we are doing for timespec), or use an alist instead.

On Thu, Oct 24, 2019 at 3:26 AM Amirouche Boubekki <xxxxxx@gmail.com> wrote:
Le dim. 6 oct. 2019 à 00:41, Amirouche Boubekki
<xxxxxx@gmail.com> a écrit :
>
> Le dim. 6 oct. 2019 à 00:38, Amirouche Boubekki
> <xxxxxx@gmail.com> a écrit :
> >
> > Here the fist paragraph from the SRFI-167 specification about engine:
> >
> > > engine
> >
> > > To allow the user of an okvs abstraction (also known as layer) to easily swap implementations, it must be written in terms of the procedures specified in this section. The engine is a simple record of okvs procedures that must be passed to the constructor of layers. It must be shared between okvs implementations. The okvs library must contain an instance of the engine record exported as engine that is bound to the procedures that it defines.

[...]

> > Based on my knowledge there is an approach to achieve that: Single dispatch.
> >
> > Do you know what would be the Right Thing? Or maybe this is the Right Thing?
> >
> > ref: https://srfi.schemers.org/srfi-167/srfi-167.html
>
> Maybe chibi-scheme generic is the way to go?
>
> ref: http://synthcode.com/scheme/chibi/lib/chibi/generic.html

I will remove the engine record type from the sample implementation
and from the specification.

ref: https://github.com/amirouche/arew-scheme/blob/master/src/arew/srfi/srfi-167/engine.md

There is still time to stop me :)