Initially, there was no [] in the prologue, but vector always built using . .
Here is an example from a 1979 article by David Warren [* 36'footnote]:
([user]) . :- (op(1,'xfy','.')) . concatenated(nil,L,L) . concatenated((X.L1),L2,(X.L3)) :- concatenated(L1,L2,L3) . %^D
testing and demonstration ...
?- ((concatenated((nil),(nil),Z)) , Z == (nil)) . %@ Z = nil ?- ((concatenated((abnil),(cdnil),Z)) , Z == (abcdnil)) . %@ Z = [a,b,c,d|nil]
The above work is done in yap, eclipse, gprolog, xsb. However, this does not work in swipl (see Appendix).
concatenated , as presented in this article, is exactly the same as the implementation of the typical modern time append run, but with a different name and different end marker.
A common pattern is that each element is separated from it by a neighbor through . .
The last element is a marker indicating the end. In Warren's example, nil is a marker that indicates the end. Using nil apparently a convention, but not a requirement. Subsequent developments in the prologue replaced the use of nil as an end marker, using [] as an end marker.
Warren's example can be minimally rewritten to use [] instead of nil ...
([user]) . ((append([] , L , L))) . ( (append((X.L1) , L2 , (X.L3))) ) :- ( (append(L1 , L2 , L3)) ) . %^D /* ((append(([]) , ([]) , Z)) , (Z == [])) . ((append((ab[]),(cd[]),Z)) , Z == (abcd[])) . ((append((ab[]),(cd[]),Z)) , Z == [a,b,c,d]) . ((append(([a,b]),([c,d]),Z)) , Z == [a,b,c,d]) . */ ?- ((append(([]) , ([]) , Z)) , (Z == [])) . %@ Z = [] ?- ((append((ab[]),(cd[]),Z)) , Z == (abcd[])) . %@ Z = [a,b,c,d] ?- ((append((ab[]),(cd[]),Z)) , Z == [a,b,c,d]) . %@ Z = [a,b,c,d] ?- ((append(([a,b]),([c,d]),Z)) , Z == [a,b,c,d]) . %@ Z = [a,b,c,d]
Warren continues ...
... where the list is either the atom 'nil' or a term derived from the binary functor '.' the second argument of which is a list ... we write a functor as the right operator-associative infix, so for example, the first list mentioned by [ed: (abcdnil) ] is equivalent to the standard form .(a,.(b,.(c,.(d,nil))))' (abcdnil) .(a,.(b,.(c,.(d,nil))))'
Warren provides this example ...
([user]) . list(nil) . list(.(X,L)) :- list(L) . %^D
testing and demonstration ...
?- ((List = (nil)) , (list(List))) . %@ List = nil ?- (\+ ((List = (a)) , (list(List)))) . %@ true ?- ((List = (a.nil)) , (list(List))) . %@ List = [a|nil] ?- (\+ ((List = (nil.a)) , (list(List)))) . %@ true ?- ((List = (nil.nil)) , (list(List))) . %@ List = [nil|nil]
This implementation (list(L)) , now 40 years ago, does not meet the current expectations of the βlogicalβ program ...
% does it provide a useful answer in the general case ? ?- ((List = _) , (list(List))) . %@ List = nil ? ; %@ List = [_A|nil] ? ; %@ List = [_A,_B|nil] ? ; %@ List = [_A,_B,_C|nil] ? ; %@ List = [_A,_B,_C,_D|nil] ? ; %@ !! etc ... non-terminating !! %@ ^CAction (h for help): a % is it steadfast ? ?- ((list(List)) , (List = (nil))) . %@ List = nil ? ; %@ !! hang , non-terminating !! %@ ^CAction (h for help): a
... I do not know how to fix these problems.
When Warren writes ...
we write the functor as a right -associative infix operator, so ...
... I think that he has in mind this peculiar and useful feature of the xfy prologue ...
([user]) . :- ((op(10'1,'xfy','~'))) . %^D ?- (((Left ~ Rest) = (a ~ b ~ c ~ d ~ e)) , (Left == a) , (Rest == (b~c~d~e))) . %@ Left = a, %@ Rest = b~c~d~e ?- (((Left_1 ~ Left_2 ~ Rest) = (a ~ b ~ c ~ d ~ e)) , (Left_1 == a) , (Left_2 == b) , (Rest == (c ~ d ~ e))) . %@ Left_1 = a, %@ Left_2 = b, %@ Rest = c~d~e
It is reasonable to expect that the yfx operator will behave in the opposite way; while xfy allows xfy to capture elements on the left and ignore the rest to the right, perhaps yfx allows yfx to capture elements on the right and ignore the rest to the left ...
:- ((op(10'1,'yfx','~'))) . %^D ?- (((Rest ~ Right) = (a ~ b ~ c ~ d ~ e)) , (Rest == a~b~c~d) , (Right == e)) . %@ Rest = a~b~c~d, %@ Right = e ?- (((Rest ~ Right_2 ~ Right_1) = (a ~ b ~ c ~ d ~ e)) , (Rest == a ~ b ~ c) , (Right_2 == d) , (Right_1 == e)) . %@ Rest = a~b~c, %@ Right_1 = e, %@ Right_2 = d
[* 36'footnote] --- https://www.era.lib.ed.ac.uk/bitstream/handle/1842/6648/Warren1978.pdf
application
Do not try to play with . or [] in swipl, nor . nor [] do not function as described.
I reported an error for swipl about . ; assuming a mismatch with the traditional and of interest were standard prolog systems. It seems that this is not so.
https://github.com/SWI-Prolog/issues/issues/55
The author of swipl proposes the use of term_expansion , but neither the use of term_expansion nor goal_expansion can fix the following major compatibility issues.
$ yap + yap YAP 6.2.2 (x86_64-linux): Wed Sep 7 07:48:47 PDT 2016 MYDDAS version MYDDAS-0.9.1 ?- (ab[]) =[a,b] . %@ yes ?- A ={ foo:abnil } . %@ A = {[foo:a,b|nil]} ?- [a,b|[c,d]] = [a,b,..[c,d]] . %@ yes ?- (halt) . % YAP execution halted $ swipl + swipl Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.3.27) Copyright (c) 1990-2016 University of Amsterdam, VU Amsterdam SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is LGPL free software, and you are welcome to redistribute it under certain conditions. For help, use ?- help(Topic). or ?- apropos(Word). ?- (ab[]) =[a,b] . ERROR: Type error: `dict' expected, found `a' (an atom) ?- A ={ foo:abnil } . ERROR: Type error: `dict' expected, found `a' (an atom) ?- [a,b|[c,d]] = [a,b,..[c,d]] . ERROR: Syntax error: Operator expected ERROR: [a,b|[c,d]] = [a,b,. ERROR: ** here ** ERROR: .[c,d]] . ?- (end_of_file) . % halt
... suggesting to me that perhaps the author of swipl does not know the prolog very well (term_expansion?! ??!) or is not interested in prolog matching or is interested in setting the provider lock.