126 lines
4.2 KiB
Racket
126 lines
4.2 KiB
Racket
#lang scribble/doc
|
|
@(require scribble/manual
|
|
scribble/eval
|
|
scribble/basic
|
|
scribble/bnf
|
|
(for-label racket/base
|
|
racket/contract
|
|
"../main.rkt")
|
|
"utils.rkt")
|
|
|
|
@title[#:tag "interop"]{Racket Interoperability}
|
|
|
|
@defmodule[datalog]
|
|
|
|
The Datalog database can be directly used by Racket programs through this API.
|
|
|
|
@examples[#:eval the-eval
|
|
#:escape UNSYNTAX-NOT
|
|
(define family (make-theory))
|
|
|
|
(datalog family
|
|
(! (parent joseph2 joseph1))
|
|
(! (parent joseph2 lucy))
|
|
(! (parent joseph3 joseph2)))
|
|
|
|
(datalog family
|
|
(? (parent X joseph2)))
|
|
|
|
(datalog family
|
|
(? (parent X (string->symbol "joseph2"))))
|
|
|
|
(let ([atom 'joseph2])
|
|
(datalog family
|
|
(? (parent X #,atom))))
|
|
|
|
(let ([table 'parent])
|
|
(datalog family
|
|
(? (#,table X joseph2))))
|
|
|
|
(datalog family
|
|
(? (parent joseph2 X)))
|
|
|
|
(datalog family
|
|
(? (parent joseph2 X))
|
|
(? (parent X joseph2)))
|
|
|
|
(datalog family
|
|
(! (:- (ancestor A B)
|
|
(parent A B)))
|
|
(! (:- (ancestor A B)
|
|
(parent A C)
|
|
(= D C)
|
|
(ancestor D B))))
|
|
|
|
(datalog family
|
|
(? (ancestor A B)))
|
|
|
|
(let ([x 'joseph2])
|
|
(datalog family
|
|
(? (parent x X))))
|
|
|
|
(datalog family
|
|
(? (add1 1 :- X)))
|
|
(datalog family
|
|
(? (add1 X :- 2)))
|
|
(datalog family
|
|
(? (#,(λ (x) (+ x 1)) 1 :- X)))]
|
|
|
|
@defthing[theory/c contract?]{ A contract for Datalog theories. }
|
|
|
|
@defproc[(make-theory) theory/c]{ Creates a theory for use with @racket[datalog]. }
|
|
|
|
@defproc[(write-theory [t theory/c]) void]{ Writes a theory to the current output port. Source location information is lost. }
|
|
@defproc[(read-theory) theory/c]{ Reads a theory from the current input port. }
|
|
|
|
@defform[(datalog thy-expr
|
|
stmt ...)
|
|
#:contracts ([thy-expr theory/c])]{ Executes the statements on the theory given by @racket[thy-expr]. Returns the answers to the final query as a list of substitution dictionaries or returns @racket[empty]. }
|
|
|
|
@defform[(datalog! thy-expr
|
|
stmt ...)
|
|
#:contracts ([thy-expr theory/c])]{ Executes the statements on the theory given by @racket[thy-expr]. Prints the answers to every query in the list of statements. Returns @racket[(void)]. }
|
|
|
|
Statements are either assertions, retractions, or queries.
|
|
|
|
@defform[(! clause)]{ Asserts the clause. }
|
|
@defform[(~ clause)]{ Retracts the literal. }
|
|
|
|
@defform[(:- literal question ...)]{ A conditional clause. }
|
|
|
|
@defform[(? question)]{ Queries the literal and prints the result literals. }
|
|
|
|
Questions are either literals or external queries.
|
|
|
|
Literals are represented as @racket[identifier] or @racket[(table term ...)].
|
|
|
|
A table is either an identifier or @RACKET[#,expr] where @racket[expr]
|
|
evaluates to a symbol.
|
|
|
|
External queries are represented as @racket[(ext-table term ... :-
|
|
term ...)], where @racket[ext-table] is an identifier bound to a
|
|
procedure or @RACKET[#,expr] where @racket[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 @RACKET[#,expr] where @racket[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:
|
|
|
|
@racketblock[
|
|
(datalog (make-theory)
|
|
(! (:- (loop X)
|
|
(add1 X :- Z)
|
|
(loop Z)))
|
|
(? (loop 1)))
|
|
]
|