The major attraction of library(pio)
is that it simply applies a DCG to a file.
So, first, you need to have a basic understanding of DCGs in Prolog.
See dcg for more information.
Next, focus on how you would normally describe the task with a DCG. You want to describe a list that contains [m,y,p,h,r,a,s,e
], or—speaking in codes—[109,121,etc.]
, as a sublist.
A useful nonterminal for describing anything at all is:
... --> [] | [_], ... .
And so we can describe a list with the given property as:
contains_myphrase -->
...,
"myphrase",
... .
The beauty of this is that we can already test it interactively:
?- length(Ls, _), phrase(contains_myphrase, Ls).
Ls = [109, 121, 112, 104, 114, 97, 115, 101] ;
Ls = [109, 121, 112, 104, 114, 97, 115, 101, _8260] ;
Ls = [_8212, 109, 121, 112, 104, 114, 97, 115, 101] ;
Ls = [109, 121, 112, 104, 114, 97, 115, 101, _8260|...] ;
Ls = [_8212, 109, 121, 112, 104, 114, 97, 115, 101|...] ;
Ls = [_8212, _8218, 109, 121, 112, 104, 114, 97, 115|...] .
And then we can also apply the same DCG to a file:
?- phrase_from_file(contains_myphrase, 'b.txt').
true .
It is straight-forward to generalize this so that you can specify what you are looking for as an argument.
However, I recommend to first do this without using phrase_from_file/2
. Simply work on the DCG, and study the different encodings. In particular, you should find out the difference between:
- atoms
- lists of codes
- lists of characters.
Make the following work first:
?- phrase(contains(MyPhrase), Ls).
This should hold iff Ls
contains MyPhrase
as a sublist, where MyPhrase
could for example be specified as a list of codes. I say "could" because you should pick an encoding that is most convenient and natural for your use case. From personal experience, I can tell you that using lists of characters is by far more convenient than using lists of codes. A Prolog flag you may find relevant in this context is called double_quotes
.
Once you have this solved with a DCG, it is straight-forward to use phrase_from_file/2
on it.
query -> true ; false
. The query will already succeed or fail, so the->
here is nearly redundant producing the same result, except it will prevent backtracking to query for more than one solution. Backtracking probably doesn't apply forphrase_from_file/2
so it is serving no purpose. – lurker; false
either, for the same reason. At that point, thephrase_from_file
call has already failed. Why do you need to callfalse
? – lurker