I’m struggling to find another egg that uses *-rm as a function name. Copying from hashtable, is *-clear or *-remove more standard?
Indeed, I will replace it with okvs-clear! because R7RS hash-table use hash-table-clear!
I also notice that you’ve elided range clears entirely from your API. Was that intentional? They are inconsistently supported across kv stores…
I will add it.
I feel like isolation is something you’d be better off leaving out of the SRFI. Which you kind of did already, as it’s in an optional config struct.
Ok.
The only difference between an ordered and unordered key-value store is if it supports efficient range operations. If your SRFI requires arbitrary get-ranges, you’re going to require someone to write an almost-equivalent unordered key-value store SRFI, and
Unordered key-value store seems not very useful to compose higher abstraction. I will think about it. I might make the okvs-range and okvs-prefix optional.
you also technically ban systems like Cassandra that distributes data such that a known prefix of the key is randomly distributed and a suffix of the key is sequentially distributed.
I don’t have enough experience with Cassandra to support it.
I don’t recall seeing “decorator” be a common scheme pattern?
It is not really a common pattern in the sens there is no word for it. That said, higher order procedures, that is procedures that take procedure as argument are common place. memoize is an example of high order procedure that is also a decorator.
I feel like I see explicit transaction runner functions in most other language’s database bindings.
I don’t understand this paragraph:
You could just offer a function like (okvs-run okvs proc) , and then (okvs-run okvs (lambda (db) (okvs-ref db key))) would be equivalent to the current ((okvs-transaction (lambda (db) (okvs-ref db key))) okvs) , the latter of which I find harder to mentally parse.
Right now, the way to use okvs-ref is as follow:
(define db (okvs config))
(okvs-set! db #vu8(42) #vu8(2019))
(define value (okvs-ref db #vu8(42))
Which is equivalent to:
(define db (okvs config))
;; set
(define tr (okvs-transaction-begin db))
(okvs-set! tr #vu8(42) #vu8(2019))
(okvs-transaction-commit tr)
;; ref
(define tr (okvs-transaction-begin db))
(define value (okvs-ref tr #vu8(42))
(okvs-transaction-commit tr)
That said, I have enjoyed @fdb.transaction making life simple in the python bindings, and I don’t really have a great sense of what is or is not idiomatic for scheme anyway.
As far as I understand, it transactional in scheme is not very idiomatic. The R7RS sheperd proposed something else:
A more Schemey approach would be (in-transaction database proc failure success), which evaluates PROC passing a newly created transaction as its argument. When PROC returns, the transaction is committed and in-transaction applies whatever PROC returned to the SUCCESS procedure and returns its result. If PROC calls “rollback” instead, then the transaction is rolled back, the execution of PROC is abandoned, FAILURE is called with no arguments, and in-transaction returns its result. By default FAILURE is raise and SUCCESS is identity.
My rationale behind transactional, tell me if I am mistaken, is that it is very easy to use procedures decorated with transactional in REPL. The in-transaction approach is a little bit more ceremony.
It seems like the above okvs-run you mention looks like in-transaction.