"Raclog" -> "Racklog"

This commit is contained in:
Eli Barzilay 2010-05-18 23:47:31 -04:00
parent c9f359a3c4
commit 14cfb73902
23 changed files with 194 additions and 194 deletions

View File

@ -673,8 +673,8 @@ plt-extras :+= (package: "plai/")
plt-extras :+= (package: "rackunit/")
plt-extras :+= (package: "schemeunit/")
;; -------------------- raclog (aka schelog)
plt-extras :+= (package: "raclog/")
;; -------------------- racklog (aka schelog)
plt-extras :+= (package: "racklog/")
;; ============================================================================
;; Readme header

View File

@ -1153,7 +1153,7 @@ path/s is either such a string or a list of them.
"collects/racket/gui.rkt" drdr:command-line (gracket "-t" *)
"collects/racket/match" responsible (samth)
"collects/racket/match.rkt" responsible (samth)
"collects/raclog" responsible (jay)
"collects/racklog" responsible (jay)
"collects/raco" responsible (mflatt)
"collects/raco/main.rkt" drdr:command-line #f
"collects/raco/raco.rkt" drdr:command-line #f
@ -1674,7 +1674,7 @@ path/s is either such a string or a list of them.
"collects/tests/racket/will.rktl" drdr:command-line (racket "-f" *)
"collects/tests/racket/zo-marshal.rktl" drdr:command-line #f
"collects/tests/racket/ztest.rktl" drdr:command-line #f
"collects/tests/raclog" responsible (jay)
"collects/tests/racklog" responsible (jay)
"collects/tests/rackunit" responsible (jay noel)
"collects/tests/run-automated-tests.rkt" drdr:command-line (mzc "-k" *) drdr:timeout 600
"collects/tests/scribble" responsible (eli mflatt)

View File

@ -0,0 +1,4 @@
#lang setup/infotab
(define scribblings
'(("racklog.scrbl" (multi-page) (tool))))

View File

@ -0,0 +1,3 @@
#lang racket
(require "racklog.rkt")
(provide (all-from-out "racklog.rkt"))

View File

@ -17,11 +17,11 @@
(syntax-rules ()
((%or g ...)
(lambda (__fk)
(let/raclog-cc __sk
(let/raclog-cc __fk
(__sk ((logic-var-val* g) __fk)))
...
(__fk 'fail))))))
(let/racklog-cc __sk
(let/racklog-cc __fk
(__sk ((logic-var-val* g) __fk)))
...
(__fk 'fail))))))
(define-syntax %and
(syntax-rules ()
@ -48,18 +48,18 @@
((%rel (v ...) ((a ...) subgoal ...) ...)
(lambda __fmls
(lambda (__fk)
(let/raclog-cc __sk
(let ((this-! (lambda (fk1) __fk)))
(syntax-parameterize
([! (make-rename-transformer #'this-!)])
(%let (v ...)
(let/raclog-cc __fk
(let* ((__fk ((%= __fmls (list a ...)) __fk))
(__fk ((logic-var-val* subgoal) __fk))
...)
(__sk __fk)))
...
(__fk 'fail))))))))))
(let/racklog-cc __sk
(let ((this-! (lambda (fk1) __fk)))
(syntax-parameterize
([! (make-rename-transformer #'this-!)])
(%let (v ...)
(let/racklog-cc __fk
(let* ((__fk ((%= __fmls (list a ...)) __fk))
(__fk ((logic-var-val* subgoal) __fk))
...)
(__sk __fk)))
...
(__fk 'fail))))))))))
(define %fail
(lambda (fk) (fk 'fail)))
@ -110,8 +110,8 @@
(define ((make-negation p) . args)
;basically inlined cut-fail
(lambda (fk)
(if (let/raclog-cc k
((apply p args) (lambda (d) (k #f))))
(if (let/racklog-cc k
((apply p args) (lambda (d) (k #f))))
(fk 'fail)
fk)))
@ -142,8 +142,8 @@
(define (%not g)
(lambda (fk)
(if (let/raclog-cc k
((logic-var-val* g) (lambda (d) (k #f))))
(if (let/racklog-cc k
((logic-var-val* g) (lambda (d) (k #f))))
(fk 'fail) fk)))
(define (%empty-rel . args)
@ -190,15 +190,15 @@
(define (make-bag-of-aux kons fvv lv goal bag)
(lambda (fk)
(let/raclog-cc sk
(let ((lv2 (cons fvv lv)))
(let* ((acc '())
(fk-final
(lambda (d)
(sk ((separate-bags fvv bag acc) fk))))
(fk-retry (goal fk-final)))
(set! acc (kons (logic-var-val* lv2) acc))
(fk-retry 'retry))))))
(let/racklog-cc sk
(let ((lv2 (cons fvv lv)))
(let* ((acc '())
(fk-final
(lambda (d)
(sk ((separate-bags fvv bag acc) fk))))
(fk-retry (goal fk-final)))
(set! acc (kons (logic-var-val* lv2) acc))
(fk-retry 'retry))))))
(define (separate-bags fvv bag acc)
(let ((bags (let loop ((acc acc)
@ -235,30 +235,30 @@
(define-syntax %which
(syntax-rules ()
((%which (v ...) g)
(with-raclog-prompt
(%let (v ...)
(set-box! *more-fk*
((logic-var-val* g)
(lambda (d)
(set-box! *more-fk* #f)
(abort-to-raclog-prompt #f))))
(abort-to-raclog-prompt
(list (cons 'v (logic-var-val* v))
...)))))))
(with-racklog-prompt
(%let (v ...)
(set-box! *more-fk*
((logic-var-val* g)
(lambda (d)
(set-box! *more-fk* #f)
(abort-to-racklog-prompt #f))))
(abort-to-racklog-prompt
(list (cons 'v (logic-var-val* v))
...)))))))
(define (%more)
(with-raclog-prompt
(if (unbox *more-fk*)
((unbox *more-fk*) 'more)
#f)))
(with-racklog-prompt
(if (unbox *more-fk*)
((unbox *more-fk*) 'more)
#f)))
(define raclog-prompt-tag (make-continuation-prompt-tag 'raclog))
(define (abort-to-raclog-prompt a)
(abort-current-continuation raclog-prompt-tag (λ () a)))
(define-syntax-rule (with-raclog-prompt e ...)
(call-with-continuation-prompt (λ () e ...) raclog-prompt-tag))
(define-syntax-rule (let/raclog-cc k e ...)
(call-with-current-continuation (λ (k) e ...) raclog-prompt-tag))
(define racklog-prompt-tag (make-continuation-prompt-tag 'racklog))
(define (abort-to-racklog-prompt a)
(abort-current-continuation racklog-prompt-tag (λ () a)))
(define-syntax-rule (with-racklog-prompt e ...)
(call-with-continuation-prompt (λ () e ...) racklog-prompt-tag))
(define-syntax-rule (let/racklog-cc k e ...)
(call-with-current-continuation (λ (k) e ...) racklog-prompt-tag))
(define (%member x y)
(%let (xs z zs)

View File

@ -1,31 +1,31 @@
#lang scribble/manual
@(require scribble/eval
(for-syntax racket)
(for-label raclog
(for-label racklog
(except-in racket _)))
@(define raclog-eval (make-base-eval))
@(raclog-eval '(require raclog))
@(define racklog-eval (make-base-eval))
@(racklog-eval '(require racklog))
@title{@bold{Raclog}: Prolog-Style Logic Programming in Racket}
@title{@bold{Racklog}: Prolog-Style Logic Programming in Racket}
@author{Dorai Sitaram}
@margin-note{Adapted from Schelog by Dorai Sitaram for Racket by Dorai Sitaram, John Clements, and Jay McCarthy.}
@defmodule[raclog]
@defmodule[racklog]
Raclog is an @emph{embedding} of
Racklog is an @emph{embedding} of
Prolog-style logic programming in Racket. ``Embedding''
means you don't lose Racket: You can use Prolog-style and
conventional Racket code fragments alongside each other.
Raclog contains the full repertoire of Prolog features,
Racklog contains the full repertoire of Prolog features,
including meta-logical and second-order (``set'')
predicates, leaving out only those features that could more
easily and more efficiently be done with Racket
subexpressions.
The Raclog implementation uses the approach to logic
The Racklog implementation uses the approach to logic
programming for Scheme described in Felleisen @cite{mf:prolog} and
Haynes @cite{logick}. In contrast to earlier Lisp simulations of
Prolog @cite{campbell},
@ -34,18 +34,18 @@ arguments to store failure (backtrack) information, the
Felleisen and Haynes model uses the implicit reified
continuations of Scheme. In Racket these are provided by the operator
@racket[call-with-current-continuation] (aka @racket[call/cc]). This
allows Raclog to be an @emph{embedding}, ie, logic
allows Racklog to be an @emph{embedding}, ie, logic
programming is not built as a new language on top of Racket,
but is used alongside Racket's other features. Both styles
of programming may be mixed to any extent that a project
needs.
The Raclog user does not need to know about the
The Racklog user does not need to know about the
implementation mechanism or about @racket[call/cc] and
continuations to get on with the business of
doing logic programming with Raclog.
doing logic programming with Racklog.
This text is a gentle introduction to Raclog syntax
This text is a gentle introduction to Racklog syntax
and programming. It assumes a working knowledge of
Racket and an awareness of, if not actual programming
experience with, Prolog. If you need assistance for Prolog,
@ -57,9 +57,9 @@ online documents available.
@section[#:tag "simple"]{Simple Goals and Queries}
Raclog objects are the same as Racket objects. However, there
Racklog objects are the same as Racket objects. However, there
are two subsets of these objects that are of special
interest to Raclog: @emph{goals} and @emph{predicates}. We
interest to Racklog: @emph{goals} and @emph{predicates}. We
will first look at some simple goals.
@secref{predicates} will introduce predicates and ways
of making complex goals using predicates.
@ -69,7 +69,7 @@ goal that turns out to be true is said to succeed.
A goal that turns out to be false is said to
fail.
Two simple goals that are provided in Raclog are:
Two simple goals that are provided in Racklog are:
@racketblock[
%true
%fail
@ -78,13 +78,13 @@ Two simple goals that are provided in Raclog are:
The goal @racket[%true] succeeds. The goal @racket[%fail]
always fails.
(The names of all Raclog primitive objects
(The names of all Racklog primitive objects
start with @litchar{%}. This is to avoid clashes with the names
of conventional Racket objects of related meaning.
User-created objects in Raclog are not required to
User-created objects in Racklog are not required to
follow this convention.)
A Raclog user can @emph{query} a goal by wrapping it in a
A Racklog user can @emph{query} a goal by wrapping it in a
@racket[%which]-form.
@racketblock[
@ -110,14 +110,14 @@ Henceforth, we will use the notation:
to say that @racket[E] @emph{evaluates to} @racket[F]. Thus,
@interaction[#:eval raclog-eval (%which () %true)]
@interaction[#:eval racklog-eval (%which () %true)]
@section[#:tag "predicates"]{Predicates}
More interesting goals are created by applying a special
kind of Raclog object called a @emph{predicate} (or
kind of Racklog object called a @emph{predicate} (or
@emph{relation}) to other
Raclog objects. Raclog comes with some primitive
Racklog objects. Racklog comes with some primitive
predicates, such as the arithmetic operators
@racket[%=:=] and @racket[%<],
standing for arithmetic ``equal'' and ``less than''
@ -125,7 +125,7 @@ respectively. For example, the following are some goals
involving these predicates:
@interaction[
#:eval raclog-eval
#:eval racklog-eval
(%which () (%=:= 1 1))
(%which () (%< 1 2))
(%which () (%=:= 1 2))
@ -138,23 +138,23 @@ Other arithmetic predicates are
@racket[%>=] (``greater than or equal''), and
@racket[%=/=] (``not equal'').
Raclog predicates are not to be confused with conventional
Racket predicates (such as @racket[<] and @racket[=]). Raclog
Racklog predicates are not to be confused with conventional
Racket predicates (such as @racket[<] and @racket[=]). Racklog
predicates, when applied to arguments, produce goals
that
may either succeed or fail. Racket predicates, when applied
to arguments, yield a boolean value. Henceforth, we will
use the term ``predicate'' to mean Raclog predicates.
use the term ``predicate'' to mean Racklog predicates.
Conventional predicates will be explicitly called ``Racket
predicates''.
@subsection[#:tag "facts"]{Predicates Introducing Facts}
Users can create their own predicates using the Raclog form
Users can create their own predicates using the Racklog form
@racket[%rel]. For example, let's
define the predicate @racket[%knows]:
@racketblock+eval[#:eval raclog-eval
@racketblock+eval[#:eval racklog-eval
(define %knows
(%rel ()
[('Odysseus 'TeX)]
@ -181,7 +181,7 @@ will be true.
We can now get answers for the following types of queries:
@interaction[#:eval raclog-eval
@interaction[#:eval racklog-eval
(%which ()
(%knows 'Odysseus 'TeX))
(%which ()
@ -193,7 +193,7 @@ We can now get answers for the following types of queries:
Predicates can be more complicated than the above bald
recitation of facts. The predicate clauses can be @emph{rules}, eg,
@racketblock+eval[#:eval raclog-eval
@racketblock+eval[#:eval racklog-eval
(define %computer-literate
(%rel (person)
[(person)
@ -218,7 +218,7 @@ can be used within the body of the @racket[%rel].
The following query can now be answered:
@interaction[#:eval raclog-eval
@interaction[#:eval racklog-eval
(%which ()
(%computer-literate 'Penelope))
]
@ -227,13 +227,13 @@ Since Penelope knows TeX and Prolog, she is computer-literate.
@subsection[#:tag "solving-goals"]{Solving Goals}
The above queries are yes/no questions. Raclog programming
The above queries are yes/no questions. Racklog programming
allows more: We can formulate a goal with @emph{uninstantiated}
logic variables and then ask the querying process to
provide, if possible, values for these variables that cause
the goal to succeed. For instance, the query:
@interaction[#:eval raclog-eval
@interaction[#:eval racklog-eval
(%which (what)
(%knows 'Odysseus what))
]
@ -251,24 +251,24 @@ variable, @racket[_what]. In general, the second subform of
bindings, one for each logic variable mentioned in its
second subform. Thus,
@interaction[#:eval raclog-eval
@interaction[#:eval racklog-eval
(%which (what)
(%knows 'Odysseus what))
]
But that is not all that wily Odysseus knows. Raclog
But that is not all that wily Odysseus knows. Racklog
provides a zero-argument procedure (``thunk'') called
@racket[%more]
that @emph{retries} the goal in the last
@racket[%which]-query for a different solution.
@interaction[#:eval raclog-eval
@interaction[#:eval racklog-eval
(%more)
]
We can keep pumping for more solutions:
@interaction[#:eval raclog-eval
@interaction[#:eval racklog-eval
(%more)
(%more)
(%more)
@ -282,10 +282,10 @@ else.
@subsection[#:tag "assert"]{Asserting Extra Clauses}
We can add more clauses to a predicate after it has already
been defined with a @racket[%rel]. Raclog provides the
been defined with a @racket[%rel]. Racklog provides the
@racket[%assert!] form for this purpose. Eg,
@racketblock+eval[#:eval raclog-eval
@racketblock+eval[#:eval racklog-eval
(%assert! %knows ()
[('Odysseus 'archery)])
]
@ -294,31 +294,31 @@ tacks on a new clause at the end of the existing clauses
of the @racket[%knows]
predicate. Now, the query:
@interaction[#:eval raclog-eval
@interaction[#:eval racklog-eval
(%which (what)
(%knows 'Odysseus what))
]
gives TeX, Racket, Prolog, and Penelope, as before, but
a subsequent @racket[(%more)] yields a new result:
@interaction-eval[#:eval raclog-eval (begin (%more) (%more) (%more))]
@interaction[#:eval raclog-eval
@interaction-eval[#:eval racklog-eval (begin (%more) (%more) (%more))]
@interaction[#:eval racklog-eval
(%more)
]
The Raclog form @racket[%assert-after!] is similar to @racket[%assert!] but
The Racklog form @racket[%assert-after!] is similar to @racket[%assert!] but
adds clauses @emph{before} any of the current clauses.
Both @racket[%assert!] and @racket[%assert-after!] assume that the variable
they are adding to already names a predicate (presumably
defined using @racket[%rel]).
In order to allow defining a predicate entirely through
@racket[%assert!]s, Raclog provides an empty predicate value
@racket[%assert!]s, Racklog provides an empty predicate value
@racket[%empty-rel]. @racket[%empty-rel] takes any number of arguments
and always fails. A typical use of the
@racket[%empty-rel] and @racket[%assert!] combination:
@racketblock+eval[#:eval raclog-eval
@racketblock+eval[#:eval racklog-eval
(define %parent %empty-rel)
(%assert! %parent ()
@ -329,7 +329,7 @@ and always fails. A typical use of the
[('Penelope 'Telemachus)])
]
(Raclog does not provide a predicate for @emph{retracting}
(Racklog does not provide a predicate for @emph{retracting}
assertions, since we can keep track of older versions of
predicates using conventional Racket features (@racket[let] and @racket[set!]).)
@ -337,20 +337,20 @@ predicates using conventional Racket features (@racket[let] and @racket[set!]).)
The local logic variables of @racket[%rel]- and
@racket[%which]-expressions are in reality introduced by the
Raclog syntactic form called @racket[%let]. (@racket[%rel] and
Racklog syntactic form called @racket[%let]. (@racket[%rel] and
@racket[%which] are macros written using @racket[%let].)
@racket[%let] introduces new lexically scoped logic variables.
Supposing, instead of
@interaction[#:eval raclog-eval
@interaction[#:eval racklog-eval
(%which (what)
(%knows 'Odysseus what))
]
we had asked
@interaction[#:eval raclog-eval
@interaction[#:eval racklog-eval
(%let (what)
(%which ()
(%knows 'Odysseus what)))
@ -362,9 +362,9 @@ bindings only for the local variables that @emph{it}
introduces. Thus, this query emits @racketresult[()] five times before
@racket[(%more)] finally returns @racket[#f].
@section[#:tag "racket-w-logic"]{Using Conventional Racket Expressions in Raclog}
@section[#:tag "racket-w-logic"]{Using Conventional Racket Expressions in Racklog}
The arguments of Raclog predicates can be any Racket
The arguments of Racklog predicates can be any Racket
objects. In particular, composite structures such as lists,
vectors, strings, hash tables, etc can be used, as also Racket expressions
using the full array of Racket's construction and
@ -406,7 +406,7 @@ a @racket[%member] goal.
Note that the variable @racket[y] in the definition of
@racket[%member] occurs only once in the second clause. As such,
it doesn't need you to make the effort of naming it. (Names
help only in matching a second occurrence to a first.) Raclog
help only in matching a second occurrence to a first.) Racklog
lets you use the expression @racket[(_)] to denote an anonymous
variable. (Ie, @racket[_] is a thunk that generates a fresh
anonymous variable at each call.) The predicate @racket[%member] can be
@ -423,14 +423,14 @@ rewritten as
@subsection[#:tag "constructors"]{Constructors}
We can use constructors --- Racket procedures for creating
structures --- to simulate data types in Raclog. For
structures --- to simulate data types in Racklog. For
instance, let's define a natural-number data-type where
@racket[0] denotes zero, and @racket[(succ x)] denotes the natural number
whose immediate predecessor is @racket[x]. The constructor
@racket[succ] can
be defined in Racket as:
@racketblock+eval[#:eval raclog-eval
@racketblock+eval[#:eval racklog-eval
(define succ
(lambda (x)
(vector 'succ x)))
@ -438,7 +438,7 @@ be defined in Racket as:
Addition and multiplication can be defined as:
@racketblock+eval[#:eval raclog-eval
@racketblock+eval[#:eval racklog-eval
(define %add
(%rel (x y z)
[(0 y y)]
@ -456,7 +456,7 @@ Addition and multiplication can be defined as:
We can do a lot of arithmetic with this in place. For
instance, the factorial predicate looks like:
@racketblock+eval[#:eval raclog-eval
@racketblock+eval[#:eval racklog-eval
(define %factorial
(%rel (x y y1)
[(0 (succ 0))]
@ -471,9 +471,9 @@ The above is a very inefficient way to do arithmetic,
especially when the underlying language Racket offers
excellent arithmetic facilities (including a comprehensive
number ``tower'' and exact rational arithmetic). One
problem with using Racket calculations directly in Raclog
problem with using Racket calculations directly in Racklog
clauses is that the expressions used may contain logic
variables that need to be dereferenced. Raclog provides
variables that need to be dereferenced. Racklog provides
the predicate @racket[%is] that takes care of this. The goal
@racketblock[
@ -489,7 +489,7 @@ may not be palatable values to the Racket operators used in
We can now directly use the numbers of Racket to write a
more efficient @racket[%factorial] predicate:
@racketblock+eval[#:eval raclog-eval
@racketblock+eval[#:eval racklog-eval
(define %factorial
(%rel (x y x1 y1)
[(0 1)]
@ -505,7 +505,7 @@ constraint. In fact, given this limitation, there is
nothing to prevent us from using Racket's factorial
directly:
@racketblock+eval[#:eval raclog-eval
@racketblock+eval[#:eval racklog-eval
(define %factorial
(%rel (x y)
[(x y)
@ -517,7 +517,7 @@ or better yet, ``in-line'' any calls to @racket[%factorial] with
@racket[%is]-expressions calling @racket[racket-factorial], where the
latter is defined in the usual manner:
@racketblock+eval[#:eval raclog-eval
@racketblock+eval[#:eval racklog-eval
(define racket-factorial
(lambda (n)
(if (= n 0) 1
@ -531,7 +531,7 @@ One can use Racket's lexical scoping to enhance predicate
definition. Here is a list-reversal predicate defined using
a hidden auxiliary predicate:
@racketblock+eval[#:eval raclog-eval
@racketblock+eval[#:eval racklog-eval
(define %reverse
(letrec
([revaux
@ -557,7 +557,7 @@ contour. We use @racket[letrec] instead of @racket[let] because
@subsection[#:tag "type-predicates"]{Type Predicates}
Raclog provides a couple of predicates that let the user
Racklog provides a couple of predicates that let the user
probe the type of objects.
The goal
@ -573,7 +573,7 @@ checks if its argument is not an atomic object.
The above are merely the logic-programming equivalents of
corresponding Racket predicates. Users can use the
predicate @racket[%is] and Racket predicates to write more type
checks in Raclog. Thus, to test if @racket[_X] is a string, the
checks in Racklog. Thus, to test if @racket[_X] is a string, the
following goal could be used:
@racketblock[
@ -589,7 +589,7 @@ It is helpful to go into the following evaluation (@secref{rules})
in a
little detail:
@racketblock+eval[#:eval raclog-eval
@racketblock+eval[#:eval racklog-eval
(%which ()
(%computer-literate 'Penelope))
]
@ -605,7 +605,7 @@ G0 = (%computer-literate Penelope)
(I've taken out the quote because @racketresult[Penelope] is the result
of evaluating @racket['Penelope].)
Raclog tries to match this with the head of the first
Racklog tries to match this with the head of the first
clause of @racket[%computer-literate]. It succeeds, generating a
binding @racket[[person . Penelope]].
@ -619,29 +619,29 @@ G1 = (%knows Penelope TeX)
G2 = (%knows Penelope Racket)
]
For @goal{G1}, Raclog attempts matches with the clauses of
For @goal{G1}, Racklog attempts matches with the clauses of
@racket[%knows], and succeeds at the fifth try. (There are no
subgoals in this case, because the bodies of these ``fact''
clauses are empty, in contrast to the ``rule'' clauses of
@racket[%computer-literate].)
Raclog then tries to solve @goal{G2} against the clauses of
Racklog then tries to solve @goal{G2} against the clauses of
@racket[%knows], and since there is no clause stating that
Penelope knows Racket, it fails.
All is not lost though. Raclog now @emph{backtracks} to the
All is not lost though. Racklog now @emph{backtracks} to the
goal that was solved just before, viz., @goal{G1}. It
@emph{retries} @goal{G1}, ie, tries to solve it in a
different way.
This entails searching down the previously unconsidered
@racket[%knows]
clauses for @goal{G1}, ie, the sixth onwards. Obviously,
Raclog fails again, because the fact that Penelope knows
Racklog fails again, because the fact that Penelope knows
TeX occurs only once.
Raclog now backtracks to the goal before @goal{G1}, ie,
Racklog now backtracks to the goal before @goal{G1}, ie,
@goal{G0}. We abandon the current successful match with the
first clause-head of @racket[%computer-literate], and try the
next clause-head. Raclog succeeds, again producing a binding
next clause-head. Racklog succeeds, again producing a binding
@racket[[person . Penelope]], and two new subgoals:
@racketblock[
@ -649,13 +649,13 @@ G3 = (%knows Penelope TeX)
G4 = (%knows Penelope Prolog)
]
It is now easy to trace that Raclog finds both @goal{G3} and @goal{G4} to be
It is now easy to trace that Racklog finds both @goal{G3} and @goal{G4} to be
true. Since both of @goal{G0}'s subgoals are true, @goal{G0} is
itself considered true. And this is what Raclog reports. The
itself considered true. And this is what Racklog reports. The
interested reader can now trace why the
following query has a different denouement:
@interaction[#:eval raclog-eval
@interaction[#:eval racklog-eval
(%which ()
(%computer-literate 'Telemachus))
]
@ -664,7 +664,7 @@ following query has a different denouement:
When we say that a goal matches with a clause-head, we mean
that the predicate and argument positions line up. Before
making this comparison, Raclog dereferences all already
making this comparison, Racklog dereferences all already
bound logic variables. The resulting structures are then
compared to see if they are recursively identical. Thus,
@racket[1] unifies with @racket[1], and @racket[(list 1 2)] with @racket['(1 2)]; but @racket[1] and
@ -679,20 +679,20 @@ variable, unifies with @racket['(0 1)], producing the
binding
@racket[[_x 0]].
Unification is thus a goal, and Raclog makes the unification predicate
Unification is thus a goal, and Racklog makes the unification predicate
available to the user as @racket[%=]. Eg,
@interaction[#:eval raclog-eval
@interaction[#:eval racklog-eval
(%which (x)
(%= (list x 1) '(0 1)))
]
Raclog also provides the predicate @racket[%/=], the @emph{negation} of
Racklog also provides the predicate @racket[%/=], the @emph{negation} of
@racket[%=]. @racket[(%/= _X _Y)] succeeds if and only if @racket[_X] does
@emph{not} unify with @racket[_Y].
Unification goals constitute the basic subgoals that all
Raclog goals devolve to. A goal succeeds because all the
Racklog goals devolve to. A goal succeeds because all the
eventual unification subgoals that it decomposes to in at
least one of its subgoal-branching succeeded. It fails
because every possible subgoal-branching was thwarted by the
@ -722,10 +722,10 @@ other hand, performing the occurs check greatly
increases the time taken by unification, even in cases
that wouldn't require the check.
Raclog uses the global parameter
Racklog uses the global parameter
@racket[use-occurs-check?] to decide whether to
use the occurs check. By default, this variable is
@racket[#f], ie, Raclog disables the occurs check. To
@racket[#f], ie, Racklog disables the occurs check. To
enable the check,
@racketblock[
@ -739,7 +739,7 @@ and @racket[%or]
to form compound goals. (For @racket[%not], see @secref{not}.)
Eg,
@interaction[#:eval raclog-eval
@interaction[#:eval racklog-eval
(%which (x)
(%and (%member x '(1 2 3))
(%< x 3)))
@ -750,7 +750,7 @@ argument goals of the @racket[%and].
Ie, @racket[_x] should both be a member of @racket['(1 2 3)]
@emph{and} be less than @racket[3]. Typing @racket[(%more)] gives another solution:
@interaction[#:eval raclog-eval
@interaction[#:eval racklog-eval
(%more)
(%more)
]
@ -760,7 +760,7 @@ the first but not the second goal.
Similarly, the query
@interaction[#:eval raclog-eval
@interaction[#:eval racklog-eval
(%which (x)
(%or (%member x '(1 2 3))
(%member x '(3 4 5))))
@ -768,7 +768,7 @@ Similarly, the query
lists all @racket[_x] that are members of either list.
@interaction[#:eval raclog-eval
@interaction[#:eval racklog-eval
(%more)
(%more)
(%more)
@ -781,7 +781,7 @@ lists all @racket[_x] that are members of either list.
We can rewrite the predicate @racket[%computer-literate]
from @secref{rules} using @racket[%and] and @racket[%or]:
@racketblock+eval[#:eval raclog-eval
@racketblock+eval[#:eval racklog-eval
(define %computer-literate
(%rel (person)
[(person)
@ -798,7 +798,7 @@ from @secref{rules} using @racket[%and] and @racket[%or]:
Or, more succinctly:
@racketblock+eval[#:eval raclog-eval
@racketblock+eval[#:eval racklog-eval
(define %computer-literate
(%rel (person)
[(person)
@ -812,7 +812,7 @@ Or, more succinctly:
We can even dispense with the @racket[%rel] altogether:
@racketblock+eval[#:eval raclog-eval
@racketblock+eval[#:eval racklog-eval
(define %computer-literate
(lambda (person)
(%and (%knows person
@ -827,9 +827,9 @@ This last looks like a conventional Racket predicate
definition, and is arguably
the most readable format for a Racket programmer.
@section[#:tag "lv-manip"]{Manipulating Raclog Variables}
@section[#:tag "lv-manip"]{Manipulating Racklog Variables}
Raclog provides special predicates for probing logic
Racklog provides special predicates for probing logic
variables, without risking their getting bound.
@subsection[#:tag "var"]{Checking for Variables}
@ -862,7 +862,7 @@ The predicate @racket[%nonvar] is the negation of @racket[%var].
@subsection[#:tag "freeze"]{Preserving Variables}
Raclog lets the user protect a term with variables from
Racklog lets the user protect a term with variables from
unification by allowing that term to be treated as a
(completely) bound object. The predicates provided for this
purpose are
@ -910,19 +910,19 @@ followed by @racket[(%melt-new _F _C)].
The cut (called @racket[!]) is a special goal that is used to
prune backtracking options. Like the @racket[%true] goal, the
cut goal too succeeds, when accosted by the Raclog
cut goal too succeeds, when accosted by the Racklog
subgoaling engine. However, when a further subgoal down the
line fails, and time comes to retry the cut goal, Raclog
line fails, and time comes to retry the cut goal, Racklog
will refuse to try alternate clauses for the predicate in
whose definition the cut occurs. In other words, the cut
causes Raclog to commit to all the decisions made from the
causes Racklog to commit to all the decisions made from the
time that the predicate was selected to match a subgoal till
the time the cut was satisfied.
For example, consider again the @racket[%factorial]
predicate, as defined in @secref{is}:
@racketblock+eval[#:eval raclog-eval
@racketblock+eval[#:eval racklog-eval
(define %factorial
(%rel (x y x1 y1)
[(0 1)]
@ -933,7 +933,7 @@ predicate, as defined in @secref{is}:
Clearly,
@interaction[#:eval raclog-eval
@interaction[#:eval racklog-eval
(%which ()
(%factorial 0 1))
(%which (n)
@ -963,7 +963,7 @@ Calling @racket[%factorial] with a @emph{negative} number would still cause an
infinite loop. To take care of that problem as well, we
use another cut:
@racketblock+eval[#:eval raclog-eval
@racketblock+eval[#:eval racklog-eval
(define %factorial
(%rel (x y x1 y1)
[(0 1) !]
@ -973,7 +973,7 @@ use another cut:
(%is y (* y1 x))]))
]
@interaction[#:eval raclog-eval
@interaction[#:eval racklog-eval
(%which ()
(%factorial 0 1))
(%more)
@ -991,7 +991,7 @@ are the conditional and negation.
An ``if ... then ... else ...'' predicate can be defined
as follows
@racketblock+eval[#:eval raclog-eval
@racketblock+eval[#:eval racklog-eval
(define %if-then-else
(%rel (p q r)
[(p q r) p ! q]
@ -1030,7 +1030,7 @@ Another common abstraction using the cut is @emph{negation}.
The negation of goal @goal{G} is defined as @racket[(%not G)], where
the predicate @racket[%not] is defined as follows:
@racketblock+eval[#:eval raclog-eval
@racketblock+eval[#:eval racklog-eval
(define %not
(%rel ()
[(g) g ! %fail]
@ -1055,7 +1055,7 @@ unifies with @racket[_Bag] the list of all instantiations of
asks for all the things known --- ie, the collection of things
such that someone knows them:
@interaction[#:eval raclog-eval
@interaction[#:eval racklog-eval
(%which (things-known)
(%let (someone x)
(%bag-of x (%knows someone x)
@ -1064,7 +1064,7 @@ such that someone knows them:
This is the only solution for this goal:
@interaction[#:eval raclog-eval
@interaction[#:eval racklog-eval
(%more)
]
@ -1074,7 +1074,7 @@ TeX. To remove duplicates, use the predicate
@racket[%set-of]
instead of @racket[%bag-of]:
@interaction[#:eval raclog-eval
@interaction[#:eval racklog-eval
(%which (things-known)
(%let (someone x)
(%set-of x (%knows someone x)
@ -1090,7 +1090,7 @@ set-predicate goal. We can do it too with some additional
syntax that identifies the free variable.
Eg,
@interaction[#:eval raclog-eval
@interaction[#:eval racklog-eval
(%which (someone things-known)
(%let (x)
(%bag-of x
@ -1104,18 +1104,18 @@ returned. That someone is Odysseus. The query can be
retried for more solutions, each listing the things known by
a different someone:
@interaction[#:eval raclog-eval
@interaction[#:eval racklog-eval
(%more)
(%more)
(%more)
(%more)
]
Raclog also provides two variants of these set predicates,
Racklog also provides two variants of these set predicates,
viz., @racket[%bag-of-1] and @racket[%set-of-1]. These act like @racket[%bag-of]
and @racket[%set-of] but fail if the resulting bag or set is empty.
@section[#:tag "glossary"]{Glossary of Raclog Primitives}
@section[#:tag "glossary"]{Glossary of Racklog Primitives}
@(define-syntax (defpred stx)
(syntax-case stx ()
@ -1133,13 +1133,13 @@ and @racket[%set-of] but fail if the resulting bag or set is empty.
@defproc[(atomic-struct? [x any/c]) boolean?]{Identifies structures that the @scheme[(current-inspector)] cannot inspect.}
@defproc[(atom? [x any/c]) boolean?]{Identifies atomic values that may appear in Raclog programs. Equivalent to the contract @racket[(or/c boolean? number? string? bytes? char? symbol? regexp? pregexp? byte-regexp? byte-pregexp? keyword? null? procedure? void? set? atomic-struct?)].}
@defproc[(atom? [x any/c]) boolean?]{Identifies atomic values that may appear in Racklog programs. Equivalent to the contract @racket[(or/c boolean? number? string? bytes? char? symbol? regexp? pregexp? byte-regexp? byte-pregexp? keyword? null? procedure? void? set? atomic-struct?)].}
@defproc[(compound-struct? [x any/c]) boolean?]{Identifies structures that the @scheme[(current-inspector)] can inspect.}
@defproc[(compound? [x any/c]) boolean?]{Identifies compound values that may appear in Raclog programs. Equivalent to the contract @racket[(or/c pair? vector? mpair? box? hash? compound-struct?)].}
@defproc[(compound? [x any/c]) boolean?]{Identifies compound values that may appear in Racklog programs. Equivalent to the contract @racket[(or/c pair? vector? mpair? box? hash? compound-struct?)].}
@defproc[(unifiable? [x any/c]) boolean?]{Identifies values that may appear in Raclog programs. Essentialy either an @racket[atom?], @racket[logic-var?], or @racket[compound?] that contains @scheme[unifiable?]s.}
@defproc[(unifiable? [x any/c]) boolean?]{Identifies values that may appear in Racklog programs. Essentialy either an @racket[atom?], @racket[logic-var?], or @racket[compound?] that contains @scheme[unifiable?]s.}
@defproc[(answer-value? [x any/c]) boolean?]{Identifies values that may appear in @racket[answer?]. Essentially @racket[unifiable?]s that do not contain @racket[logic-var?]s.}
@ -1196,7 +1196,7 @@ local logic variables for @racket[clause], ....}
Like @racket[%assert!], but adds the new clauses to the @emph{front}
of the existing predicate.}
@subsection{Raclog Variables}
@subsection{Racklog Variables}
@defproc[(_) logic-var?]{
A thunk that produces a new logic variable. Can be
@ -1217,10 +1217,10 @@ Introduces a cut point. See @secref{cut}.}
@defidform[!]{
The cut goal, see @secref{cut}.
May only be used syntactically inside @racket[%cut-delimiter] or @racket[%rel].}
@subsection{Raclogal Operators}
@subsection{Racklog Operators}
@defgoal[%fail]{
The goal @racket[%fail] always fails.}
@ -1277,7 +1277,7 @@ Fails if @racket[E2] contains unbound logic variables.}
@defparam[use-occurs-check? on? boolean?]{
If this is false (the default),
Raclog's unification will not use the occurs check.
Racklog's unification will not use the occurs check.
If it is true, the occurs check is enabled.}
@subsection{Numeric Predicates}
@ -1343,7 +1343,7 @@ the occurrences of the variables @racket[V], ..., in goal
@racket[G] as free. It is used to avoid existential quantification
in calls to set predicates (@racket[%bag-of], @racket[%set-of], &c.).}
@subsection{Raclog Predicates}
@subsection{Racklog Predicates}
@defpred[(%compound [E unifiable?])]{
The goal @racket[(%compound E)] succeeds if @racket[E] is a compound
@ -1363,7 +1363,7 @@ it.}
The goal @racket[(%nonvar E)] succeeds if @racket[E] is completely
instantiated, ie, it has no unbound variable in it.}
@subsection{Raclog Variable Manipulation}
@subsection{Racklog Variable Manipulation}
@defpred[(%freeze [S unifiable?] [F unifiable?])]{
The goal @racket[(%freeze S F)] unifies with @racket[F] a new frozen
@ -1423,4 +1423,4 @@ frozen structure in @racket[F].}
#:title "Transliterating Prolog into Scheme"
#:location "Indiana U Comp Sci Dept Tech Report #182"
#:date "1985"]
]
]

View File

@ -1,4 +0,0 @@
#lang setup/infotab
(define scribblings
'(("raclog.scrbl" (multi-page) (tool))))

View File

@ -1,3 +0,0 @@
#lang racket
(require "raclog.rkt")
(provide (all-from-out "raclog.rkt"))

View File

@ -1,6 +1,6 @@
#lang racket
(require raclog
(require racklog
rackunit)
;The following is the "Biblical" database from "The Art of

View File

@ -1,6 +1,6 @@
#lang racket
(require raclog
(require racklog
rackunit)
;The following is a simple database about a certain family in England.

View File

@ -1,6 +1,6 @@
#lang racket
(require raclog)
(require racklog)
;The following is a simple database about a certain family in England.
;Should be a piece of cake, but given here so that you can hone

View File

@ -1,5 +1,5 @@
#lang racket
(require raclog tests/eli-tester)
(require racklog tests/eli-tester)
(define %factorial
(%rel (x y x1 y1)
@ -23,4 +23,4 @@
(%factorial 3 x))
=> `((x . 6))
(%more)
=> #f)
=> #f)

View File

@ -1,6 +1,6 @@
#lang racket
(require raclog
(require racklog
"./puzzle.rkt"
rackunit)

View File

@ -1,6 +1,6 @@
#lang racket
(require raclog
(require racklog
tests/eli-tester)
;This is a very trivial program. In Prolog, it would be:

View File

@ -1,6 +1,6 @@
#lang racket
(require raclog)
(require racklog)
;Exercise 14.1 (iv) from Sterling & Shapiro, p. 217-8

View File

@ -1,12 +1,12 @@
#lang racket
(require (except-in raclog %member))
(require (except-in racklog %member))
;map coloring, example from Sterling & Shapiro, p. 212
;(%member x y) holds if x is in y
;; is this different from the %member provided by raclog? fencing that one out.
;; is this different from the %member provided by racklog? fencing that one out.
(define %member
(%rel (X Xs Y Ys)

View File

@ -1,6 +1,6 @@
#lang racket
(require raclog)
(require racklog)
(provide (all-defined-out))

View File

@ -1,9 +1,9 @@
#lang racket
(require (except-in raclog %append))
(require (except-in racklog %append))
;A list of trivial programs in Prolog, just so you can get used
;to raclog syntax.
;to racklog syntax.
;(%length l n) holds if length(l) = n

View File

@ -1,5 +1,5 @@
#lang racket
(require raclog
(require racklog
tests/eli-tester)
(test
@ -557,4 +557,4 @@
(%which () (%let (x) (%var 1))) => #f
(%which () (%let (x) (%and (%= x 1) (%var x)))) => #f
)
)