P.Brian.Mackey
P.Brian.Mackey

Reputation: 44275

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

Upvotes: 2

Views: 446

Answers (2)

P.Brian.Mackey
P.Brian.Mackey

Reputation: 44275

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).

Upvotes: 0

Shon
Shon

Reputation: 4098

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

Upvotes: 2

Related Questions