Reputation: 403
I am trying to develop a "simplest" prolog program.
Method 1
Conceptually, the program creates a set of facts which are stored in the database, to be queried later.
% simple facts
apple.
banana.
orange.
cherry.
The database can be queried as expected.
?- apple.
true
?- mango.
procedure `mango' does not exist
Method 2
Most textbooks which teach prolog would start such a "simplest" program using predicates, something like:
% simple facts
exists(apple).
exists(banana).
exists(orange).
exists(cherry).
The queries would then change in nature to testing whether the predicate can be satisfied, eg:
?- exists(apple).
true
?- exists(mango).
false
Question:
Is Method 1 an incorrect use of prolog? If so, why?
In my understanding, prolog is testing whether queries can be shown to be true, and to do this the database is searched. My doubt is raised by the error "procedure `mango' does not exist".
Upvotes: 2
Views: 125
Reputation: 71070
The predicate exists/1
exists, the predicate apple/0
exists, the predicate mango/0
does not exist.
The query exists(apple).
successfully reports true
("succeeds" in the Prolog vernacular), the query exists(mango).
successfully reports false
("fails" to be proven, in the vernacular), the query apple.
successfully reports true
and the query mango.
fails to execute because the predicate mango/0
does not exist.
So we can say that apple
"exists
", mango
does not "exist
", apple/0
exists, but mango/0
does not exist.
However, (in SWI Prolog),
11 ?- mango.
ERROR: toplevel: Undefined procedure: mango/0 (DWIM could not correct goal)
12 ?- [user].
:- dynamic(mango/0).
|: ^Z
true.
13 ?- mango.
false.
So you can work with your 1st method too, if you declare all the predicates of interest as dynamic
.
Upvotes: 3
Reputation: 28963
I think you are focusing on a distinction between "facts" and "predicates" which does not really exist; apple.
is apple().
a predicate with no body and no arguments. The following shape:
name(argument1, argument2) :-
n2(arg3),
n3(arg4).
says that "name holds for the given arguments if n2 and n3 hold for their arguments", i.e. name only holds in certain conditions. Take the conditions away and you get:
name(argument1, argument2).
Now there are no conditions where it can fail, so it says "name holds for the given arguments". It always holds, it's like an unchanging fact, but "fact" is not a different kind of thing in Prolog, it's still a term with a functor and arity which can be called, it's just that the body of code to check is effectively true
and nothing else.
Take the arguments away and you get:
name.
"name holds". It's similar to name().
, no arguments.
The way Prolog is implemented, these are close to functions, procedures, subroutines in other languages - they are not the same, but Prolog looks through your code for one with a matching name (functor) and matching number of arguments (similar to method overload resolution in other languages), and calls it with the given arguments and sees whether it holds or not. If it cannot find a matching name and number of arguments, you get the "procedure does not exist" error.
In typical Prolog usage, the style name(argument1, argument2)
is used so that "name" tries to describe a logical relation between the arguments, and the arguments are the data being related. e.g. length(List, Quantity)
tries to explain that List is related to Quantity through the relation of length.
With method 2 you can extend it to:
exists(apple).
exists(crabapple).
exists(concrete).
food(apple).
food(crabapple).
food(snozzcumber).
edible(apple).
edible(snozzcumber).
and then ask for all things which exist, all foods, all edible things, or combinations like foods which are fictional and edible, things which exist but are inedible, etc. With method 1 you can say that apple holds, but you can't easily use it as data, can't easily query for all things which exist, can't easily change the code to describe that apple exists and is edible. With method 2 you can ask ?- exists(X).
and have Prolog fill in X
and tell you that apple exists. You can't easily do that with method 1.
If you put the data in place of the name (functor) that's like storing food by using an empty text file named 'apple.txt' and an empty text file named 'banana.txt' and so on, instead of putting them in a single file exists.txt. It's not a syntax or logical error to do this, if there is a reason you want to do it like that then you can, so it's hard to call it strictly "incorrect". Also like using a SQL database and making a table 'apple' and a table 'banana' and so on, instead of putting them in a table 'fruit'. Like having a bookshelf with a book named 'apple' and a book named 'banana' and so on, instead of one book named 'Fruits of the World'. You can do that, it's not incorrect to name a book "apple", but it's not a good way to use books to store lists of fruit.
If you specifically want something for codegolf where shortness trumps all other concerns then yes, fine. But it is going against the grain, against the normal use, it limits what you can do and it's not how Prolog was built to be used. It's also hard to describe something with fewer characters as "simpler" if it means a weird, limited, non-standard way of doing things.
Upvotes: 3