1
votes

Prolog's grammar uses a <head> :- <body> format for rules as such:

tree(G) :- acyclic(G) , connected(G). , denoting status of G as a tree depends on status as acyclic and connected.

This grammar can be extended in an implicit fashion to facts. Following the same example:

connected(graphA) suggests connected(graphA):-true.

In this sense, one might loosely define Prolog facts as Prolog rules that are always true.

My question: Is in any context a bodiless rule (one that is presumed to be true under all conditions) ever appropriate? Syntactically such a rule would look as follows.

graph(X). (suggesting graph(X):-true.)

4
Using your terminology, what is the difference between a "bodiless rule" and a "fact"?user1812457
Example of bodiless rule: blah(X). Example of fact (bodiless by definition): blah(a). Note the use of a variable for the argument of the first.David Shaked
I did remember at least one valid use for such rules: see my answer below.user1812457
What about this definition is "loose"?Scott Hunter
@ScottHunter, not all rules that are always presumed to be true (in other words, have no bodies) qualify as facts. For instance, the recursive case in my answer below (member) is bodiless but not a fact. In other words, a bodiless rule does not a fact make. The definition is loose in that facts are only partially defined.David Shaked

4 Answers

3
votes

Before answering, to rephrase your question:

In Prolog, would you ever write a rule with nothing but anonymous variables in the head, and no body?

The terminology is kind of important here. Facts are simply rules that have only a head and no body (which is why your question is a bit confusing). Anonymous variables are variables that you explicitly tell the compiler to ignore in the context of a predicate clause (a predicate clause is the syntactical scope of a variable). If you did try to give this predicate clause to the Prolog compiler:

foo(Bar).

you will get a "singleton variable" warning. Instead, you can write

foo(_).

and this tells the compiler that this argument is ignored on purpose, and no variable binding should be attempted with it.

Operationally, what happens when Prolog tries to prove a rule?

  • First, unification of all arguments in the head of the rule, which might lead to new variable bindings;
  • Then, it tries to prove the body of the rule using all existing variable bindings.

As you can see, the second step makes this a recursively defined algorithm: proving the body of a rule means proving each rule in it.

To come to your question: what is the operational meaning of this:

foo(_).

There is a predicate foo/1, and it is true for any argument, because there are no variable bindings to be done in the head, and always, because no subgoals need to be proven.

I have seen at least one use of such a rule: look at the very bottom of this section of the SWI-Prolog manual. The small code example goes like this:

term_expansion(my_class(_), Clauses) :-
        findall(my_class(C),
                string_code(_, "~!@#$", C),
                Clauses).

my_class(_).

You should read the linked documentation to see the motivation for doing this. The purpose of the code itself is to add at compile time a table of facts to the Prolog database. This is done by term expansion, a mechanism for code transformations, usually used through term_expansion/2. You need the definition of my_class/1 so that term_expansion/2 can pick it up, transform it, and replace it with the expanded code. I strongly suggest you take the snipped above, put it in a file, consult it and use listing/1 to see what is the effect. I get:

?- listing(my_class).
my_class(126).
my_class(33).
my_class(64).
my_class(35).
my_class(36).

true.

NB: In this example, you could replace the two occurrences of my_class(_) with anything. You could have just as well written:

term_expansion(foobar, Clauses) :-
        findall(my_class(C),
                string_code(_, "~!@#$", C),
                Clauses).

foobar.

The end result is identical, because the operational meaning is identical. However, using my_class(_) is self-documenting, and makes the intention of the code more obvious, at least to an experienced Prolog developer as the author of SWI-Prolog ;).

3
votes

A fact is just a bodiless rule, as you call it. And yes, there are plenty of use cases for bodiless facts:

  1. representing static data
  2. base cases for recursion
  3. instead of some curly brace language pseudo code

    boolean is_three(integer x) {
        if (x == 3) { return  true; }
        else        { return false; }
    }
    

    we can simply write

    is_three(3).
    
1
votes

This is often how the base case of a recursive definition is expressed.

0
votes

To highlight what I was initially looking for, I'll include the following short answer for those who might find themselves asking my initial question in the future.

An example of a bodiless rule is, as @Anniepoo suggested, a base case for a recursive definition. Look to the example of a predicate, member(X,L) for illustration:

member(X,[X|T]). /* recursive base case*/
member(X,[H|T]):- member(X,T).

Here, the first entry of the member rule represents a terminating base case-- the item of interest X matching to the head of the remaining list.

I suggest visiting @Boris's answer (accepted) for a more complete treatment.