Array Univ var ([x,y]=..T) - prolog - prolog

I saw a question asking what does [a,b,c]=..L. return.
When testing this I saw that it returns: L = ['.', a, [b, c]].
I can't understand why this happens, I was unable to understand the nature of Univ from the documentation. Understanding this will help me understand Univ.

One way to learn more about terms is to use write_canonical/1 in a conforming Prolog system.
For example, with GNU Prolog, we obtain:
| ?- write_canonical([x,y]).
'.'(x,'.'(y,[]))
This shows:
the primary functor in this term is '.', with arity 2
the first argument is x
the second argument is '.'(y, []), which is the list [y]
This explains why (=..)/2 yields:
| ?- [x,y] =.. Ls.
Ls = ['.',x,[y]]
and also your other example.

This happends because representation of the list in prolog is a tree datastructure,like this.It's top node is a "dot" left side is Head then again a dot on right if tail is not empty and head on left hand side and "dot" on right handside. When you do this you are simply creating a predicate(well , not exact a predicate but it is sometimes needed as i show an example): suppose i write:
V=..[somefunctor,X,Y,Z]
Then it will automatically construct a predicate like this:
somefunctor(X,Y,Z).
Now Why do we need this? Supppose i call a predicate with these terms: predicate(somefunctor,term,term2,term3) and predicate or rule looks something like this: predicate(X,Y,Z,T) and i ask you that no matter what predicate is in X, you have to call this predicate with parameters Y,Z,T. May be you think you call that predicate by writing like this: X(Y,Z,T) but unfortunately it is not allowed in prolog, so here you can use V=..[X,Y,Z,T] where X should be placed as first argument because it's predicate name and as a result you get something like this: V = somefunctor(term,term2,term3) and this happends internally. In order to invoke this predicate you make use of call predicate:
call(V) where `call/1` is a metapredicate and `V=..` is a not logical predicate.

Related

Representing truth regarding beliefs in prolog

How to make this (or something similar) work in Prolog:
belief(john,red(apple)).
belief(peter,red(apple)).
X :- belief(john,X), belief(peter,X).
And get true. for the following query (while consulting above):-
?- red(apple).
First, it's useful to define a little helper to capture when all (relevant) persons believe something:
all_believe(Belief) :-
belief(john, Belief),
belief(peter, Belief).
Then you can define, for example:
red(Object) :-
all_believe(red(Object)).
green(Object) :-
all_believe(green(Object)).
And with your given set of beliefs you get:
?- red(apple).
true.
?- green(apple).
false.
This works. It requires you to define similar rules for any term that you want to use as a belief.
You can make this a bit shorter with macro definitions using term_expansion:
term_expansion(declare_belief(Belief),
Belief :- all_believe(Belief)).
This means that every top-level definition in your source code of the form declare_belief(Belief) should be treated as if you had written Belief :- all_believe(Belief) instead (with the variable Belief substituted appropriately).
So now you can just write this:
declare_belief(red(_)).
declare_belief(green(_)).
and it will be treated exactly like the longer definitions for red(Object) and red(Object) above. You will still have to write this kind of declaration for any term that you want to use as a possible belief.
Prolog does not allow the head of a rule to be just a variable. The head must be a nonvar term, whose functor (i.e., name and arity) identifies the predicate being defined. So, a possible solution would be something like this:
true_belief(X) :-
belief(john, X),
belief(peter, X).
belief(john, red(apple)).
belief(peter, red(apple)).
Examples:
?- true_belief(red(apple)).
true.
?- true_belief(X).
X = red(apple).

Prolog print statement does not work as expected

I was trying to define a functor and print each individual items of list in Prolog, but Prolog is not printing in correct format.
rint(L):-
write(H).
the output is like
rint([a, s,v ,c]).
_L139
true.
This is what I expect to achieve by calling the functor, any help or thought is appreciated, I'm new to Prolog and learning it.
?- rint([a,b,c,d]).
.(a, .(b, .(c, .(d, []))))
I think it should be
rint(L) :- write(L).
Also if you want .(a, .(b, .(c, .(d, [])))) and not [a, b, c, d] in output, use display:
rint(L) :- display(L).
The problem is an error in your rule for rint.
Your definition says that rint(L) succeeds if write(H) succeeds. At that point, the interpreter knows nothing about H. So it writes a value it doesn't know, which is why you see the _L139, the internal representation of an uninitialised variable.
Having done that, write(H) has succeed, is true, so rint(L) is true. The interpreter tells you that: true.
To define your own rint/1 without relying on built-ins such as display/1, you would need to do something like
rint([]) :-
write([]).
rint([H|T]) :-
write('.('),
write(H),
write(', '),
rint(T),
write(')').
If you're trying to display an empty list, just write it. If you're trying to display any other list, write the opening period and parenthesis, write the Head, write the following comma and space, then call itself for the Tail of the list, then write the closing parenthesis.

How to do this in one function

I was wondering how to do the answer (or first function) to this question in Prolog only using one predicate? The link I'm referring to is here.
Here's an example of what I mean by only calling one predicate:
reverse([X|Y],Z,W) :- reverse(Y,[X|Z],W).
reverse([],X,X).
What are you trying to do and why do you want just one clause for the predicate?
personally I believe that having the ability to write many clauses is one of the great things of prolog and the code is more elegant and readable that way
Anyway, you will probably want to use or. assuming that you have the following clauses:
foo(Arg11,Arg12,Arg13):-
(Body1).
foo(Arg21,Arg22,Arg23):-
(Body2).
foo(Arg31,Arg32,Arg33):-
(Body3).
you should first make sure that every clause has the same arguments (bye bye pattern matching there!):
foo(Arg1,Arg2,Arg3):-
(Body1b).
foo(Arg1,Arg2,Arg3):-
(Body2b).
foo(Arg1,Arg2,Arg3):-
(Body3b).
and then you will use or (;):
foo(Arg1,Arg2,Arg3):-
(Body1b)
; (Body2b)
; (Body3b).
for example,
reverse([X|Y],Z,W):-
reverse(Y,[X|Z],W).
reverse([],X,X).
will become:
reverse(X,Y,Z):-
X = [H|T],
reverse(T,[H|Y],X).
reverse(X,Y,Z):-
X = [],
Z = Y.
and then:
reverse(X,Y,Z):-
(X = [H|T],
reverse(T,[H|Y],X) )
; (X = [],
Z = Y). *%ew ew ugly!*
regarding the example on your first post, there are two different predicates, each having just one clause. the second predicate has 2 arguments while the first one has 1 therefore they are different. The only way to "merge" them would be by simply calling the second one as has_equal_sums(List, _) in the place of the first.
To be honest, I dont see the point of doing this; I doubt you will not get any significant speedup and the code becomes way messier.
Of course, it's your code and there can be restrictions we dont know (that's why I asked what you want to accomplish)

Convert list into functor parameter

I got stuck to implement a logic. At some instance in my program I have a list say named as List.
The length of this List is variable and I don't know in advance. Now I have to pass this list in a functor to create a fact and I am unable to implement it. For eg:
if List is [first] then it should add the fact functor(first).
if List is [first,second] then it should add the fact functor(first,second).
if List is [first,second,third] then it should add the fact functor(first,second,third).
and so on...
I was trying by =.. but here I am unable to map that variable length constraint. For fixed length I am able to perform but I don't know in advance that how many elements will be there in list.
Any suggestions to implement this logic. Thanks.
I don't quite understand your problem with =.. but this worked for me:
assert_list(List) :-
Term =.. [my_functor|List],
assert(Term).
Note that I use my_functor instead of simply functor because functor/3 is a built-in predicate so you cannot assert ternary functor facts (functor(first, second, third)).
Calling it:
?- assert_list([first,second,third]).
true.
Checking that it works:
?- listing(my_functor).
:- dynamic user:my_functor/3.
user:my_functor(first, second, third).
true.
Note that technically, the different n-ary my_functor/n predicates are not the same predicates. You must use different queries in your program for each n. To circumvent this, you could simply assert the list as one and only argument of my_functor:
?- List = [first, second, third],
assert(my_functor(List)).
true.
?- listing(my_functor).
:- dynamic user:my_functor/3.
user:my_functor([first, second, third]).
true.
My SWI-Prolog version is 5.7.5.

How can I insert an additional argument after the last argument in a prolog procedure?

I am new to learning prolog, and I want to know, if we have some procedure like
father("Nic","Adam").
and I want to write a function that it will add new value to this
father("Nic","Adam","something"..)
how can I do this? Using list? Or what?
Quick answer: You don't want to do that.
Longer answer: The father/2 predicate has a certain meaning, namely that for father(X,Y) X is the father of Y. A father/3 predicate is a different thing altogether. What do you want to achieve with that third argument? Normally, you use additional rules, which derive things from the father/2 predicate, or even resolve it to a father/3 argument.
The main question remains: what's the purpose of the third argument? If you want your resolution to work for certain specific 3rd arguments based on the existance of a corresponding father/2 predicate for example, you could do father(X, Y, 'something') :- father(X,Y) which will succeed if you have a corresponding father/2 fact.
PS: Do learn your terminology. In Prolog we don't speak of procedures and we don't write functions. Instead we have predicates, facts, rules, ...
PPS: I am not sure which Prolog implementation you are using, but you might want to use 'something' instead of "something". The latter usually creates a list of character codes, not a string:
?- X = 'some'.
X = some.
?- X = "some".
X = [115, 111, 109, 101].
Simply writing
father(nic, adam).
As a predicate already defines it. It is like stating a fact: you declare that father(nic, adam) is true, then you can execute the following with these expected results :
?- father(nic, adam).
Yes
?- father(nic, X).
X = adam

Resources