3

In Prolog, [H|T] is the list that begins with H and where the remaining elements are in the list T (internally represented with '.'(H, '.'(…))).

Is it possible to define new syntax in a similar fashion? For example, is it possible to define that [T~H] is the list that ends with H and where the remaining elements are in the list T, and then use it as freely as [H|T] in heads and bodies of predicates? Is it also possible to define e.g. <H|T> to be a different structure than lists?

false
  • 10,264
  • 13
  • 101
  • 209
Fatalize
  • 3,513
  • 15
  • 25

2 Answers2

3

One can interpret your question literally. A list-like data structure, where accessing the tail can be expressed without any auxiliary predicate. Well, these are the minus-lists which were already used in the very first Prolog system — the one which is sometimes called Prolog 0 and which was written in Algol-W. An example from the original report, p.32 transliterated into ISO Prolog:

t(X-a-l, X-a-u-x). 

?- t(nil-m-e-t-a-l, Pluriel).
   Pluriel = nil-m-e-t-a-u-x.

So essentially you take any left-associative operator.

But, I suspect, that's not what you wanted. You probably want an extension to lists.

There have been several attempts to do this, one more recent was Prolog III/Prolog IV. However, quite similar to constraints, you will have to face how to define equality over these operators. In other words, you need to go beyond syntactic unification into E-unification. The problem sounds easy in the beginning but it is frightening complex. A simple example in Prolog IV:

>> L = [a] o M, L = M o [z].
M ~ list,
L ~ list.

Clearly this is an inconsistency. That is, the system should respond false. There is simply no such M, but Prolog IV is not able to deduce this. You would have to solve at least such problems or get along with them somehow.

In case you really want to dig into this, consider the research which started with J. Makanin's pioneering work:

The Problem of Solvability of Equations in a Free Semi-Group, Akad. Nauk SSSR, vol.233, no.2, 1977.

That said, it might be the case that there is a simpler way to get what you want. Maybe a fully associative list operator is not needed.

Nevertheless, do not expect too much expressiveness from such an extension compared to what we have in Prolog, that is DCGs. In particular, general left-recursion would still be a problem for termination in grammars.

false
  • 10,264
  • 13
  • 101
  • 209
1

It is possible to extend or redefine syntax of Prolog with iso predicate

 :- op(Precedence, Type, Name).

Where Precedence is a number between 0 and 1200, Type describe if the operatot is used postfix,prefix or infix:

infix: xfx, xfy, yfx
prefix: fx, fy
suffix: xf, yf

and finally name is the operator's name.

Operator definitions do not specify the meaning of an operator, but only describe how it can be used syntactically. It is only a definition extending the syntax of Prolog. It doesn't gives any information about when a predicate will succeed. So you need also to describe when your predicate succeeds. To answer your question and also give an example you could define :

:- op( 42, xfy, [ ~ ]).

where you declare an infix operator [ ~ ]. This doesn't means that is a representation of a list (yet). You could define clause:

[T ~ H]:-is_list([H|T]).

which matches [T~H] with the list that ends with H and where the remaining elements are in the list T.

Note also that it is not very safe to define predefined operators like [ ] or ~ because you overwrite their existing functionality. For example if you want to consult a file like [file]. this will return false because you redefined operators.

coder
  • 12,832
  • 5
  • 39
  • 53
  • 2
    I don't see how `[T~H]` will match with the list that ends with `H` and where the remaining elements are in the list `T`. In fact, it doesn't even match with a list: `?- X = [1,2,3], X = [T~H]. false.`. – Fatalize Oct 26 '16 at 14:22
  • Yes because they are different syntactically but same semantically. As I referred above [T~H] is just a definition of syntax ,it does not says that this is a list. The semantics come from the rule [T ~ H]:-is_list([H|T]). which says [T~H] is a list with head H and tail T if and only if is_list[H|T] so you the syntax [T~H] is true when [H|T] is a list. – coder Oct 26 '16 at 14:28
  • 1
    I still don't see how that answers the question. I want something such that `?- X = [1,2,3], X = [T~H].` returns `H = 3, T = [1,2]` and your answer does not provide that. As I said I don't even know if this is possible without touching the compiler. – Fatalize Oct 26 '16 at 14:33
  • I think you can't do: X = [1,2,3], X = [T~H] because you use unification in syntactically different clauses! Then how would be determined unification. My answer answers the question "is it possible to define that [T~H] is the list" but you have to use [~] r [ | ] syntax and not mixed up.... – coder Oct 26 '16 at 14:36