how to implement if-then-else in prolog - prolog

I have tried so many things but I could not found How I can implement following wish in prolog .
if list is empty
call foo function
else
do nothing
What I did:
list = [] -> foo(...)
;
fail.
But, it does not work

fail does not mean "do nothing", but "fail (and backtrack)".
You need to use true instead:
( List == [] -> foo(...) ; true ),
Also, List should be a variable, so use upper case.

Another, perhaps more idiomatic, way to write this would be
% foo_if_empty(?List) call foo if list is empty
foo_if_empty([]) :- !,foo(...).
foo_if_empty(_).
What my code does is to unify with the first clause if list is empty.
If so, we do a cut. If foo fails, we don't want mypred to succeed. So we don't want to do the second clause. The cut eliminates that possiblity.
Now, if we don't unify with the first clause we'll certainly unify with the second. And it does nothing.
This is a much more idiomatic way of doing if/then/else in Prolog than using ->. -> is usually just used for situations where introducing another pred would obscure rather than enlighten the code, similar to the ?: operator in curly brace languages.

Related

Concatenate two atoms in prolog without using atom_concat

I want to write prolog that can essentially do what this is doing
atom_concat('3',' =',Answer).
Answer = '3 ='.
But I do not want to use the atom_concat function (or any built in predicates). I would also like the answer to have no quotation marks in it.
I have tried implementing a method that operates the same as the append method, which I have called merge.
merge([],Xs,Xs).
merge([X|Xs],Ys,[X|Zs]):-
merge(Xs,Ys,Zs).
But when I write this into my db.pl file I get false when running it.
?- [db].
true.
?- merge('3',' =',Answer).
false.
You can't mutate immutable values. You could use string_concat/3 to create a merger of two string atoms. By putting 'Variable' you are signalling Prolog that you want an ATOM called Variable. So numerical 3 and string atom '3' are not the same. What basically happens is you have two >immutables<, so a third has to be made that is an amalgamation of the other two.
atom_concat
string_concat
'merge' is also a deprecated method, just to clear up any confusion:
merge
The program you want:
The query
?- trace, (concat_strings(['Hello ','Hello ','Hello '],[world1,world2,world3],Output)).
The code
concat_strings([H1|T1],[H2|T2],[H3|T3]) :-
string_concat(H1, H2, H3),
concat_strings(T1,T2,T3).
concat_strings([],[],[]).
It takes the the first word of both lists, makes a new immutable atom from the 2 through string_concat and puts it in H3, which is then put onto the head of the list when the call ends. We have the end condition concat_strings([],[],[]) and the first 2 are the lists YOU pass, the third means T3 eventually unifies as T3 = [], which is also the atom to show Prolog the end of a list has been reached. Prolog then starts stepping back, adds [] as the tail and then adds the new atoms to the new list as it works its way back to your call.
OPINION:
My favorite resource for Prolog basics explained: http://www.learnprolognow.org/lpnpage.php?pageid=top
built_equality_structure(Id,Value,Id = Value).
If you call it with
?- built_equality_structure(a,3,X).
you will get the result
X = (a=3)
where the Prolog system only add parentheses for readability.

How to check whether some variable returns something in predicate

Lets assume I have facts as follows:
airport(nyc,'newyork').
I want want to display a message if the user inputs an airport that doesn't exist.
My Attempt:
isAirport(Air) :-
airport(Air,T),
(var(T) -> true
;
write('Airport not found'),
fail
).
However, this doesn't seem to work.
First let's see what happens if you query a conjunction (the , operator) first:
?- airport(nyc, _), write('found!').
found!
true.
?- airport(abc, _), write('found!').
false.
This means, isAirport(abc) directly fails after trying airport(abc,_) without the rest of your predicate being evaluated. In many cases, you can therefore get by without an explicit if-then-else construct and just write something of the form
predicate(X) :-
first_condition(X),
second_condition(X).
and it will only succeed if both conditions are fulfilled for X.
In case you really want to create some user interface, this is a bit more tricky, because I/O is inherently non-logical, in particular when there is backtracking involved. We usually call a program which behaves like we would expect from a logical formula pure and when it contains non-logical constructs like I/O or the cut operator ! are called impure.
Unfortunately, the if-then-else construct (-> and ;) and negation (\+) are implemented via cut and therefore impure as well. Luckily, most of the time people want a conditional, a pure disjunction is sufficient:
case(1,a).
case(2,b).
We have an automatic branching from the execution mechanism of Prolog:
?- case(X,Y).
X = 1,
Y = a ;
X = 2,
Y = b.
But sometimes we really want to do something that needs the impure constructs, like user input. Then the easiest way to keep the nice logical properties of our program is to separate the task into pure and impure ones:
main :-
uinput(Data),
pure_predicate(Data, Result),
write(Result).
After we have done all the impure parts, Data is unified with the user data we wanted. Let's have a look at the implementation of uinput/1:
uinput(data(Airport,D-M-Y)) :-
format('~nAirport? '),
read(Airport),
( ground(Airport), airport(Airport, _) )
->
(
format('~nDay? '),
read(D),
format('~nMonth? '),
read(M),
format('~nYear? '),
read(Y),
( ground(D-M-Y), isDate(D-M-Y) )
->
true
;
throw(failure('unknown date'))
)
;
throw(failure('unknown airport'))
.
We successively read terms from the input and throw an exception if we can't handle it. For the if-then-else construct to work, we need to take special care. If we compare the two queries:
?- between(1,3,X), write(X).
1
X = 1 ;
2
X = 2 ;
3
X = 3.
and
?- between(1,3,X) -> write(X); false.
1
X = 1.
you can see that the if-then-else is losing solutions. This means we need to make sure that our condition is deterministic. Asking for a user input term to be ground is already a good idea, because without variables, there is only one solution term. Still, a call to one of the data-predicates airport/1 and isDate/1 might generate the same term multiple times or not terminate at all. In this particular case, we just need to make sure that each airport has a unique shortcut name, we can also generate dates without repetition:
airport(nyc, 'New York City').
airport(wdc, 'Washington DC').
isDate(X-Y-Z) :-
between(1,31,X),
between(1,12,Y),
between(1970,2100,Z).
Another trick in the implementation of uinput is that we just succeed with true when we have validated everything. The only effect of is now that Data is instantiated with whatever the user entered.
If we give a dummy implementation of the actual implementation, we can already try the implementation oursevles:
pure_predicate(_Data, Result) :-
% here goes the actual stuff
Result='we have found something awesome'.
On the prompt we can use the pure predicate without trouble:
?- pure_predicate(someinputdata,Y).
Y = 'we have computed something awesome'.
On the other hand, we can also use the full predicate as follows:
?- main(_).
Airport? wdc.
Day? |: 1.
Month? |: 2.
Year? |: 2000.
we have found something awesome
true.
Since we are using read, we have to input prolog terms and terminate with a dot ., but everything worked as expected.
In case the user input fails, we get:
?- main(_).
Airport? bla(X).
ERROR: Unhandled exception: failure('unknown airport')
Please note that we only went through this trouble to actually fail early and give a user message in that case. For the actual computation, this is completely unneccessary.
In the code below you are making false assumption that T will remain unbound in case if airport will not be found in database:
airport(Air, T)
What happens actually is that call to airport(Air, T) will make isAirport(Air) to fail immediately and your var(T) and other parts will not be executed at all.
Try this code instead:
isAirport(Air) :-
airport(Air, _T), ! ; write('Airport not found'), fail.

Prolog: Rules with nothing but anonymous variables in the head, and no body

Prolog's grammar uses a <head> :- <body> format for rules as such:
tree(G) :- acyclic(G) , connected(G).
, denoting status of G as a tree depends on status as acyclic and connected.
This grammar can be extended in an implicit fashion to facts. Following the same example:
connected(graphA) suggests connected(graphA):-true.
In this sense, one might loosely define Prolog facts as Prolog rules that are always true.
My question: Is in any context a bodiless rule (one that is presumed to be true under all conditions) ever appropriate? Syntactically such a rule would look as follows.
graph(X). (suggesting graph(X):-true.)
Before answering, to rephrase your question:
In Prolog, would you ever write a rule with nothing but anonymous variables in the head, and no body?
The terminology is kind of important here. Facts are simply rules that have only a head and no body (which is why your question is a bit confusing). Anonymous variables are variables that you explicitly tell the compiler to ignore in the context of a predicate clause (a predicate clause is the syntactical scope of a variable). If you did try to give this predicate clause to the Prolog compiler:
foo(Bar).
you will get a "singleton variable" warning. Instead, you can write
foo(_).
and this tells the compiler that this argument is ignored on purpose, and no variable binding should be attempted with it.
Operationally, what happens when Prolog tries to prove a rule?
First, unification of all arguments in the head of the rule, which might lead to new variable bindings;
Then, it tries to prove the body of the rule using all existing variable bindings.
As you can see, the second step makes this a recursively defined algorithm: proving the body of a rule means proving each rule in it.
To come to your question: what is the operational meaning of this:
foo(_).
There is a predicate foo/1, and it is true for any argument, because there are no variable bindings to be done in the head, and always, because no subgoals need to be proven.
I have seen at least one use of such a rule: look at the very bottom of this section of the SWI-Prolog manual. The small code example goes like this:
term_expansion(my_class(_), Clauses) :-
findall(my_class(C),
string_code(_, "~!##$", C),
Clauses).
my_class(_).
You should read the linked documentation to see the motivation for doing this. The purpose of the code itself is to add at compile time a table of facts to the Prolog database. This is done by term expansion, a mechanism for code transformations, usually used through term_expansion/2. You need the definition of my_class/1 so that term_expansion/2 can pick it up, transform it, and replace it with the expanded code. I strongly suggest you take the snipped above, put it in a file, consult it and use listing/1 to see what is the effect. I get:
?- listing(my_class).
my_class(126).
my_class(33).
my_class(64).
my_class(35).
my_class(36).
true.
NB: In this example, you could replace the two occurrences of my_class(_) with anything. You could have just as well written:
term_expansion(foobar, Clauses) :-
findall(my_class(C),
string_code(_, "~!##$", C),
Clauses).
foobar.
The end result is identical, because the operational meaning is identical. However, using my_class(_) is self-documenting, and makes the intention of the code more obvious, at least to an experienced Prolog developer as the author of SWI-Prolog ;).
A fact is just a bodiless rule, as you call it. And yes, there are plenty of use cases for bodiless facts:
representing static data
base cases for recursion
instead of some curly brace language pseudo code
boolean is_three(integer x) {
if (x == 3) { return true; }
else { return false; }
}
we can simply write
is_three(3).
This is often how the base case of a recursive definition is expressed.
To highlight what I was initially looking for, I'll include the following short answer for those who might find themselves asking my initial question in the future.
An example of a bodiless rule is, as #Anniepoo suggested, a base case for a recursive definition. Look to the example of a predicate, member(X,L) for illustration:
member(X,[X|T]). /* recursive base case*/
member(X,[H|T]):- member(X,T).
Here, the first entry of the member rule represents a terminating base case-- the item of interest X matching to the head of the remaining list.
I suggest visiting #Boris's answer (accepted) for a more complete treatment.

SWI-Prolog goal fail variable binding result

Is there any way that I can get a binding for a variable in Prolog even if the goal fails. I have a predicate where I am binding a variable with some value and after this I am failing the goal explicitly, but when I run the query it simply results in a fail without providing any biding for the variable. Something similar:
a(X) :-
X = 'something',
fail.
#Will Ness is correct (+1), assert can be used to capture bindings of variables as shown.
However, if you strictly need to retrieve bindings for variables in predicates like a and you know which parts could fail (and you don't care about them), then you could use combinations of cut (!) and true to permit a to proceed regardless. For example, consider:
a(X) :-
goalA(X), % a goal for which we definitely want a binding
(goalB, ! ; true). % an 'optional' goal which may fail
goalA('something').
goalB :- fail.
Executing this gives a('something'), even though goalB failed. Note that this isn't a commonly used way to program in Prolog, but if you know exactly what you're doing...
yes, this is how it is supposed to happen in Prolog. fail means the rejection of bindings made so far, because it says that these bindings are invalid, do not satisfy the goal.
but you can save some binding that will be undone on backtracking, with e.g. asserta predicate:
a(X) :-
X = 'something',
asserta(saved_x(X)),
fail.
Then, if you query saved_x(Z) afterwards, you will recover that value. Of course this is the part of Prolog that is extra-logical, i.e. outside of the logical programming paradigm.

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)

Resources