0
votes

I am trying to create a rule called great_show/1 that checks that a show has a rating of at least 8. Here is the fact base:

show(mad_men, 2007, 8.6).
show(breaking_bad, 2008, 9.5).
show(outlander, 2014, 8.5).
show(the_xfiles, 1993, 8.7).
show(friends, 1994, 8.9).
show(general_hospital, 1963, 6.3).
show(the_walking_dead, 2010, 8.4).
show(game_of_thrones, 2011, 9.4).
show(rick_and_morty, 2013, 9.5).
show(the_soprano, 1999, 9.2).

I tried this, but SWI-Prolog gave me an unknown procedure error:

?- great_show(show(movie, year, rating) :- rating>8.5).

Then, I tried this and it gave me several errors including an unknown procedure error and an error message saying that rules should be loaded from a file but that shouldn't be necessary.

?- great_show(Z):-show(X,Y,_),Z>8.5.

What should I do? Thank you in advance for any guidance you can give me.

2

2 Answers

1
votes

The error message is right: In SWI-Prolog and most other Prologs, rules must be loaded from a file. Your facts are in a file as well, right? In the same file, add (thanks Enigmativity for the correct definition, even though they seem to have missed the real problem you were having):

great_show(Z) :- show(Z,_,R), R > 8.5.

then load the file as before. Now you can call great_show at the interactive prompt:

?- great_show(Z).
Z = breaking_bad ;
Z = the_xfiles ;
Z = friends ;
Z = game_of_thrones ;
Z = rick_and_morty ;
Z = the_soprano.

The interactive ?- prompt is for queries. It is not meant for defining code. Source files are for defining code but not for running queries. (This is different from some other languages with interactive prompts that also allow you to define code at the prompt.)

There are two unsatisfactory workarounds:

At the interactive prompt in SWI-Prolog, you can run the special goal [user], which will allow you to define things:

?- [user].
|: hello(world).
|: hello(stack_overflow).
|: ^D% user://1 compiled 0.01 sec, 2 clauses
true.

(The ^D shows where I typed Ctrl-D after I was done inputting code, on Windows you might need to use Ctrl-Z instead.)

Now you have actually defined code that you can use:

?- hello(Who).
Who = world ;
Who = stack_overflow.

But this isn't how you should edit your program since there's no way to save the code, and if you notice a typo you made in an earlier line, there's no way to fix it.

Another workaround is to use assert:

?- assert((great_show(Z) :- show(Z,_,R), R > 8.5)).
true.

This is usable, and you can even retract code if you make mistakes, but you still cannot save your work and really, why not just write code in your editor?

0
votes

It appears you haven't understood the structure of predicates and what makes a term an atom or a variable.

Your first attempt (?- great_show(show(movie, year, rating) :- rating>8.5).) was trying to define a fact in terms of a rule with no variables

The second (?- great_show(Z):-show(X,Y,_),Z>8.5.) was super close, but you chose to ignore the rating, i.e. _, but you expected the calling to pass in the rating.

This is what you needed:

great_show(Z) :- show(Z,_,R), R > 8.5.