4 Racket Interoperability
(require datalog) | package: datalog |
The Datalog database can be directly used by Racket programs through this API.
> (define family (make-theory))
> (datalog family (! (parent joseph2 joseph1)) (! (parent joseph2 lucy)) (! (parent joseph3 joseph2))) '()
> (datalog family (? (parent X joseph2))) '(#hasheq((X . joseph3)))
> (datalog family (? (parent X (string->symbol "joseph2")))) '(#hasheq((X . joseph3)))
> (let ([atom 'joseph2]) (datalog family (? (parent X #,atom)))) '(#hasheq((X . joseph3)))
> (let ([table 'parent]) (datalog family (? (#,table X joseph2)))) '(#hasheq((X . joseph3)))
> (datalog family (? (parent joseph2 X))) '(#hasheq((X . joseph1)) #hasheq((X . lucy)))
> (datalog family (? (parent joseph2 X)) (? (parent X joseph2))) '(#hasheq((X . joseph3)))
> (datalog family (! (:- (ancestor A B) (parent A B))) (! (:- (ancestor A B) (parent A C) (= D C) (ancestor D B)))) '()
> (datalog family (? (ancestor A B)))
'(#hasheq((A . joseph3) (B . joseph2))
#hasheq((A . joseph2) (B . lucy))
#hasheq((A . joseph2) (B . joseph1))
#hasheq((A . joseph3) (B . lucy))
#hasheq((A . joseph3) (B . joseph1)))
> (let ([x 'joseph2]) (datalog family (? (parent x X)))) '(#hasheq((X . joseph1)) #hasheq((X . lucy)))
> (datalog family (? (add1 1 :- X))) '(#hasheq((X . 2)))
> (datalog family (? (add1 X :- 2))) '()
> (datalog family (? (#,(λ (x) (+ x 1)) 1 :- X))) '(#hasheq((X . 2)))
procedure
(make-theory) → theory/c
procedure
(write-theory t [out]) → void?
t : theory/c out : output-port? = (current-output-port)
procedure
(read-theory [in]) → theory/c
in : input-port? = (current-input-port)
Statements are either assertions, retractions, or queries.
syntax
(! clause)
syntax
(~ clause)
syntax
(:- literal question ...)
syntax
(? question)
Questions are either literals or external queries.
Literals are represented as identifier or (table term ...).
A table is either an identifier or #,expr where expr evaluates to a symbol.
External queries are represented as (ext-table term ... :- term ...), where ext-table is an identifier bound to a procedure or #,expr where expr evaluates to a procedure that when given the first set of terms as arguments returns the second set of terms as values.
A term is either a non-capitalized identifiers for a constant symbol, a Racket expression for a constant datum, or a capitalized identifier for a variable symbol, or #,expr where expr evaluates to a constant datum. Bound identifiers in terms are treated as the datum they are bound to.
External queries fail if any logic variable is not fully resolved to a datum on the Datalog side. In other words, unbound logic variables never flow to Racket.
External queries invalidate Datalog’s guaranteed termination. For example, this program does not terminate:
(datalog (make-theory) (! (:- (loop X) (add1 X :- Z) (loop Z))) (? (loop 1)))