Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does [a|b|c] evaluate to in SWI-Prolog?

The pipe operator in prolog returns one or more atomic Heads and a Tail list.

?- [a,b,c] = [a,b|[c]].
true.

Nesting multiple pipes in a single match can be done similar to this:

?- [a,b,c] = [a|[b|[c]]].
true.

What does the statement [a|b|c] infer about a, b and c?

EDIT

So far, all I can deduce is:

?- [a,b,c] = [a|b|c].
false.

I am more interested in any techniques to find the answer rather than to answer this borderline useless question.

EDIT2
I'm clearly not too familiar with prolog, a simple assignment answered my question...

?- R = [a|b|c].
R = [a| (b'|'c)].

What exactly is going on with (b'|'c)?

like image 257
Ambrose Avatar asked Jun 03 '10 15:06

Ambrose


2 Answers

Since I'm your lecturer I, here's my answer.
(Oh, and I can confirm that this isn't homework, it's related to the practice exam).

The syntax [a|b|c] actually doesn't seem to be standard Prolog, and some implementations interpret it differently. (Had I known this I might not have used it.)

Some interpret it as [a|[b|c]]. (As I intended.)

But with SWI Prolog (and probably others):

?- [a|b|c] = [a|[b|c]].
false.

The (b '|' c) is actually constructed using '|' rather than '.' as a list would be. So, the the second | is not interpreted as being part of constructing a list at all.

To confirm this, the following succeeds:

   ?- X=(b|c), [a|b|c] = [a|X].
   X = (b'|'c) .

The '|' here seems to be a another binary operator on terms just like '.'.

Instead of [a|b|c] the standard in Prolog is to use [a,b|c].

(I only decided to use [a|b|c] in Programming Paradigms because it more directly relates to the notation a::b::c from F#, and we only saw a tiny glimpse of Prolog. In future I guess I'll relate to [a|[b|c]] and then give [a,b|c] as an abbreviation.)

like image 123
RD1 Avatar answered Oct 07 '22 09:10

RD1


It isn't a statement, it's a term, and it doesn't imply anything at all about a, b or c. It just constructs an improper list.

To elaborate: The [|] syntax is actually syntactic sugar for the .() operator. Lists are internally constructed via '.'(a,[]), but since that becomes extremely tedious to type right away, you are allowed to write [a] instead. So the . operator is supposed to take a thing and a list and then contructs a longer list, but since there is no typing, nobody prevents you from applying it to two atoms, or any other pair of things. The result is a structure on which some list operations succeed and others fail. This is sometimes useful (think binary trees), but not as common as lists, therefore there is no special read syntax for it.

(Much the same happens with the cons operator in Lisp; if you google "improper list" you are liable to get many more results about Lisp, but the principle is exactly the same.)

like image 44
Kilian Foth Avatar answered Oct 07 '22 09:10

Kilian Foth