Space in ":-" not yielding an error

Clauses being split by the :- character sequence, if I intentionally put a blank space between the two characters, SWI-Prolog seems to only give an error when the body is composed by two or more goals, but not if the body is composed by only one.

Source that throws:

:- module(_, []).

a :- write(a), nl. % ok clause

b : - write(b), nl. % error (as expected)

Source that does not throw:

:- module(_, []).

a :- write(a), nl. % same

b : - write(b). % no error (removed the second goal)

I can’t seem to find what “happens” to that second rule.

listing does not show it and predicate_property(<module_name>:Pred) only yields a/0, but if I do source_file_property(<file_path>, number_of_clauses(X)) I get 2 clauses, and I’m sure that b/0 is the second one because without it the source has only one.

So, what happens to a rule in the form of <head> : - <goal>. and is this ISO behavior?

(I need to know this because I’m trying to implement an accurate TextMate grammar for VS Code, and I need to be sure of :- not allowing any space in it.)

I didn’t dig deeply into understanding the problem but did try this

?- write_canonical(b : - write(b)).
:(b,-(write(b)))
true.

versus

?- write_canonical(b :- write(b)).
:-(b,write(b))
true.

See: What does the colon (:) exactly stand for in Swi-Prolog?

That’s the module qualifier

I didn’t think about write_canonical, thanks.

So is the line parsed as a fact with the head having the : functor and two args?

(I just tried and it still doesn’t get listed as a clause, though.)

I would not argue so much with that. If one want to split hairs I am sure they could find parts of that I would not agree with but spending hours arguing about how many angels can dance on the head a pin is not something I care to do.


If one does

?- assert(b : - write(b)).
true.

then one can use listing to see the result

?- listing(b:G).

:- dynamic (-)/1.

-write(b).
true.

b before : is the name of a module as seen by using b in listing(b:G).

The :- dynamic (-)/1. makes one think it is a predicate so trying

?- b: -(X).
X = write(b).

does work.

So with regards to your question of wondering if that is valid Prolog syntax, the answer is yes.


EDIT

More fun information

?- predicate_property(b:Head,Property).
Head = -_,
Property = interpreted ;
Head = -_,
Property = visible ;
Head = -_,
Property =  (dynamic) ;
Head = -_,
Property = number_of_clauses(1) ;
Head = -_,
Property = number_of_rules(0) ;
Head = -_,
Property = last_modified_generation(5973) ;
Head = -_,
Property = defined ;
Head = -_,
Property = size(256) ;
false.
1 Like

Since your example term b : - write(b) is a corner case, using with print_term/2 did this

?- print_term(b : - write(b),[]).
b:-write(b)
true.

That does not look correct. I would expect

?- print_term(b : - write(b),[]).
b: -write(b)
true.

or similar with a space between the : and the -.

1 Like