On Mon, Jul 8, 2019 at 6:50 AM <xxxxxx@ancell-ent.com> wrote:

I have a feeling it would be better if there were separate procedures for insertion and deletion; what code could be easily shared if there was just one?

 None, probably.  So yes, two procedures.

Needs to be centralized maintain data integrity, so "per database", whatever that means, at a low enough level that all mutation transactions must go through it, i.e. implemented in this SRFI.  The scope in time I'm thinking of is from the initialization of the higher level library to program exit, unless you disable one or more constraints for maintenance, and then hopefully remember to enable it.  Which suggests a wrapper rather than explicit disable and enable procedures, but that's not ideal for maintenance.

I agree that that's the Right Thing, but if we want to keep the complete freedom of keys (which I do), the price will be having a side channel that allows the constraints in source form to be downloaded by the library.   Perhaps the convention is that there is a little HTTP server on a well-known port of the same machine that when you do "GET $home", fetches the constraints.  It's a lot more overhead.

OTOH, we could preempt the key "", which is unlikely to be used by anybody.  We would have to put the whole current constraint framework in there, though: both the user supplied constraint procedures and the framework code that invokes them appropriately.
 
How about extending the interface above so that a registered constraint procedure gets a continuation argument which it tail-calls to let higher-level constraints decide?  Best of both worlds and very Schemey.

But that would require me learning continuations for real....

Actually not.  Don't confuse continuations as such with the escape procedures provided by call/cc.

A continuation argument in this sense is just an ordinary procedure, named or anonymous, which
is passed to the constraint procedure.  The constraint procedure's protocol is to be called with key, value, and proc, and then to return if the constraint is met, throw an exception if it is not met, and call proc with the first two arguments if it can't decide.  Requiring this call to be a tail call allows for an arbitrarily long chain of constraints without winding up the stack.

The mini-framework for constraints would pass as proc a procedure that takes key and value arguments, figures out the next constraint to invoke, and then invokes it.

More seriously, how much do we care about Scheme implementations that implement continuations slowly, imperfectly, or not at all?

Not relevant to this.
 

This sounds like it would require running every registered constraint for every key to "decide" if it should fire

Not every constraint, because the prefix limits to a few what constraint exists, and the longest prefix dictates which constraint is called first. 


John Cowan          http://vrici.lojban.org/~cowan        xxxxxx@ccil.org
At times of peril or dubitation,
Perform swift circular ambulation,
With loud and high-pitched ululation.