daniel235
daniel235

Reputation: 21

How can I solve the Syntax error in Prolog SWI?

I'm getting 'Syntax error: Operator expected' and also the Warnings: 'Singleton variables: ... ".

Here's my code:

schwester_von(A,B) :- 
  weiblich(C),
  mutter_von(C,A),
  mutter_von(C,B),
  A \== B.

grossvater_von(A,B) :-
  maennlich(A),
  (
    vorfahr_von(A,C),
    (
      vater_von(C,B)
    ;
      mutter_von(C,B).
                                                    
vorfahr_von(A,B) :-
  vater_von(A,B)
  ;
  mutter_von(A,B)
  ;
  (
    (
      vater_von(A,C)
    ;
      mutter_von(A,C)
    ),
    vorfahr_von(C,B)
  ).

einzelkind(A) :-
  (
    vater_von(B,A)
  ;
    mutter_von(C,A)
  ),
  not(
      bruder_von(A,D)
    ;
      schwester_von(A,E)
  ).

vater_von(Stefan,Barbara).
vater_von(Stefan,Anna-Lena).
mutter_von(Marianne,Barbara).
mutter_von(Marianne,Anna-Lena).
mutter_von(Barbara,Timo).
vater_von(Christopher,Timo).
mutter_von(Anna-Lena,Ursula).
mutter_von(Anna-Lena,Thomas).
vater_von(Christian,Ursula).
vater_von(Christian,Thomas).
mutter_von(Ursula,Uta).
vater_von(Ralf,Uta).
vater_von(Thomas,Sven).
mutter_von(Sabrina,Sven).

I tried to avoid the spaces after the opening bracket but the errors are still there.

Upvotes: 2

Views: 331

Answers (1)

firefrorefiddle
firefrorefiddle

Reputation: 3805

I agree with the commenter who suggested you need a better editor. SWI-Prolog includes a version of emacs, which you can use right now. If you are on Windows, all it takes is probably File-open. Syntax and error highlighting will show you quickly what's wrong. As a beginner, you may be even better off with VSCode.

I would also suggest that you start to write you code in English, it's a good habit. For example, some reading this question will not understand what your predicates mean, which makes it harder to answer.

Now let's have a look at the code.

grossvater_von(A,B) :-
  maennlich(A),
  (
    vorfahr_von(A,C),
    (
      vater_von(C,B)
    ;
      mutter_von(C,B).

This causes the syntax error. You need closing parentheses:

grossvater_von(A,B) :-
  maennlich(A),
  (
    vorfahr_von(A,C),
    (
      vater_von(C,B)
    ;
      mutter_von(C,B)
    )
  ).

But the logic is really muddled together. You define a grandfather as someone who's male (alright!), and also the ancestor of someone who is either the father or the mother of the grandchild. That's not right.

  • A should not be some ancestor, but precisely the father of C.
  • If you had used the father_of (vater_von) instead of ancestor, you needn't even specify that he is male, but that's.
  • It would be nicer to have an auxiliary parent_of (elternteil_von) predicate, so you don't need that many conjunctions. Try it!
vorfahr_von(A,B) :-
  vater_von(A,B)
  ;
  mutter_von(A,B)
  ;
  (
    (
      vater_von(A,C)
    ;
      mutter_von(A,C)
    ),
    vorfahr_von(C,B)
  ).

Again, this will be much clearer when you replace each instance of vater_von;mutter_von with parent_of (elternteil_von). Same thing with brothers and sisters.

Now to:

vater_von(Stefan,Barbara).

That looks innocent, but will totally confuse you because it's absolutely wrong. Stefan and Barbara are free variables, and totally unrestricted. When you define it like that you can also ask

?- vater_von(pi, 3.14).
true 

Because Prolog binds Stefan=pi and Barbara=3.14. That's also the reason for the "Singleton variable" warning. It means that these variables occur only once in the rule, which is often an indication for an error on your side, because they are not really useful like that.

Of course, you didn't mean to use variables in the first place, but atoms. Lowercase them or quote them, either is fine:

vater_von(stefan,barbara).
vater_von('Stefan','Barbara').

Even worse:

vater_von(Stefan,Anna-Lena).

Anna-Lena is an application of the functor - to two variables, Anna and Lena. Here, you just have to quote it:

vater_von('Stefan','Anna-Lena').

One more thing: You will also have noted the warnings about discontiguous predicates. As a rule, keep all the rules for a predicate together - first state all vater_von facts, then all mutter_von facts, don't mix them up.

It is possible to use a :- discontiguous directive in cases where that is impractical.

Upvotes: 1

Related Questions