What is Prolog saying about an uninstantiated variable?

Say we were to execute the following, and SWI Prolog responds:

?- write(X).
_13074
true.

What is _13074? Is this an address? Is this an ID of some sort? I notice that we'll get a different value each time. Furthermore, why does Prolog report true.? Is this Prolog saying that anything can be unified with X? Why do these appear in the order they do?

If we were to unify X with, say, 1, then the result is different.

?- X = 1, write(X).
1
X = 1.

Solution 1:

What is _13074?

The simplest answer is that it represents an uninstantiated variable.

To be more precise from the Prolog Standard

anonymous variable: A variable (represented in a term or Prolog text by _) which differs from every other variable (and anonymous variable) (see 6.1.2, 6.4.3)

instantiated: A variable is instantiated with respect to substitution if application of the substitution yields an atomic term or a compound term.

A term is instantiated if any of its variables are instantiated.

uninstantiated: A variable is uninstantiated when it is not instantiated.

variable: An object which may be instantiated to a term during execution.

named variable: A variable which is not an anonymous variable (see 6.1.2, 6.4.3)

So obviously all of that is self referential but in short by the standard there are anonymous variables _ and named variables, E.g. X, Y, Ls.

Note that the standard does not say what is the difference between _ and variables with numbers in the suffix, E.g. _13074. Those are implementation specific.

The standard does note for writing a term,

7.10.5 Writing a term

When a term Term is output using write-term/3 (8.14.2) the action which is taken is defined by the rules below:

a) If Term is a variable, a character sequence representing that variable is output. The sequence begins with _ (underscore) and the remaining characters are implementation dependent. The same character sequence is used for each occurrence of a particular variable in Term. A different character sequence is used for each distinct variable in Term.

Since you specifically mention SWI-Prolog there are other variable caveats to be aware of:

  1. named singleton variables AKA auxiliary variables

Named singletons start with a double underscore (__) or a single underscore followed by an uppercase letter, E.g., __var or _Var.

  1. Attribute variables - provide a technique for extending the Prolog unification algorithm Holzbaur, 1992 by hooking the binding of attributed variables. There is no consensus in the Prolog community on the exact definition and interface to attributed variables. The SWI-Prolog interface is identical to the one realised by Bart Demoen for hProlog Demoen, 2002. This interface is simple and available on all Prolog systems that can run the Leuven CHR system (see chapter 9 and the Leuven CHR page).

  2. Global variables - are associations between names (atoms) and terms.

I don't plan to dive deeper into variables as one has to start looking at SWI-Prolog C level source code to really get a more accurate understanding, (ref). I also don't plan to add more from the standard as one would eventually have to reproduce the entire standard here just to cover all of the references.

For more definitions from the Prolog standard see: Is this Prolog terminology correct? (fact, rule, procedure, predicate, ...) The answer is a community wiki so most users can add to it and the OP does not get the points, so upvote all you want.


Is this an address?

No

Sometimes you will also see logic variable used but I don't plan to expand on that here, however for the record SWI-Prolog is NOT based on WAM it is based on A Portable Prolog Compiler.

See above 7.10.5 Writing a term


Is this an ID of some sort?

I would not argue with that in a causal conversation about SWI-Prolog but there is enough problems with that simple analogy to split hairs and start a discussion/debate, E.g. can a blob be assigned to a variable? What is numbervars?

See above 7.10.5 Writing a term


I notice that we'll get a different value each time.

The Prolog standard uses the word occurrence.

See above 7.10.5 Writing a term


why does Prolog report true.?

Prolog is a logic language which executes queries (goal) that result in either true or false or the instantiated values of variables, however there can be side effects such as writing to a file, throwing exceptions, etc.

The Prolog standard states

A.2.1.1 The General Resolution Algorithm

The general resolution of a goal G of a database P is defined by the following non-deterministic algorithm:
a) Start with the initial goal G which is an ordered conjunction of predications.
b) If G is the singleton true then stop (success).
c) Choose a predication A in G (predication-choice)
d) If A is true, delete it, and proceed to step (b).
e) If no renamed clause in P has a head which unifies with A then stop (failure).
f) Choose a freshly renamed clause in P whose head H unifies with A (clause-choice) where σ = MGU(H, A) and B is the body of the clause,
g) Replace in G the predication A by the body B, flatten and apply the substitution σ.
h) Proceed to step (b).

Also see:
Resolution
MGU


Is this Prolog saying that anything can be unified with X?

For very simple Prolog implementations (ref) then the question would make sense. In the real world and even more so with SWI-Prolog were the rubber meets the road I would have to say not in all cases.

For most Prolog code syntactic unification is what is driving what is happening. See: A.2.1.1 The General Resolution Algorithm above. However if you start to think about things like blobs, attributes, threads, exceptions, and so on then you really have to look at what is a variable, even the kind of variable and what that variable can do , E.g.

?- X is true.
ERROR: Arithmetic: `true/0' is not a function
ERROR: In:
ERROR:   [10] _4608 is true
ERROR:    [9] toplevel_call(user:user: ...) at c:/program files/swipl/boot/toplevel.pl:1117
?- trie_new(A_trie).
A_trie = <trie>(0000000006E71DB0).

?- write(X).
_13074
true.

Why do these appear in the order they do?

write(X). is the goal entered by the user.

The goal is executed which in this case has the side effect of writing to the current output stream stream, E.g. current_output/1, the variable X which for SWI-Prolog for this occurrence of X is uninstantiated and is displayed as _13074.

The logic query ends and the result of the query being logical is either true or false. Since the query executed successfully the result is true.


If we were to unify X with, say, 1, then the result is different.

?- X = 1, write(X).
1
X = 1.

I will presume you are asking why there is no true at the end.

IIRC with SWI-Prolog, if the query starts with a variable and then the query succeeds with the variable being instantiated that will be reported and no true or false will then appear, E.g.

?- X = 1.
X = 1.
?- current_prolog_flag(double_quotes,V).
V = string.
?- X = 1, Y = 1, X = Y.
X = Y, Y = 1.

If however the query succeeds and no variable was instantiated then the query will report true E.g.

?- 1 = 1.
true.
?- current_prolog_flag(double_quotes,string).
true.

If the the query fails the query will report false E.g.

?- X = 1, Y = 2, X = Y.
false.
?- current_prolog_flag(quotes,String).
false.

I suspect this much information will now have you asking for more details but I won't go much deeper than this as SO is not a place to give a lecture condensed into an answer. I will try to clarify what is written but if it needs a lot more detail expect to be requested to post a new separate question.

I know the info from the standard presented here leaves lots of lose ends. If you really want the details from the standard then purchase the standard as those of us who have have done. I know it is not cheap but for questions like this it is the source of the answers.