I am learning Prolog ideas and here is what I want to practice:
I want to write a Prolog program that can work like this:
?- input([apple,is,fruit]).
?- input([chicken,is,meat]).
?- input([Is,apple,meat]).
No, it is a fruit
?- input[(Is,chicken,meat])
Yes.
And when I was trying to implement this program, I got some problem:
(1) I used this code trying to read the input and distinguish between questions and assertions, but it fails:
input([]).
input([X|R]) :- X is 'Is', write('test code read question'); write("test code read assertion").
(2) I am still confused about How I can filter the useful information out from the input message. For example, in the [Apple,is,fruit]input array, all I need is apple and fruit. How do we normally do to jump the is word?
I don’t want to hardcode too many things to the program, and prefer a good functional programming style to solve the problem that can help me learn from it.
Thank you in advance.
Just because I enjoy them, I’d be inclined towards a definite clause grammar (DCG). Then you can make statements and parse them fairly easily:
The trick going on here with DCGs is that your grammar is being transformed to a difference list representation. The part in brackets is normal Prolog code; the part around it is interpreted either as literal parts of the list or as other grammar rules. So [Word] is matching one atom. We could actually write the rule like this:
and it would have the same effect, and perhaps be more readable, but I like being pedantic. Note especially the use of
=.., which converts lists into facts and vice versa (so[fruit, apple]becomesfruit(apple)).Parsing with DCGs is quite easy: use
phrase/2:Then you can use
assertato insert these clauses into the dynamic store:For example:
Now you can write another clause for parsing queries:
Looks very similar! And again, if you wanted, you could use this syntax:
Now you might want to write a clause to combine both grammar rules into one “sentence” rule:
Try it out:
You see now we get not just the parsed fact, but also a wrapper that tells us whether it was a statement or a query. We can now parse with this instead of statement and query, and rewrite
inputlike so:I’ve added an auxiliary to handle the work:
This will be convenient later as you add more grammatical abstractions: each
performclause handles a different “sentence” type, so you do your parsing above and handle the work below. And now we have, more or less, what you wanted:You can improve things by introducing a cut in your
sentencerule and handling true/false with special output, but I think this is the direction I’d want to go in, particularly if you want to be able to handle different syntax in the future.