7
votes

I am reading http://cs.union.edu/~striegnk/learn-prolog-now/html/node3.html#subsec.l1.kb1, but I am having trouble running the following predicate:

SICStus 4.0.1 (x86-win32-nt-4): Tue May 15 21:17:49 WEST 2007
| ?- woman(mia).
! Existence error in user:woman/1
! procedure user:woman/1 does not exist
! goal:  user:woman(mia)
| ?- 

If, on the other hand, I write it to a file and run consult the file, it seems to work fine...

Am I only allowed to define predicates in a file having later to consult them? Can't I just do it in the editor itself?

2

2 Answers

8
votes

You should enter woman(mia). into a file to assert it as a fact. If you write it into the interpreter, it's taken as a query, not a fact.

From the SWI Prolog FAQ:

Terms that you enter at the toplevel are processes as queries, while terms that appear in a file that is loaded into Prolog is processed as a set of rules and facts. If a text reads as below, this is a rule.

carnivore(X) :- animal(X), eats_meat(X).

Trying to enter this at the toplevel results in the error below. Why? Because a rule is a term :-(Head, Body), and because the toplevel interprets terms as queries. There is no predicate with the name :- and two arguments.

?- carnivore(X) :- animal(X), eats_meat(X). ERROR: Undefined
procedure: (:-)/2 ERROR:   Rules must be loaded from a file ERROR:  
See FAQ at http://www.swi-prolog.org/FAQ/ToplevelMode.txt

Isn't this stupid? Well, no. Suppose we have a term eats_meat(rataplan). If this appears in a file, it states the fact that rataplan eats meat. If it appears at the toplevel, it asks Prolog to try proving whether rataplan eats meat.

If a text reads

:- use_module(library(clpfd)).

This is a directive. Directives are similar to queries, but instead of asking the toplevel to do something, they ask the compiler to do something. Like rules and facts, such terms belong in files.

Instead of writing to a file you can also use assert in the toplevel (as explained later in the FAQ as well).

12
votes

It's a little annoying to make predicates in the repl. You could do

| ?- ['user'].
woman(mia).
^D

ie consult user input, or

| ?- assertz(woman(mia)).

assert it. Both awkward IMO -- there might be a better way, though, I just don't know it. In general it is easier to use a script.