Skip to content

Command line

The clausal command runs a Clausal Prolog (.clausal) or ISO Prolog (.pl) program. It is installed with the package (pip install clausal); python -m clausal is the same command.

clausal [-g GOAL]... [--once] [--test] FILE [-- ARGS...]
clausal                      # no FILE: the interactive REPL

Running a program

Given only a file, clausal loads it and runs main/0:

% hello.clausal
:- module(hello, []).

main :- write('Hello, world'), nl.

:- end_module(hello).
$ clausal hello.clausal
Hello, world

The exit status is 0 when main succeeds and 1 when it fails or raises. main/0 need not be exported. A program with no main/0 is only loaded, so clausal lib.clausal is a quick load check: it reports a syntax or load error and exits 1, or exits 0.

Clausal Prolog refuses :- initialization(...), so main/0 is the entry point by name.

Running goals: -g

-g GOAL runs a goal in the program's module, instead of main/0, and prints each answer the way a Prolog toplevel does:

$ clausal family.clausal -g "grandparent(tom, X)"
X = ann.
X = pat.
$ clausal family.clausal -g "grandparent(tom, ann)"
true.
$ clausal family.clausal -g "grandparent(ann, X)"
false.
  • -g can be given more than once; the goals run in order.
  • --once (or -1) prints only the first answer of each goal.
  • Variables whose names start with _ are not printed. A variable left unbound is not printed on its own, and appears by its name inside other answers (S = f(X)).
  • A rational prints as Scryer prints it: X is 1 rdiv 2 answers X = 1 rdiv 2.
  • CLP(Q) constraints left on the answer's variables are printed after the bindings, projected onto those variables:
:- use_module(library(clpq)).
dependent(X, Y) :- {X + Y = 3, 2*X + 2*Y = 6}.
between_1_3(X) :- {X > 1, X < 3}.
$ clausal lin.clausal -g "dependent(X, Y)"
{X + Y = 3}.
$ clausal lin.clausal -g "between_1_3(X)"
{X > 1}, {X < 3}.

When projecting would take too long (many constraints linking many variables the answer does not show), the constraints are printed as they are stored, over internal variables named _Q1, _Q2, …: still the whole answer, just not simplified.

A strict bound that passes through a variable the answer does not show is printed as non-strict ({X < Y, Y =< 3} shows X as {X =< 3}), and a value that the constraints force is shown as constraints, not as a binding.

Other constraints (clpz, freeze/2, dif/2) are not printed yet. - A goal can use the operators the program has: its own op/3 directives and those of the libraries it imports, such as #= after :- use_module(library(clpz)). - A goal that fails prints false. and ends the run with status 1. A goal that raises prints the error term on standard error and exits 1. A goal that does not parse is a usage error, status 2.

Running tests: --test

clausal --test FILE runs the program's test/1 and test/2 clauses, the same as python -m clausal.testing FILE. See Testing.

Program arguments: --

Everything after -- is passed to the program, as a list of atoms in the read-only argv flag:

main :- current_prolog_flag(argv, Args), write(Args), nl.
$ clausal echo.clausal -- one two 3
[one,two,3]

Each argument is an atom, so the 3 above is the atom '3', not a number. Without --, argv is [].

Exit status

Status Meaning
0 main/0 or every -g goal succeeded, the tests passed, or the program loaded
1 a goal failed or raised, a test failed, or the program did not load
2 a usage error: a missing or unsupported FILE, a goal that does not parse, conflicting options

--test returns the test runner's own statuses; see Testing.