first order logic creating terms for arithmetic expressions using prolog - prolog

given a signature (0,Z,{plus(2),minus(2),times(2)}, constants are integers and functions are plus, minus and times with arity 2 for each. I wanted to write a two predicates arth/2 and printarth/1 which takes terms in the above signature and do the necessary arithmetic calculations addition, subtraction and multiplication.arth/2 will print the results and printarth/1 should results out the evaluation expression as shown below.
I wanted to achieve two things
first:
?- arth( plus(minus(8,2), times(4,-3)), N).
N = -6
N is evaluated as ((8−2) + (4∗−3)) = (6 +−12) =−6
second:
?- printarth(plus(minus(8,2), times(4,-3)), N).
((8 - 2) + (4 * -3))
true.
I understand that the use of Terms, Ops and complex terms are used for this and started my code as below
arithmetic_operator('+').
arithmetic_operator('-').
arithmetic_operator('*').
arithmetic_expression(N) :- integer(N).
arithmetic_expression(Term) :-
Term =..[Functor,Component1,Component2],
arithmetic_operator(Functor),
arithmetic_expression(Component1),
arithmetic_expression(Component2).
From here I find it difficult on how to create arth/2 and printarth/1 as I cannot call arithmetic_expression(Term) and throws me an error when I call it.
?- arithmetic_expression(..[+,5,7]).
ERROR: Syntax error: Operator expected
ERROR: arithmetic_expression(.
ERROR: ** here **
ERROR: .[+,5,7]) .
any resources on this task is very useful.

If you want to take a term that looks like this:
minus(2, 3)
and turn it into an arithmetic expression -(2, 3) which is equivalent to 2 - 3 (with the default definition of - as an operator), then evaluate it, you could do it like this:
term_arithmetic_expression(T, E) :-
T =.. [Name, X, Y],
binary_op(Name, Op),
E =.. [Op, X, Y].
eval_arithmetic_expression(T, R) :-
term_arithmetic_expression(T, E),
R is E.
binary_op(minus, -).
% add more binary operations
Now this at least works:
?- eval_arithmetic_expression(minus(2, 3), R).
R = -1.
As you see, both term_arithmetic_expression/2 and eval_arithmetic_expression/2 have two arguments. This is what you need to map minus(2, 4) to 2 - 4.
Your arithmetic_expression/1 is correctly traversing, but not mapping from the one representation to the other. Your arithmetic_operator has the same problem. With minimal changes:
arithmetic_operator(plus, +).
arithmetic_operator(minus, -).
arithmetic_operator(times, *).
arithmetic_expression(N, N) :- integer(N).
arithmetic_expression(Term, Expr) :-
Term =.. [Functor,Component1,Component2],
arithmetic_operator(Functor, Operator),
arithmetic_expression(Component1, Expr1),
arithmetic_expression(Component2, Expr2),
Expr =.. [Operator, Expr1, Expr2].
and then:
?- arithmetic_expression(plus(minus(8,2), times(4,-3)), Expr).
Expr = 8-2+4* -3 ;
false.
?- arithmetic_expression(plus(minus(8,2), times(4,-3)), Expr),
Result is Expr.
Expr = 8-2+4* -3,
Result = -6 ;
false.
?- arithmetic_expression(plus(minus(8,2), times(4,-3)), Expr),
Result is Expr,
display(Expr).
+(-(8,2),*(4,-3))
Expr = 8-2+4* -3,
Result = -6 ;
false.
The display is what is outputting +(-(8,2),*(4,-3)) in the last query.

Related

Prolog - How to separate atoms from expression involving predicates?

If I’ve an expression:
x + y * (-z)
How to I separate them to form a list of [x,y,z]?
My idea:
split2(X, [X]) :-
X \= +(_,_),
*(_,_),
-(_).
split2(X + Y, [H|T]) :-
split2(X,[H]),
split2(Y, T).
(Repeat for * and -).
Somehow it only works for simple case(involving 2 terms or only one predicate), but not complicated one.
Can someone tells me what’s wrong with my idea?
Follows a solution using DCGs that doesn't require a grammar rule per arithmetic operator and that takes full advantage of first-argument indexing (thus avoiding spurious choice-points or ugly cuts in the grammar rules):
split(Expression, Atomics) :-
Expression =.. [Functor| Args],
phrase(split_atomics(Args, Functor), Atomics).
split_atomics([], Atomic) -->
[Atomic].
split_atomics([Head| Tail], _) -->
split_list([Head| Tail]).
split_list([]) -->
[].
split_list([Head| Tail]) -->
{Head =.. [Functor| Args]},
split_atomics(Args, Functor),
split_list(Tail).
Sample calls:
| ?- split((x + y * (-z)), Atomics).
Atomics = [x, y, z]
yes
| ?- split((x + 3 * (-2)), Atomics).
Atomics = [x, 3, -2]
yes
Your predicates are pretty mixed up. For starters, you're using X \= _+_ to prevent the other rule from matching; instead you should use atomic(X). You're then saying _*_, -_ which is not clearly saying anything in particular except that certain anonymous variables... exist? Anyway, the rest of the first clause is erroneous for one reason or another.
Your second clause is off to a decent start, but I think you are avoiding a use of append/3 here for no particular reason. In the head, you are expecting H to be an atom, but then with the first term in the body you're forcing H to be a singleton list. What if X = a*b? You'd expect split2(a*b,[a,b]) to unify.
You're not far from where you need to be though. This is probably your general pattern:
split2(X, [X]) :- atomic(X).
split2(-X, Result) :- split2(X, Result).
split2(X+Y, Result) :-
split2(X, XVars),
split2(Y, YVars),
append(XVars, YVars, Result).
Continue the pattern for your other operators.
Can someone tells me what's wrong with my idea?
What you are doing is too complicated, that's what's wrong. If you really have as input a valid compound term, and what you need to get out of it is a list of the atomic sub-terms, then, here is what you might want to try:
expression_atoms(E) -->
{ compound(E),
E =.. [_Name|Args]
},
!,
expression_list_atoms(Args).
expression_atoms(E) -->
{ atomic(E)
},
!,
[E].
expression_list_atoms([E|Es]) -->
expression_atoms(E),
expression_list_atoms(Es).
expression_list_atoms([]) --> [].
(Ninja edit: see the solution by Paulo Moura for a cleaner implementation of the same idea.)
The only reason why this is a DCG and not a normal predicate is that I am too lazy to figure out how to do the appends properly.
Here is a small test:
?- X = x + y * (-z).
X = x+y* -z.
?- X = x + y * (-z), write_canonical(X).
+(x,*(y,-(z)))
X = x+y* -z.
?- X = x + y * (-z), write_canonical(X), phrase(expression_atoms(X), Atoms).
+(x,*(y,-(z)))
X = x+y* -z,
Atoms = [x, y, z].
In the last query, you can see the atoms extracted from the expression.
As you see, this solution doesn't care about the names of the compound terms. This happens in line 3 of the listing:
E =.. [_Name|Args]
So you can throw anything at it and it will still "work":
?- phrase(expression_atoms(
the(naked, truth(about(our(waitresses))), is(that(they(only(flirt, with, you))), to(get(a(better(tip('!')))))))),
Atoms).
Atoms = [naked, waitresses, flirt, with, you, !].
If you want this to fail for anything else but a predefined list of operators with a given arity, then you'd have to put a bit more code in there.

Predicates with =.. operator in Prolog

Last time I learnt about =.. that can translate a list to term and opposite.
I have 3 predicates to do, first one is the one that translates a list to a term. I came up with sth like this:
list_to_term(List, Functor, Term) :-
Term =.. [Functor | List].
Is it okey? Enough? Or I miss something?
The other predicate is count(A,T,N) for element A, in term T with number N that is true if N is a count of elements A in term T... Can anyone help me with this one or how to start?
?- count(a,f(a),N).
N = 1
?- count(a,f(a,g(b,a),N).
N = 2.
?- count(a,f(a,g(X,a),N).
N = 2.
Looking at the answer of this post you can reuse the predicate flatten_term/2, a little bit modified to handle free variables, to sove your problem. Here is the code for a basic solution:
flatten_term(Term,[Term]):-
(atomic(Term);var(Term)),!.
flatten_term(Term,Flat):-
Term =.. TermList,
flatten_term_list(TermList,Flat),!.
flatten_term_list([],[]):-!.
flatten_term_list([H|T],List):-
flatten_term(H,HList),
flatten_term_list(T,TList),
append(HList,TList,List),!.
occurrences(_,[],N,N):-!.
occurrences(A,[H|T],N,Tot):-
A \== H,!,
occurrences(A,T,N,Tot).
occurrences(A,[H|T],N,Tot):-
A == H,!,
N1 is N+1,
occurrences(A,T,N1,Tot).
count(A,Term,N):-
flatten_term(Term,Flatten),
occurrences(A,Flatten,0,N).
?- count(a,f(a,g(X,a),d),T).
T = 2.
?- count(X,f(a,g(X,a),d),T).
T = 1
First of all you flatten the term using flatten_term/2. Then simply count the occurrences of the element you want to find using occurrences/4. You can, if you want, modify flatten_term/2 to avoid the usage of occurrences/4 and so scan the term (list) only one time... Something like: flatten_term(Term,Flatten,ElementToFind,Counter,Total).
Start by solving a more general problem of counting the terms in a list. Processing a term is processing a singleton list containing that term, after all:
count(A,T,N):- count(A, [T|Z],Z, 0,N).
count(_, [], [], C,N):- N is C, !.
count(A, [T|B],Z, C,N):- ?=(A,T), A=T, !, count(A, B,Z, C+1,N).
count(A, [T|B],Z, C,N):- ?=(A,T), T=..[_|S], !, append(S,Y,Z), count(A, B,Y, C,N).
count(A, [_|B],Z, C,N):- count(A, B,Z, C,N).
This opens up each head term in a list in succession and appends its argument terms to that list thus using it as a queue... thus processing the predicate's second argument T in a breadth-first manner.
This assumes A argument is an atom, and ?= is used to avoid instantiating the free variables we might encounter, and instead to skip over them, as your examples seem to indicate.
Is it okey? Enough? Or I miss something?
Prolog's =../2 predicate [swi-doc] can "pack" and "unpack" a list that contains the functor name and its arguments in a term and vice versa. So one can use this to construct a term, or to analyze a term. For example:
?- f(a,g(b,a)) =.. L.
L = [f, a, g(b, a)].
Here f is the functor name, and a and g(b, a) are the arguments. These arguments can be terms as well, and then we thus need to unpack these arguments further.
We can for example obtain all the subterms of a term with:
subterms(T, T) :-
\+ var(T).
subterms(T, ST) :-
\+ var(T),
T =.. [_|As],
member(A, As),
subterms(A, ST).
For example:
?- subterms(f(a,g(X,a)),N).
N = f(a, g(X, a)) ;
N = a ;
N = g(X, a) ;
N = a ;
false.
Now that we obtained all (sub)terms, we can slightly rewrite the predicate to count the number of elements that match:
subterm_query(Q, T) :-
Q == T.
subterm_query(Q, T) :-
\+ var(T),
T =.. [_|As],
member(A, As),
subterm_query(Q, A).
so we obtain if we query for a:
?- subterm_query(a, f(a,g(X,a))).
true ;
true ;
false.
If we can use the aggregate library, we can make use of the aggregate_all/3 predicate to count the number of times, the predicate was succesful:
?- aggregate_all(count, subterm_query(a, f(a,g(X,a))), Count).
Count = 2.
If not, you need to implement a mechanism that returns 1 for a match, and sums up recursively the matches of the child terms. I leave this as an exercise.

Error condition if else in prolog

Could someone tell me what's wrong in my If else in my search, in the sublist.
Because when the size is 0, the conditional works, but if the value becomes 1,2 and 3 it presents an error, but the relational operators are not correct?
If the variable length has size = 0, the condition works, but if the variable length has size 3 it has an error.
Error is:
Exception: >=/2: Arguments are not sufficiently instantiated.
subList([], []).
subList(List1,List2):-
concatenate(List1,List2,Result1),
equalelements(Result1,Result2),
counting(Result2,Length),
Length =< 2
-> false
; Length >= 3
-> true.
searchdisease([],_).
searchdisease(Symptoms,Disease) :-
disease(Ls, Disease),
subList(Symptoms, Ls).
counting([ ],0).
counting([_| T], N) :-
counting(T, N1),
N is N1 + 1.
concatenate(L1, L2, NL) :-
append(L1, L2, L12),
msort(L12, NL).
This is a common problem with priorities of operators. Note that Prolog ignores the precise indentation you use. Instead it takes operators into account. So you need to add round brackets accordingly.
Most probably you want the following:
subList([], []).
subList(List1,List2):-
concatenate(List1,List2,Result1),
equalelements(Result1,Result2),
counting(Result2,Length),
( Length =< 2
-> false
; Length >= 3
-> true
).
On the other hand, why not simply replace the comparisons for Length by a single goal: Length >= 3.

Finding the max in a list - Prolog

I was just introduced to Prolog and am trying to write a predicate that finds the Max value of a list of integers. I need to write one that compares from the beginning and the other that compares from the end. So far, I have:
max2([],R).
max2([X|Xs], R):- X > R, max2(Xs, X).
max2([X|Xs], R):- X <= R, max2(Xs, R).
I realize that R hasn't been initiated yet, so it's unable to make the comparison. Do i need 3 arguments in order to complete this?
my_max([], R, R). %end
my_max([X|Xs], WK, R):- X > WK, my_max(Xs, X, R). %WK is Carry about
my_max([X|Xs], WK, R):- X =< WK, my_max(Xs, WK, R).
my_max([X|Xs], R):- my_max(Xs, X, R). %start
other way
%max of list
max_l([X],X) :- !, true.
%max_l([X],X). %unuse cut
%max_l([X],X):- false.
max_l([X|Xs], M):- max_l(Xs, M), M >= X.
max_l([X|Xs], X):- max_l(Xs, M), X > M.
Ignoring the homework constraints about starting from the beginning or the end, the proper way to implement a predicate that gets the numeric maximum is as follows:
list_max([P|T], O) :- list_max(T, P, O).
list_max([], P, P).
list_max([H|T], P, O) :-
( H > P
-> list_max(T, H, O)
; list_max(T, P, O)).
A very simple approach (which starts from the beginning) is the following:
maxlist([],0).
maxlist([Head|Tail],Max) :-
maxlist(Tail,TailMax),
Head > TailMax,
Max is Head.
maxlist([Head|Tail],Max) :-
maxlist(Tail,TailMax),
Head =< TailMax,
Max is TailMax.
As you said, you must have the variables instantiated if you want to evaluate an arithmetic expression. To solve this, first you have to make the recursive call, and then you compare.
Hope it helps!
As an alternative to BLUEPIXY' answer, SWI-Prolog has a builtin predicate, max_list/2, that does the search for you. You could also consider a slower method, IMO useful to gain familiarity with more builtins and nondeterminism (and then backtracking):
slow_max(L, Max) :-
select(Max, L, Rest), \+ (member(E, Rest), E > Max).
yields
2 ?- slow_max([1,2,3,4,5,6,10,7,8],X).
X = 10 ;
false.
3 ?- slow_max([1,2,10,3,4,5,6,10,7,8],X).
X = 10 ;
X = 10 ;
false.
edit
Note you don't strictly need three arguments, but just to have properly instantiated variables to carry out the comparison. Then you can 'reverse' the flow of values:
max2([R], R).
max2([X|Xs], R):- max2(Xs, T), (X > T -> R = X ; R = T).
again, this is slower than the three arguments loops, suggested in other answers, because it will defeat 'tail recursion optimization'. Also, it does just find one of the maxima:
2 ?- max2([1,2,3,10,5,10,6],X).
X = 10 ;
false.
Here's how to do it with lambda expressions and meta-predicate foldl/4, and, optionally, clpfd:
:- use_module([library(lambda),library(apply),library(clpfd)]).
numbers_max([Z|Zs],Max) :- foldl(\X^S^M^(M is max(X,S)),Zs,Z,Max).
fdvars_max( [Z|Zs],Max) :- foldl(\X^S^M^(M #= max(X,S)),Zs,Z,Max).
Let's run some queries!
?- numbers_max([1,4,2,3],M). % integers: all are distinct
M = 4. % succeeds deterministically
?- fdvars_max( [1,4,2,3],M).
M = 4. % succeeds deterministically
?- numbers_max([1,4,2,3,4],M). % integers: M occurs twice
M = 4. % succeeds deterministically
?- fdvars_max( [1,4,2,3,4],M).
M = 4. % succeeds deterministically
What if the list is empty?
?- numbers_max([],M).
false.
?- fdvars_max( [],M).
false.
At last, some queries showing differences between numbers_max/2 and fdvars_max/2:
?- numbers_max([1,2,3,10.0],M). % ints + float
M = 10.0.
?- fdvars_max( [1,2,3,10.0],M). % ints + float
ERROR: Domain error: `clpfd_expression' expected, found `10.0'
?- numbers_max([A,B,C],M). % more general use
ERROR: is/2: Arguments are not sufficiently instantiated
?- fdvars_max( [A,B,C],M).
M#>=_X, M#>=C, M#=max(C,_X), _X#>=A, _X#>=B, _X#=max(B,A). % residual goals
list_max([L|Ls], Max) :- foldl(num_num_max, Ls, L, Max).
num_num_max(X, Y, Max) :- Max is max(X, Y).
%Query will be
?-list_max([4,12,5,3,8,90,10,11],Max).
Max=90
Right now I was working with recursion in Prolog, so if it is useful for someone I will leave 'my two cents' solving it in the two ways that I have thought:
% Start
start :- max_trad([2, 4, 6, 0, 5], MaxNumber1),
max_tail([2, 4, 6, 0, 5], 0, MaxNumber2),
show_results(MaxNumber1, MaxNumber2).
% Traditional Recursion (Method 1)
max_trad([Head|Tail], Max) :- max_trad(Tail, Value), Head > Value, Max is Head.
max_trad([Head|Tail], Max) :- max_trad(Tail, Value), Head =< Value, Max is Value.
max_trad([], 0).
% Tail Recursion (Method 2)
max_tail([], PartialMax, PartialMax).
max_tail([Head|Tail], PartialMax, FinalMax) :- Head > PartialMax, max_tail(Tail, Head, FinalMax).
max_tail([_|Tail], PartialMax, FinalMax) :- max_tail(Tail, PartialMax, FinalMax).
% Show both of the results
show_results(MaxNumber1, MaxNumber2) :-
write("The max value (obtained with traditional recursion) is: "), writeln(MaxNumber1),
write("The max value (obtained with tail recursion) is: "), writeln(MaxNumber2).
The output of the above code is:
Both methods are similar, the difference is that in the second an auxiliary variable is used in the recursion to pass values forward, while in the first method, although we have one less variable, we are filling the Stack with instructions to be executed later, so if it were an exaggeratedly large list, the second method is appropriate.
maximum_no([],Max):-
write("Maximum No From the List is:: ",Max).
maximum_no([H|T],Max):-
H>Max,
N = H,
maximum_no(T,N).
maximum_no(L,Max):-
maximum_no(L,Max).
The maximum number in a list in Prolog ?
max([],A):-print(A),!.
max([Head | Tail] , A):-A =< Head ,A1 is Head , max(Tail,A1) ; max(Tail,A).
max(L,M):-
member(M,L),
findall(X,(member(X,L),X>M),NL),
length(NL,0).

Prolog - unusual cons syntax for lists

I have come across an unfamiliar bit of Prolog syntax in Lee Naish's paper Higher-order logic programming in Prolog. Here is the first code sample from the paper:
% insertion sort (simple version)
isort([], []).
isort(A.As, Bs) :-
isort(As, Bs1),
isort(A, Bs1, Bs).
% insert number into sorted list
insert(N, [], [N]).
insert(N, H.L, N.H.L) :-
N =< H.
insert(N, H.LO, H.L) :-
N > H,
insert(N, LO, L).
My confusion is with A.As in isort(A.As, Bs) :-. From the context, it appears to be an alternate cons syntax for lists, the equivalent of isort([A|As], Bs) :-.
As well N.H.L appears to be a more convenient way to say [N|[H|L]].
But SWI Prolog won't accept this unusual syntax (unless I'm doing something wrong).
Does anyone recognize it? is my hypothesis correct? Which Prolog interpreter accepts that as valid syntax?
The dot operator was used for lists in the very first Prolog system of 1972, written in Algol-W, sometimes called Prolog 0. It is inspired by similar notation in LISP systems. The following exemple is from the paper The birth of Prolog by Alain Colmerauer and Philippe Roussel – the very creators of Prolog.
+ELEMENT(*X, *X.*Y).
+ELEMENT(*X, *Y.*Z) -ELEMENT(*X, *Z).
At that time, [] used to be NIL.
The next Prolog version, written in Fortran by Battani & Meloni, used cases to distinguish atoms and variables. Then DECsystem 10 Prolog introduced the square bracket notation replacing nil and X.Xs with [] and [X,..Xs] which in later versions of DECsystem 10 received [X|Xs] as an alternative. In ISO Prolog, there is only [X|Xs], .(X,Xs), and as canonical syntax '.'(X,Xs).
Please note that the dot has many different rôles in ISO Prolog. It serves already as
end token when followed by a % or a layout character like SPACE, NEWLINE, TAB.
decimal point in a floating point number, like 3.14159
graphic token char forming graphic tokens as =..
So if you are now declaring . as an infix operator, you have to be very careful. Both with what you write and what Prolog systems will read. A single additional space can change the meaning of a term. Consider two lists of numbers in both notations:
[1,2.3,4]. [5].
1 .2.3.4.[]. 5.[].
Please note that you have to add a space after 1. In this context, an additional white space in front of a number may change the meaning of your terms. Like so:
[1|2.3]. [4]. 5. [].
1 .2.3. 4.[]. 5. [].
Here is another example which might be even more convincing:
[1,-2].
1.(-2).[].
Negative numbers require round brackets within dot-lists.
Today, there is only YAP and XSB left that still offer infix . by default – and they do it differently. And XSB does not even recognize above dot syntax: you need round brackets around some of the nonnegative numbers.
You wrote that N.H.L appears to be a more convenient way to say [N|[H|L]]. There is a simple rule-of-thumb to simplify such expressions in ISO Prolog: Whenever you see within a list the tokens | and [ immediately after each other, you can replace them by , (and remove the corresponding ] on the right side). So you can now write: [N,H|L] which does not look that bad.
You can use that rule also in the other direction. If we have a list [1,2,3,4,5] we can use | as a "razor blade" like so: [1,2,3|[4,5]].
Another remark, since you are reading Naish's paper: In the meantime, it is well understood that only call/N is needed! And ISO Prolog supports call/1, call/2 up to call/8.
Yes, you are right, the dot it's the list cons infix operator. It's actually required by ISO Prolog standard, but usually hidden. I found (and used) that syntax some time ago:
:- module(eog, []).
:- op(103, xfy, (.)).
% where $ARGS appears as argument, replace the call ($ARGS) with a VAR
% the calle goes before caller, binding the VAR (added as last ARG)
funcs(X, (V, Y)) :-
nonvar(X),
X =.. W.As,
% identify meta arguments
( predicate_property(X, meta_predicate M)
% explicitly exclude to handle test(dcg)
% I'd like to handle this case in general way...
, M \= phrase(2, ?, ?)
-> M =.. W.Ms
; true
),
seek_call(As, Ms, Bs, V),
Y =.. W.Bs.
% look for first $ usage
seek_call([], [], _Bs, _V) :-
!, fail.
seek_call(A.As, M.Ms, A.Bs, V) :-
M #>= 0, M #=< 9, % skip meta arguments
!, seek_call(As, Ms, Bs, V).
seek_call(A.As, _, B.As, V) :-
nonvar(A),
A = $(F),
F =.. Fp.FAs,
( current_arithmetic_function(F) % inline arith
-> V = (PH is F)
; append(FAs, [PH], FBs),
V =.. Fp.FBs
),
!, B = PH.
seek_call(A.As, _.Ms, B.As, V) :-
nonvar(A),
A =.. F.FAs,
seek_call(FAs, Ms, FBs, V),
!, B =.. F.FBs.
seek_call(A.As, _.Ms, A.Bs, V) :-
!, seek_call(As, Ms, Bs, V).
:- multifile user:goal_expansion/2.
user:goal_expansion(X, Y) :-
( X = (_ , _) ; X = (_ ; _) ; X = (_ -> _) )
-> !, fail % leave control flow unchanged (useless after the meta... handling?)
; funcs(X, Y).
/* end eog.pl */
I was advised against it. Effectively, the [A|B] syntax it's an evolution of the . operator, introduced for readability.
OT: what's that code?
the code above it's my attempt to sweeten Prolog with functions. Namely, introduces on request, by means of $, the temporary variables required (for instance) by arithmetic expressions
fact(N, F) :-
N > 1 -> F is N * $fact($(N - 1)) ; F is 1.
each $ introduce a variable. After expansion, we have a more traditional fact/2
?- listing(fact).
plunit_eog:fact(A, C) :-
( A>1
-> B is A+ -1,
fact(B, D),
C is A*D
; C is 1
).
Where we have many expressions, that could be useful...
This syntax comes from NU-Prolog. See here. It's probably just the normal list functor '.'/2 redefined as an infix operator, without the need for a trailing empty list:
?- L= .(a,.(b,[])).
L = [a,b]
Yes (0.00s cpu)
?- op(500, xfy, '.').
Yes (0.00s cpu)
?- L = a.b.[].
L = [a,b]
Yes (0.00s cpu)

Resources