Scryer-prolog: Clauses are sometimes ignored

Created on 4 Jul 2020  路  7Comments  路  Source: mthom/scryer-prolog

To reproduce, please clone the repository

https://github.com/triska/the-power-of-prolog/

and start the server with:

$ scryer-prolog -g "server(6012)" server.pl

Then direct your browser to: http://localhost:6012/prolog/clpfd

The server emits:

waiting for connections...
handling client '127.0.0.1:59647'...
request is for "prolog/clpfd"
sending 'prolog/clpz.html'
etc.

This works completely as expected.

However, when I change the order of clauses in the definition of path_file/2 to read:

path_file("prolog", "prolog/prolog.html").
path_file("prolog/clpfd", "prolog/clpz.html").
path_file(Path, HTML) :- append(Path, ".html", HTML).
path_file(Path, File) :-
        path_segments(Path, Segments),
        append(_, [Last,[]], Segments),
        phrase(format_("~s~s.html", [Path,Last]), File).
path_file(Path, Path).

i.e., I move the previously fourth clause to become the second clause, and then direct my browser to http://localhost:6012/prolog/clpfd, then I get:

waiting for connections...
handling client '127.0.0.1:59616'...
request is for "prolog/clpfd"
redirecting to: https://www.metalevel.at/prolog/clpfd
waiting for connections...

This seems to indicate that the second clause is now ignored, even though I expect it to be applicable for the requested path, "prolog/clpfd", and I expect the server to respond with the contents of prolog/clpz.html exactly as above.

Most helpful comment

The issue seems to be in Path. With this test:

$ echo "prolog/clpfd" > path.txt
$ cat test.pl
:- use_module(library(debug)).
:- use_module(library(dcgs)).
:- use_module(library(format)).
:- use_module(library(pio)).

seq([]) --> [].
seq([S|Ss]) --> [S], seq(Ss).

path_file("prolog", "prolog/prolog.html").
path_file("prolog/clpfd", "prolog/clpz.html").
path_file(A, B) :- format("a: ~q ~q\n", [A, B]).
$ scryer-prolog test.pl
?- phrase_from_file((seq(Path), "\n"), 'path.txt'), Path = "prolog/clpfd", path_file(Path, HTML).
a: "prolog/clpfd" A
   Path = "prolog/clpfd"
;  false.
?- *phrase_from_file((seq(Path), "\n"), 'path.txt'), Path = "prolog/clpfd", path_file(Path, HTML).
   Path = "prolog/clpfd", HTML = "prolog/clpz.html"
;  a: "prolog/clpfd" A
Path = "prolog/clpfd"
;  false.
?- 

This could be a partial string issue or phrase/phrase_from_file issue. More investigation is required.

All 7 comments

The issue seems to be in Path. With this test:

$ echo "prolog/clpfd" > path.txt
$ cat test.pl
:- use_module(library(debug)).
:- use_module(library(dcgs)).
:- use_module(library(format)).
:- use_module(library(pio)).

seq([]) --> [].
seq([S|Ss]) --> [S], seq(Ss).

path_file("prolog", "prolog/prolog.html").
path_file("prolog/clpfd", "prolog/clpz.html").
path_file(A, B) :- format("a: ~q ~q\n", [A, B]).
$ scryer-prolog test.pl
?- phrase_from_file((seq(Path), "\n"), 'path.txt'), Path = "prolog/clpfd", path_file(Path, HTML).
a: "prolog/clpfd" A
   Path = "prolog/clpfd"
;  false.
?- *phrase_from_file((seq(Path), "\n"), 'path.txt'), Path = "prolog/clpfd", path_file(Path, HTML).
   Path = "prolog/clpfd", HTML = "prolog/clpz.html"
;  a: "prolog/clpfd" A
Path = "prolog/clpfd"
;  false.
?- 

This could be a partial string issue or phrase/phrase_from_file issue. More investigation is required.

A brilliant test case, thank you a lot!

To avoid introducing unintended solutions, I often use false/0 when a clause is used only for output:

path_file(A, B) :- format("a: ~q ~q\n", [A, B]), false.

Yielding:

?- phrase_from_file((seq(Path), "\n"), 'path.txt'), Path = "prolog/clpfd", path_file(Path, HTML).
a: "prolog/clpfd" A
false.

and

?- *phrase_from_file((seq(Path), "\n"), 'path.txt'), Path = "prolog/clpfd", path_file(Path, HTML).
   Path = "prolog/clpfd", HTML = "prolog/clpz.html"
;  a: "prolog/clpfd" A
false.

This makes the difference immediately clear: One query succeeds, and the other fails without a single solution.

With path.txt as above, the following program shows the problem very clearly:

:- use_module(library(debug)).
:- use_module(library(dcgs)).
:- use_module(library(pio)).

seq([]) --> [].
seq([S|Ss]) --> [S], seq(Ss).

path_file("prolog", "prolog/prolog.html").
path_file("prolog/clpfd", "prolog/clpz.html").

We have:

?- Path = "prolog/clpfd", phrase_from_file((seq(Path), "\n"), 'path.txt'), path_file(Path, HTML).
   Path = "prolog/clpfd", HTML = "prolog/clpz.html".

But generalizing the query fails:

?- *Path = "prolog/clpfd", phrase_from_file((seq(Path), "\n"), 'path.txt'), path_file(Path, HTML).
false.

Here is another example of this phenomenon that arises before and also after the most recent commit:

test("a").
test("b").

I get, as expected:

?- test(Ls), Ls = [a|_].
   Ls = "a"
;  false.

However, exchanging the order of goals yields:

?- Ls = [a|_], test(Ls).
false.

This works nicely now, thank you a lot!

Are there any other cases like this? If not, I can close #642 too, however, I think adding a safeguard may still be a good idea!

Are there any other cases like this? If not, I can close #642 too, however, I think adding a safeguard may still be a good idea!

Not that I've found. Perhaps we should leave it open for a while in case we discover further issues?

Perfect, I will leave it open!

Issues like these are the worst problem: In a complex computation, nobody can tell whether there are solutions that ought to be reported but were not found by the system (for example, due to a problem with indexing). It is much preferable to crash instead of incorrectly failing silently, because then we at least get a chance to debug and correct the issue. Otherwise, such mistakes may go unnoticed, silently yielding incorrect results.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Qqwy picture Qqwy  路  3Comments

UWN picture UWN  路  3Comments

XVilka picture XVilka  路  3Comments

UWN picture UWN  路  4Comments

XVilka picture XVilka  路  3Comments