I am very new to Prolog and trying to learn.
For my program, I would like to have the user provide pairs of strings which are "types of".
For example, user provides at command line the strings "john" and "man". These atoms would be made to be equal, i.e. john(man).
At next prompt, then user provides "man" and "tall", again program asserts these are valid, man(tall).
Then the user could query the program and ask "Is john tall?". Or in Prolog: john(tall) becomes true by transitive property.
I have been able to parse the strings from the user's input and assign them to variables Subject
and Object
.
I tried a clause (where Subject and Object are different strings):
attribute(Subject, Object) :-
assert(term_to_atom(_ , Subject),
term_to_atom(_ , Object)).
I want to assert the facts that Subject and Object are valid pair. If the user asserts it, then they belong to together. How do I force this equality of the pairs?
What's the best way to go about this?
Don't do variable fact heads. Prolog works best when the set of term names is fixed. Instead, make a generic place for storing properties using predefined, static term name, e.g.:
(think SQL tables in a normal form). Then you can use simple
assertz/1
to update the database:Questions of this sort have been asked a lot recently (I guess your professors all share notes or something) so a browse through recent history might have been productive for you. This one comes to mind, for instance.
Your code is pretty wide of the mark. This is what you're trying to do:
Using it works like this:
So, here's what you should notice about this code:
=../2
, the "univ" operator, to build structures from lists. This is the only way to create a fact from some atoms.assertz/1
orasserta/1
, notassert/2
. The a and z on the end just tells Prolog whether you want the fact at the beginning or end of the database.Based on looking at your code, I think you have a lot of baggage you need to shed to become productive with Prolog.
assert(term_to_atom(...
wasn't even on the right track, because you seemed to think thatterm_to_atom
would "return" a value and it would get substituted into theassert
call like in a functional or imperative language. Prolog just plain works completely differently from that.term_to_atom
predicates. I think you did that to satisfy the predicate's arity, but this predicate is pretty useless unless you have one ground term and one variable.assert/2
, but it doesn't do what you want. It should be clear why assert normally only takes one argument.property(subject...)
. It is not easy to construct facts and then query them, which is what you'd have to do usingman(tall)
. What you want to say is that there is a property, being tall, andman
satisfies it.I would strongly recommend you back up and go through some basic Prolog tutorials at this point. If you try to press forward you're only going to get more lost.
Edit: In response to your comment, I'm not sure how general you want to go. In the basic case where you're dealing with a 4-item list with [is,a] in the middle, this is sufficient:
If you want to isolate the first and last and create the fact, you have to use univ again:
Not sure if you want to live with the articles ("a", "the") that will wind up on the end though: