views:

175

answers:

2

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)?

+3  A: 

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.)

Kilian Foth
Great answer, thanks! Any chance you could give me a pointer on my second edit of the question, with `'|'`?
Ambrose
Yes, except that in SWI Prolog (and probably others) the second '|' isn't interpreted as '.'.
RD1
+1  A: 

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.)

RD1
Oh, right! So `[a|b|c]` is syntactic sugar for `'.'(a,(b'|'c))`! So the `|` operator differs from `::` in that the tail doesn't strictly need to be a list, just a "thing"? I'm still trying to swallow what exactly it means for a language to **not** have types...
Ambrose
Technically the `'.'` and the `'|'` are the operators. Both can be applied to any two terms to create a kind a pair - unlike `::` in F#/ML where the type checker makes sure `::` is only used for pairs of a head and corresponding tail.`'.'` is nearly always used for lists though, and the syntax `[t1, t2 | t3]` is an abbreviation for `'.'(t1, '.'(t2, t3))`. If the `t3` is actually `t4 | t5` then that `|` isn't part of the abbreviation, so you get `'.'(t1, '.'(t2, (t4'|'t5)))`.
RD1