Using Prolog with AllegroGraph | AllegroGraph 9.0.1
Author: Franz Incorporated

Copyright (c) 2005 - 2026 Franz, Incorporated
Last updated 27 May 2026 at 10:34

# Using Prolog with AllegroGraph 9.0.1

- Documentation Index
  - Release Notes
  - Quick Start
  - SSL/TLS Quick Start
  - Introduction
  - Setup and Configuration
    - Download
    - Server Installation
    - Server Configuration and Control
    - WebView
    - Database Upgrading
    - Managing Users
  - Server Management
    - Performance Tuning
    - Deleting Duplicate Triples
    - Purging Deleted Triples
    - Auditing
    - Managing Users
    - Replication
    - Point-in-Time Recovery
    - Transaction Log Archiving
    - Security Overview
    - Security Implementation
  - Tools
    - agtool
    - Data Loading
    - Data Export
    - Backup and Restore
    - Querying
    - RDFS++
    - Materializer
    - Event Scheduler
    - SHACL
  - Details
    - Triple Indices
    - Freetext Indices
    - Encoded IDs
    - Connection Pooling
    - N-dimensional Geospatial Overview
    - 2-D Geospatial
    - Temporal
    - Social Network
    - JavaScript
    - Datatypes
    - Data Conversion (Rapper)
    - Stored Procedures
    - Triple Attributes
    - Lineparse Format
  - Querying
    - SPARQL documentation summary
    - SPARQL Reference
    - SPIN
    - SPARQL Magic Properties
    - Prolog
  - 3rd-party tools
    - Solr text Indices
    - MongoDB integration
    - TopBraid Composer Plugin
    - Cloudera
  - Client APIs
    - Gruff
    - GraphTalker
    - REST/HTTP interface
    - HTTP reference
    - Javadocs (Sesame and Jena)
    - Python API
    - Lisp Reference
    - JavaScript
  - Tutorials
    - N-dimensional Geospatial
    - SPARQL Tutorial
    - Java Sesame
    - Java Jena
    - Python Sesame
    - Lisp
    - Prolog
    - More...
  - Other
    - Conferences and Seminars
    - Source Code on Github
    - Amazon EC2
    - Copyrights
  - Franz, Inc.

- Introduction
  - Prolog Notation
  - Sample data and setup
  - Extending Prolog: Defining new predicates
  - Problem with use of ! in Prolog code

Documentation Index

## Introduction

If you are new to Prolog, we would suggest that you complete this tutorial and then study the Allegro Prolog documentation if you would like more details. The prolog operators in AllegroGraph are documented in the Lisp Reference. A note on the differences between using SPARQL and using Prolog for queries can be found in the SPARQL Reference.

This is a basic tutorial on how to use Prolog with AllegroGraph 9.0.1. It should be enough to get you going but if you have any questions please contact Franz Support for assistance. In this tutorial we will focus mainly on how to use the following constructs:

- select
- q-
- q
- <--
- <-
- ??
- !

Because a Prolog query may be used to evaluate arbitrary Lisp code, executing Prolog queries requires eval permission. User permissions are discussed in the section Managing Users in the WebView document.

### Prolog Notation

When consulting the Reference Guide, one should understand the conventions for documenting Prolog predicates (which are Prolog operators, also called functors). Here we repeat some of what we say in the Reference Guide, and add an example.

A Prolog predicate call (in Lisp syntax) looks like a regular Lisp function call; the symbol naming the predicate being the first element of the list and the remaining elements being arguments. But arguments to a Prolog predicate call can either be supplied as input to the call, or unsupplied (that is specified as a variable rather than a value) so that the clause might return possible values for that argument as a result by unifying some data to it, or may be a tree of nodes containing both ground data and Prolog variables, as shown in the example below. Thus we must distinguish, in the predicate documentation, between arguments which must be specified with a value, those which must be a variable, and those which can be either. We will describe the notation for doing so after an example to show what we mean by specifying values or variables.

The following example uses the predicate `append` which has three arguments and succeeds for any solution where the third argument is the same as the first two arguments appended. The remarkable thing about Prolog semantics is that append is a declarative relation that works regardless of which arguments are supplied as inputs (values) and which are supplied as outputs (specified as variables). The example uses a Prolog interpreter. Results are displayed one at a time. `<ret>`, indicating the user pressing Return, causes Prolog to find the next result if there is one, or to print No if there is not. The symbols whose names start with ? are variables. (This example uses simple expressions to illustrate Prolog calls and what we mean by saying arguments can be specified as values or variables. Calls used in association with AllegroGraph are more complex and generally return lists of result triples rather than results one at a time.)

        > (?- (append (1 2) (3) ?z))  ;; Asks what values of ?z
                                      ;; will satisfy the call
        ?z = (1 2 3)
        <ret>
        No.
                                      ;; Only ?z = (1 2 3) works.

        > (?- (append (1 2) ?y (1 2 3))) ;; Asks what values of ?y
                                         ;; will satisfy the call
        ?y = (3)
        <ret>
        No.                              ;; Again, only one possibility

        > (?- (append ?x ?y (1 2 3)))    ;; What values of ?x and ?y
                                         ;; will work? There are four
                                         ;; possibilities:
        ?x = ()
        ?y = (1 2 3)
        <ret>
        ?x = (1)
        ?y = (2 3)
        <ret>
        ?x = (1 2)
        ?y = (3)
        <ret>
        ?x = (1 2 3)
        ?y = ()
        <ret>
        No.                    ;; And no more

        > (?- (append ? (1 ?next . ?) (1 2 1 3 4 1 5 1)))
        ?next = 2
        <ret>
        ?next = 3
        <ret>
        ?next = 5
        <ret>
        No.

The last example successively unifies to each element in the list immediately preceded by a `1`. It shows the power of unification against a partially ground tree structure.

Now back to notation: see the Prolog section of the Lisp Reference Guide for full details, but in short a `+` prefix on an argument in the argument list in documentation indicates that the argument must be supplied as a value (it is input to the predicate), a `-` prefix indicates the argument is output and must not be supplied (should be a variable), and a ± prefix indicates the argument may be either.

Also sometimes names ending in a /N, where N is a number, will appear in Prolog documentation and in the debugger: for example parent/2. This is the predicate/arity syntax. The portion of that notation that is the predicate name, parent in this example, is the same as the Lisp symbol naming the predicate. The non-negative integer after the slash is the arity, which is the number of arguments to the predicate. Two predicates with the same predicate name but different arities are completely different predicates. In the example later in this tutorial the predicate parent/1 has no relation to the parent/2 predicate which it calls.

### Sample data and setup

This tutorial will be based on a tiny genealogy database of the Kennedy family.

Please open the file `kennedy.ntriples` that came with this distribution (it will be in the tutorial sub-directory of the Lisp client) in a text editor or with TopBraidComposer and study the contents of the file. Notice that people in this file have a type, sometimes multiple children, multiple spouses, multiple professions, and attended multiple colleges or universities.

First let us get AllegroGraph ready to use. It is assumed here that you have started the AllegroGraph server and know how to load your favorite Lisp client into your running Lisp. (See the Quick Start for more details):

    ;; We've removed the output of the following forms
    > :ld [agraph client directory]/agraph.fasl

    > (in-package :triple-store-user)

    > (enable-!-reader)

    > (enable-print-decoded t)

    > (register-namespace "ex" "http://franz.com/simple#" :errorp nil)

Now we can create a triple-store and load it with data. The function create-triple-store creates a new triple-store and opens it. If you use the triple-store name "test", then AllegroGraph will create a triple-store named `test` in the root catalog. The following three forms will create the store and load the data. They work as written only with the direct Lisp client. If you are using a remote client, again see the Quick Start for more details about the :port, :user, and :password arguments to create-triple-store.

    > (create-triple-store "test" :if-exists :supersede)
    > (load-ntriples #p"sys:agraph;tutorial-files;kennedy.ntriples")
    > (commit-triple-store)
    ;; .... output deleted.

So let us first look at `person1` in this database:

    > (print-triples
       (get-triples-list :s !ex:person1))
    <http://franz.com/simple#person1> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://franz.com/simple#person> .
    <http://franz.com/simple#person1> <http://franz.com/simple#first-name> <http://franz.com/simple#Joseph> .
    <http://franz.com/simple#person1> <http://franz.com/simple#middle-initial> <http://franz.com/simple#Patrick> .
    <http://franz.com/simple#person1> <http://franz.com/simple#last-name> <http://franz.com/simple#Kennedy> .
    <http://franz.com/simple#person1> <http://franz.com/simple#birth-year> <http://franz.com/simple#1888> .
    <http://franz.com/simple#person1> <http://franz.com/simple#death-year> <http://franz.com/simple#1969> .
    <http://franz.com/simple#person1> <http://franz.com/simple#sex> <http://franz.com/simple#male> .
    <http://franz.com/simple#person1> <http://franz.com/simple#spouse> <http://franz.com/simple#person2> .
    <http://franz.com/simple#person1> <http://franz.com/simple#suffix> <http://franz.com/simple#none> .
    <http://franz.com/simple#person1> <http://franz.com/simple#has-child> <http://franz.com/simple#person9> .
    <http://franz.com/simple#person1> <http://franz.com/simple#has-child> <http://franz.com/simple#person13> .
    <http://franz.com/simple#person1> <http://franz.com/simple#has-child> <http://franz.com/simple#person17> .
    <http://franz.com/simple#person1> <http://franz.com/simple#has-child> <http://franz.com/simple#person4> .
    <http://franz.com/simple#person1> <http://franz.com/simple#has-child> <http://franz.com/simple#person6> .
    <http://franz.com/simple#person1> <http://franz.com/simple#has-child> <http://franz.com/simple#person15> .
    <http://franz.com/simple#person1> <http://franz.com/simple#has-child> <http://franz.com/simple#person11> .
    <http://franz.com/simple#person1> <http://franz.com/simple#has-child> <http://franz.com/simple#person3> .
    <http://franz.com/simple#person1> <http://franz.com/simple#has-child> <http://franz.com/simple#person7> .
    <http://franz.com/simple#person1> <http://franz.com/simple#profession> <http://franz.com/simple#producer> .
    <http://franz.com/simple#person1> <http://franz.com/simple#profession> <http://franz.com/simple#banker> .
    <http://franz.com/simple#person1> <http://franz.com/simple#profession> <http://franz.com/simple#ambassador> .
    <http://franz.com/simple#person1> <http://franz.com/simple#alma-mater> <http://franz.com/simple#Harvard> .

Now we are ready to try a select statement in combination with the Prolog q- predicate. Let us try to find all the children of `person1`. Start by typing the following in the listener (the explanation follows).

    > (select (?x)
       (q- !ex:person1 !ex:has-child ?x))

    ;; produces output:
    (("http://franz.com/simple#person9")
     ("http://franz.com/simple#person13")
     ("http://franz.com/simple#person17")
     ("http://franz.com/simple#person4")
     ("http://franz.com/simple#person6")
     ("http://franz.com/simple#person15")
     ("http://franz.com/simple#person11")
     ("http://franz.com/simple#person3")
     ("http://franz.com/simple#person7"))

`select` is a wrapper used around one or more Prolog clauses. The first element after `select` is a template for the format and variables that you want to bind and return. So in this example we want to bind the Prolog variable `?x`. The remaining concatenation of clauses tell Prolog how to constrain the binding of `?x` in the result set.

This select form has only one clause, namely `(q- !ex:person1 !ex:has-child ?x)`.

If you have studied how get-triples works you will have already guessed that `q-` is its Prolog analogue. `q-` calls `get-triples` and unifies the `?x` with the objects of all triples with subject `!ex:person1` and predicate `!ex:has-child`. 1

To make things more complex, let us find all the children of the children of person1:

    > (select (?y)
       (q- !ex:person1 !ex:has-child ?x)
       (q- ?x !ex:has-child ?y))

    ;; produces output:
    (("http://franz.com/simple#person33")
     ("http://franz.com/simple#person26")
     ("http://franz.com/simple#person28")
     ("http://franz.com/simple#person31")
     ("http://franz.com/simple#person25")
     ("http://franz.com/simple#person62")
     ("http://franz.com/simple#person56")
     ("http://franz.com/simple#person42")
     ("http://franz.com/simple#person47")
     ("http://franz.com/simple#person51") ...)

Although Prolog is a declarative language, this query is easy to read procedurally:

Find all triples that have subject `!ex:person1` and predicate `!ex:has-child`. For each match unify `?x` to the object of that triple; then for each triple that has subject `?x` and predicate `!ex:has-child` return the object.

Next, we will try to find all the spouses of the grandchildren of `!ex:person1`. Notice that `select` does not return information about the variables `?x` and`?y` in the query. The select template will return only the `?z` because that is what is in the list which is the first argument.

    > (select (?z)
       (q- !ex:person1 !ex:has-child ?x)
       (q- ?x !ex:has-child ?y)
       (q- ?y !ex:spouse ?z))

    ;; produces output:
    (("http://franz.com/simple#person34")
     ("http://franz.com/simple#person27")
     ("http://franz.com/simple#person30")
     ("http://franz.com/simple#person32")
     ("http://franz.com/simple#person63")
     ("http://franz.com/simple#person57")
     ("http://franz.com/simple#person43")
     ("http://franz.com/simple#person49")
     ("http://franz.com/simple#person48")
     ("http://franz.com/simple#person52") ...)

Now if you wanted to you could get the other variables back. Here is the same query that also returns the grandchild.

    > (select (?y ?z)
        (q- !ex:person1 !ex:has-child ?x)
        (q- ?x !ex:has-child ?y)
        (q- ?y !ex:spouse ?z))

    ;; produces output:
    (("http://franz.com/simple#person33" "http://franz.com/simple#person34")
     ("http://franz.com/simple#person26" "http://franz.com/simple#person27")
     ("http://franz.com/simple#person28" "http://franz.com/simple#person30")
     ("http://franz.com/simple#person31" "http://franz.com/simple#person32")
     ("http://franz.com/simple#person62" "http://franz.com/simple#person63")
     ("http://franz.com/simple#person56" "http://franz.com/simple#person57")
     ("http://franz.com/simple#person42" "http://franz.com/simple#person43")
     ("http://franz.com/simple#person47" "http://franz.com/simple#person49")
     ("http://franz.com/simple#person47" "http://franz.com/simple#person48")
     ("http://franz.com/simple#person51" "http://franz.com/simple#person52")
     ...)

We have covered `select` and `q-` and know how to make basic Prolog queries against a triple-store. Next, we'll see how to use more of Prolog's power:

### Extending Prolog: Defining new predicates

Predicates are defined using `<--` and `<-` (we will explain the difference below). The following defines a predicate that succeeds if its first and only argument is a male, provided the necessary triple is present in the triple store.

    > (<-- (male ?x)
        (q- ?x !ex:sex !ex:male))
    male

Let us try it out by finding all the sons of person1.

    > (select (?x)
        (q- !ex:person1 !ex:has-child ?x)
        (male ?x)) ;;; Note how we use NO q here!
    (("http://franz.com/simple#person13")
     ("http://franz.com/simple#person17")
     ("http://franz.com/simple#person4")
     ("http://franz.com/simple#person3"))

Note that this is equivalent to the more complex query:

    (select (?x)
     (q- !ex:person1 !ex:has-child ?x)
     (q- ?x !ex:sex !ex:male))

We will define some more useful predicates to expand our useful vocabulary:

    > (<-- (female ?x)
        (q- ?x !ex:sex !ex:female))
    female
    > (<-- (father ?x ?y)
        (male ?x)
        (q- ?x !ex:has-child ?y))
    father
    > (<-- (mother ?x ?y)
        (female ?x)
        (q- ?x !ex:has-child ?y))
    mother

The `female`, `father`, and `mother` relations are all simple to understand. We can also create more complicated relations that can be satisfied in more than one way. For example, suppose we want to define the `parent` relation: `?x` is the parent of `?y` if

- `?x` is the father of `?y` or
- `?x` is the mother of `?y.`

In Prolog, this can be implemented as

    > (<-- (parent ?x ?y)
        (father ?x ?y))
    parent
    > (<- (parent ?x ?y)
        (mother ?x ?y))
    parent

Notice how we define the `parent` predicate, which is comprised of two rules: the first rule uses <-- and the second rule uses <-. The reason is that <-- means wipe out all the previous rules and start anew whereas <- means to add to the existing rules for the predicate. The rules for any particular predicate and arity form an ordered set. When that predicate is called, the rules are tried in order.

The `parent` predicate could have been written as a single rule using the `or` predicate. The two are essentially equivalent and a matter of personal preference.

    > (<-- (parent ?x ?y)
        (or (father ?x ?y)
            (mother ?x ?y)))
    parent

Either way, can we use our new predicate to find the grandchildren of person1:

    > (select (?y)
        (parent !ex:person1 ?x)
        (parent ?x ?y))

    ;; produces output
    (("http://franz.com/simple#person33")
     ("http://franz.com/simple#person26")
     ("http://franz.com/simple#person28")
     ("http://franz.com/simple#person31")
     ("http://franz.com/simple#person25")
     ("http://franz.com/simple#person62")
     ("http://franz.com/simple#person56")
     ("http://franz.com/simple#person42")
     ("http://franz.com/simple#person47")
     ("http://franz.com/simple#person51") ...)

We could have done the same thing by defining a grandparent predicate.

    > (<-- (grandparent ?x ?y)
        (parent ?x ?z)
        (parent ?z ?y))
    grandparent
    > (<-- (grandchild ?x ?y)
        (grandparent ?y ?x))
    grandchild

Finally, we can define `ancestor` which is a recursive predicate (i.e. it is defined in terms of itself).

    > (<-- (ancestor ?x ?y)
        (parent ?x ?y))
    ancestor
    > (<-  (ancestor ?x ?y)
        (parent ?x ?z)
        (ancestor ?z ?y))
    ancestor

Read the previous two expressions as

- `?x` is the ancestor of `?y` if
  - `?x` is the parent of `?y` or
  - `?x` is the parent of some person `?z` and `?z` is the ancestor of `?y`

A descendant is of course the reverse of ancestor

    > (<-- (descendant ?x ?y)
        (ancestor ?y ?x))
    descendant

So if we want to find all the male descendants of person1 then here is how to do it.

    > (select (?x)
        (descendant ?x !ex:person1)
        (male ?x))

    ;; produces output:
    (("http://franz.com/simple#person13")
     ("http://franz.com/simple#person17")
     ("http://franz.com/simple#person4")
     ("http://franz.com/simple#person3")
     ("http://franz.com/simple#person33")
     ("http://franz.com/simple#person28")
     ("http://franz.com/simple#person31")
     ("http://franz.com/simple#person25")
     ("http://franz.com/simple#person62")
     ("http://franz.com/simple#person47") ...)

Here are some puzzles that you can work out for yourself. Note the use of `not` and part= in these statements. 'not' can contain any expression. `part=` will compare its two arguments as UPIs.

    > (<-- (aunt ?x ?y)
        (father ?z ?x)
        (female ?x)
        (father ?z ?w)
        (not (part= ?x ?w))
        (parent ?w ?y))
    aunt
    > (<-- (uncle ?x ?y)
        (father ?z ?x)
        (male ?x)
        (father ?z ?w)
        (not (part= ?x ?w))
        (parent ?w ?y))
    uncle

And the final query: find all the children of person1 that are uncles

    > (select (?x ?y)
        (parent !ex:person1 ?x)
        (uncle ?x ?y))
    (("http://franz.com/simple#person13" "http://franz.com/simple#person33")
     ("http://franz.com/simple#person13" "http://franz.com/simple#person26")
     ("http://franz.com/simple#person13" "http://franz.com/simple#person28")
     ("http://franz.com/simple#person13" "http://franz.com/simple#person31")
     ("http://franz.com/simple#person13" "http://franz.com/simple#person25")
     ("http://franz.com/simple#person13" "http://franz.com/simple#person62")
     ("http://franz.com/simple#person13" "http://franz.com/simple#person56")
     ("http://franz.com/simple#person13" "http://franz.com/simple#person42")
     ("http://franz.com/simple#person13" "http://franz.com/simple#person47")
     ("http://franz.com/simple#person13" "http://franz.com/simple#person51")
     ...)

There is another convenient shorthand to know in Allegro Prolog. It is often necessary to use small bits of Lisp code inside a series of Prolog clauses. A typical example is here, where it is necessary inside a sequence of Prolog clauses to retrieve a value from the surrounding Lisp environment. Here we define a Lisp function that returns the first and last name of every person born in the argument year.

        > (defun born-in-year (year)
            (select0 (?first-name ?last-name)
              (lisp ?year (literal (princ-to-string year)))
              (q- ?person !ex:birth-year ?year)
              (q- ?person !ex:first-name ?first-name)
              (q- ?person !ex:last-name ?last-name)))
        born-in-year
        > (born-in-year 1915)
        (({Joseph} {Kennedy}) ({Robert} {Shriver}))
        t

The year argument may be a string or an integer, but we need to convert it to a string since that's the way birth years are stored in this particular database. Then the argument needs to be interned as a literal. But the important point is that we need to get the value of year from the surrounding Lisp environments and bind it to a Prolog variable (here named `?year`) so it can be passed to `q-`.

This necessary transfer of data into the Prolog environment clutters the code and makes it harder to read. The `??` syntax marker can eliminate much of this:

        > (defun born-in-year (year)
            (select0 (?first-name ?last-name)
              (q- ?person !ex:birth-year (?? (literal (princ-to-string year))))
              (q- ?person !ex:first-name ?first-name)
              (q- ?person !ex:last-name ?last-name)))

This is nothing more than a syntactic shorthand of the previous example and operates just like it. It eliminates the need for the Prolog variable to be visible. The body of `??` has syntax like Lisp progn and substitutes at runtime the value computed by the progn body into the Prolog clause.

Another useful Prolog predicate is `optional`. When wrapped around a concatenation of clauses it allows that concatenation to succeed as many times as it would succeed if those clauses had simply been in series at that location. However, if the concatantation does not succeed at least once, the `optional` predicate succeeds a single time without establishing any new variable bindings.

For example, if some of the people in our database did not have first name data, our previous `born-in-year` predicate would not find those people. We could improve this and return `nil` for unknown first names:

        > (defun born-in-year (year)
            (select0 (?first-name ?last-name)
              (q- ?person !ex:birth-year (?? (literal (princ-to-string year))))
              (optional (q- ?person !ex:first-name ?first-name))
              (q- ?person !ex:last-name ?last-name)))

### Problem with use of ! in Prolog code

There is a conflict between the syntax for the Prolog cut (described in the Allegro Prolog Manual) and AllegroGraph's future-part notation (see here). Prolog uses the exclamation point ! to denote the cut predicate. When executed, a cut clears all previous backtracking points within call to the current predicate. For example,

     > (<-- (parent ?x)
          (parent ?x ?)
          !)

defines a predicate that tests whether the argument person is a parent, but if so succeeds only once. (If there are multiple rules for `parent/1` ! cuts all the way back through the choice of the current rule.) The ! is traditional Prolog notation, but AllegroGraph uses the ! character as a reader macro to create a future part, so the above definition will signal a read error when the AllegroGraph readtable is in effect (see the !-reader macro section).

The simplest way to resolve this is to preface the Prolog ! with a backslash in any code that might be read with the AllegroGraph readtable in effect. The backslash suppresses any reader macro for the following character. This adds minimal clutter to the source code, and is completely harmless even when the AllegroGraph readtable is not in effect.

     > (<-- (is-a-parent ?x)
          (parent ?x ?)
          \!)

## Footnotes

1. The q- predicate has many variants to handle the graph slot, range queries, etc. See the Lisp Reference Prolog documentation for details. ↩