Read a file line by line error in prolog - prolog

For reading a file i'm using below code, but this code reads only lines where there is a '.' in the end of file, is there another way to read any kind of file and store in the list?
main :-
open('myFile.txt', read, Str),
read_file(Str,Lines),
close(Str),
write(Lines), nl.
read_file(Stream,[]) :-
at_end_of_stream(Stream).
read_file(Stream,[X|L]) :-
\+ at_end_of_stream(Stream),
read(Stream,X),
read_file(Stream,L).
I took this code from this link
Read a file line by line in Prolog

Please note that the code you wrote is inherently incorrect for the following reasons.
1mo, you are reading Prolog data, and not lines at all. Take a. b. c. which would make a list [a,b,c].
2do, testing for at_end_of_stream/1 is extremely tricky, and does not work as expected when reading Prolog data. Take the 3-line file:
first_fact.
second_fact.
% no comment - oh that's a comment nevertheless
This will give you the list [first_fact, second_fact, end_of_file]. For read/1 gives you a term end_of_file after having read the last line.
3tio, upon backtracking, main will always produce an error!
?- main.
[first_fact,second_fact,end_of_file]
true ;
ERROR: at_end_of_stream/1: stream `<stream>(0x1c38330)' does not exist
If you want to read just bytes use library(pio). And to use that, first learn the dcg formalism.
The following will succeed for each occurrence of magic in the file:
?- phrase_from_file((..., "magic", ...), filename).
using the following definition of ... //0:
... --> [] | [_], ... .
See this for more.

Related

Use expand_term/2 with file for dcg translation

I'm trying to "translate" a file that contains dcg's. in particular i am trying to transform all dcg into normal definite clauses using expand_term/2, however i would like to avoid manually translating all dcgs, so i would try to translate all clauses of the file at once (e.g. passing the whole file) . is there any way to do it?
for example, suppose we have a temp.pl file which contains some dcg:
a(X,Y) --> b(X), c(Y).
d([A | Ax]) --> b(A).
....
....
instead of using expand_term/2 individually for each term, like:
?- expand_term((a(X,Y) --> b(X), c(Y)), Clause).
Clause = [(:-non_terminal(user:a/4)), (a(X, Y, _A, _B):-b(X, _A, _C), c(Y, _C, _B))].
And then replace the dcg with definite clause in file.
I would like to pass for example the whole file (to a clause for example
) which contains the dcg, and translate all the dcg at once and print in a file or as an output, I don't know.
If I understand your question correctly then you are missing the obvious which is that what you seek is already in the SWI-Prolog code. The translation is done as the module is loaded. If you use listing/1 on a DCG predicate the code will list as normal Prolog and not DCGs.
See
dcg.pl
load.pl
expand.pl
apply_macros.pl
Demonstration of listing/1 with DCG
Directory: C:/Users/Groot
File: example.pl (Based on this SO answer )
:- module(example,
[
monlangage/2
]).
:- set_prolog_flag(double_quotes, chars).
monlangage --> "ab" | "a", monlangage.
Example run
Welcome to SWI-Prolog (threaded, 64 bits, version 8.5.3)
...
?- working_directory(_,'C:/Users/Groot').
true.
?- [example].
true.
?- listing(example:_).
monlangage(A, B) :-
( A=[a, b|B]
; A=[a|C],
monlangage(C, B)
).
true.
Notice that the source code is DCG with --> and the listing is not DCG with :-. Also notice that the rewritten clause has two extra arguments.

How to setup a PrologScript

I setup the following rules to find if there is a relationship between two elements:
directReference(A,B) :- projectReferences(A,B).
transitiveReference(A,C) :- directReference(A,B),directReference(B,C).
transitiveReferenceD1(A,D) :- transitiveReference(A,C),directReference(C,D).
transitiveReferenceD2(A,E) :- transitiveReferenceD1(A,D),directReference(D,E).
Can I write a PrologScript that will check all these queries for a fact? Although I plan to use Ruby&Rake, someone is trying to do a non-interactive call from PHP here and it has not worked. I also saw this answer and tried Kaarel's answer. I just added a new opts_spec:
opts_spec(
[ [opt(day), type(atom),
shortflags([d]), longflags(['term', 'day']),
help('name of day')]
, [opt(goal),
shortflags([g]), longflags([goal]),
help('goal to be called')]
, [opt(projectReferences), type(atom),
shortflags([pr]), longflags(['term', 'projectReferences']),
help('Project Reference lookup')]
]
).
I then compiled with:
.\swipl.exe -o day.exe -g main -c "D:\DevProjects\AskJoe\Output\Sample.pro"
And ran it with:
./day.exe -g "day(Sunday)"
And got error:
ERROR: Prolog initialisation failed: ERROR: validate_opts_spec/1:
Domain error: unique_atom' expected, foundterm' (ambiguous flag)
My goal is to have this work:
./day.exe -g "transitiveReference('a','b')"
I don't like compiling a "day.exe" to run a script (according to the docs this often is not necessary), but I have found no other way to pass arguments to rules.
I saw a basic intro on swi-pl.org that has not helped much. It does not explain how to make the leap from the script.sh file example to the execution of ./eval 1+2. In fact, the example is a comment so I'm totally lost
Here is a very crude example of a PrologScript program that will read its arguments as a single goal (which may be compound), call it, and then terminate. It should work on *nix systems, and has been tested on OS X. It is just a slight variation of the example program given for using PrologScript in the SWI docs:
#!/usr/bin/env swipl
:- initialization main.
query :-
current_prolog_flag(argv, Argv),
concat_atom(Argv, ' ', Atom),
read_term_from_atom(Atom, Term, []),
call(Term).
main :-
catch(query, E, (print_message(error, E), fail)),
halt.
main :-
halt(1).
projectReferences(valueA, valueB) :- writeln('I was called!').
directReference(A,B) :- projectReferences(A,B).
transitiveReference(A,C) :- directReference(A,B),directReference(B,C).
transitiveReferenceD1(A,D) :- transitiveReference(A,C),directReference(C,D).
transitiveReferenceD2(A,E) :- transitiveReferenceD1(A,D),directReference(D,E).
After saving this file as, e.g., cli_test.pl, you'll need to change the permissions on the file so that the operating system will recognize it as an executable:
chmod -x scratchboard.pl
After that, you should be able to call the file as as a normal executable from the command line:
$ path/to/the/file/scratchboard.pl 'transitiveReferenceD1(A,D).'
I was called!
Note:
The goal to be evaluated is simply passed as a single argument. query/0 will then retrieve this argument using current_prolog_flag/2, read it as a Prolog term, and call it.
Since the program is not running in interactive mode, the only output will result from explicit imperatives to write out, such as occur if catch/3 (in the body of main/0) is triggered by an error or if projectReferences/2 is called successfully.
Using library(optparse) seems advisable for more complicated cli interface, but is not necessary for your stated aim of merely querying goals in a file.
I understand that getting the PrologScript approach to work on Windows is somewhat different. A bit of information can be fond here: http://www.swi-prolog.org/FAQ/PrologScript.html
So I got this all working and then after a few runs everything just stopped. I started getting 'permission denied bad interpreter' errors. All I can say is that it has something to do with the hashBang. The workaround for me was to create a shell script around the call to swipl:
shellscript.sh
#!/bin/bash
swipl -s script4.pl 'projectReferences(A,D).'
Then I continued using aBathologist's example, but just took off the hashBang:
:- initialization main.
query :-
current_prolog_flag(argv, Argv),
concat_atom(Argv, ' ', Atom),
read_term_from_atom(Atom, Term, []),
call(Term).
main :-
catch(query, E, (print_message(error, E), fail)),
halt.
main :-
halt(1).
projectReferences(valueA, valueB) :- writeln('I was called!').
directReference(A,B) :- projectReferences(A,B).
transitiveReference(A,C) :- directReference(A,B),directReference(B,C).
transitiveReferenceD1(A,D) :- transitiveReference(A,C),directReference(C,D).
transitiveReferenceD2(A,E) :- transitiveReferenceD1(A,D),directReference(D,E).

running prolog as a script

So, I have some Prolog code that models variable assignments, such as in a programming language, and tries to see if they are compatible with one another. So,
assigned(X, X).
and(P, Q) :- P, Q.
or(P, Q) :- P.
or(P, Q) :- Q.
% and then we should test an expression like this:
and(assigned(X, 5), assigned(X, 6)).
So that last expression fails, since X can't be assigned to both 5 and 6.
Now, what I want to do is have this test a single expression (which can and should be hardcoded into the file), and then simply print out whether or not it's able to be satisfied. But it seems that SWIPL really wants me to run interactively. Ideally, something like this:
> ./test-assignments
false.
Surely this is possible? I'm at my wit's end on this.
There are several ways to get an SWI-Prolog program to run directly from the shell. You can look at this question and the answers:
How to run SWI-Prolog from the command line?
My personal preference now is to have a file example.pl like this:
:- set_prolog_flag(verbose, silent).
:- initialization(main).
main :-
format('Example script~n'),
current_prolog_flag(argv, Argv),
format('Called with ~q~n', [Argv]),
halt.
main :-
halt(1).
which I then run from the command line with:
$ swipl example.pl and a few arguments
Example script
Called with [and,a,few,arguments]
The initialization directive tells the interpreter which goal to evaluate after it loads the program: here it is main/0. The name main is a convention, it could have been called anything else.
See the linked question and answers for other options.

Prolog, getting right answer in terminal, but wrong answer when running a program

Typing "prolog" in terminal gets:
GNU Prolog 1.3.0
By Daniel Diaz
Copyright (C) 1999-2007 Daniel Diaz
| ?-
Typing:
| ?- member(2, [1,2,3]).
Gets:
true ?
Then pressing enter gets:
yes
Typing:
| ?- member(4, [1,2,3]).
gets:
no
When i write a file; test.pl consisting of this:
:- member(4, [1,2,3]), nl, halt.
And then write in the terminal:
| ?- [test2].
I get:
compiling /path/test.pl for byte code...
/path/test.pl:1: warning: unknown directive (',')/2 - maybe use initialization/1 - directive ignored
/path/test.pl compiled, 1 lines read - 139 bytes written, 11 ms
yes
Shouldnt the answer here be no? What am i doing wrong. Also, how would you do this in prolog:
if (testInPrologTerminal(member(4, [1,2,3])) { do this; }
I.e, i want to send queries to the prolog top level, and get an answer
When you type the query member(2, [1,2,3]), GNU Prolog prompts you for a possible additional solution (hence the true ? prompt) as only by backtracking (and looking to the last element in the list, 3) it could check for it. When you press enter, you're telling the top-level interpreter that you are satisfied with the current solution (the element 2 in the list second position). The second query, member(4, [1,2,3]), have no solutions so you get a no.
To execute a query when a file is loaded, the standard and portable way of doing it, is to use the standard initialization/1 directive. In this case, you would write:
:- initialization((member(4, [1,2,3]), nl, halt)).
Note the ()'s surrounding the query, otherwise you may get a warning about an unknown initialization/3 standard, built-in, control construct. If you have more complex queries to be executed when a file is loaded, then define a predicate that makes the queries a call this predicate from the initialization/1 directive. For example:
main :-
( member(4, [1,2,3]) ->
write('Query succeeded!'), nl
; write('Query failed!'), nl
).
:- initialization(main).
Writing arbitrary queries as directives in a source file is legacy practice and thus accepted by several Prolog implementations but using the initialization/1 directive is the more clean, standard, and portable alternative.

What is wrong with the following piece of code in prolog?

I am new to prolog and trying a very simple example on http://www.compileonline.com/execute_prolog_online.php . Here is my code:
:- initialization(main).
main :-
female(ayse).
?- female(ayse).
But it gives an error saying that:
/web/com/136989421322328/main.pr:5:4: syntax error: . or operator expected after expression
1 error(s)
compilation failed
where line 5 is the line starts with ?. What is wrong here? Can anyone help?
Thanks.
This code works:
:- initialization(hello).
hello :- write('hello').
Lines:
you say you want to have a predicate called hello that will be specified in the following lines that shell be executed when everything is loaded.
you declare the predicate.
"hello implies write('hello') is true"
What you wanted to write is
:- initialization(main).
female(ayse).
main :- female(ayse), write('ayse is female').

Resources