How to run SWI-Prolog from the command line?
Asked Answered
L

3

20

Is there a way to just create a prolog script called hello.pl like this:

#!/usr/local/bin/swipl -q -s -t main

main:-
  write('Hello World\n').

And be able to run it from the terminal like this?

$ hello.pl
Hello World
$

When I do that it gives me this:

hello.pl: line 3: main:-: command not found
hello.pl: line 4: syntax error near unexpected token `'Hello World\n''
hello.pl: line 4: `  write('Hello World\n').'

I am able to get it working by writing this on the command line:

$ swipl -q -f hello.pl -t main
Hello World
$

But is there a way to just run the straight script as an executable instead?

Edit

Haven't yet been able to get this to work. Here is the output from the commands @Boris asked in the comments in his answer:

$ ls -l
total 8
-rwxr-xr-x  1 viatropos  staff  235 Aug 26 20:28 example.pl
$ cat example.pl
#!/usr/local/bin/swipl

:- 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 swipl
/usr/local/bin/swipl
$ swipl --version
SWI-Prolog version 6.6.6 for x86_64-darwin13.1.0
$ ./example.pl
./example.pl: line 3: syntax error near unexpected token `('
./example.pl: line 3: `:- set_prolog_flag(verbose, silent).'
$

I am on Mac OSX 10.9.2, and installed swipl with homebrew via brew install swi-prolog --with-libarchive

Lifesaving answered 23/8, 2014 at 22:53 Comment(2)
Yes, it really seems like your OS does not recognize/respect the shebang line. Is is completely unacceptable to drop the shebang and do $ swipl example.pl instead, as shown in the edit to my answer? (you could try to put swipl example.pl in a script of its own, just to see if that does it).Johnathanjohnathon
What's the point of -q -f ?Jewelfish
H
15

ISO directive: initialization. This should work.

:- initialization main.

main :-
  write('Hello World\n').

edit sorry, I skipped over most interesting details. Here is a sample script, let's say saved in ~/test/main.pl

#!/home/carlo/bin/swipl -f -q

:- initialization main.

main :-
  current_prolog_flag(argv, Argv),
  format('Hello World, argv:~w\n', [Argv]),
  halt(0).

and made executable with

chmod +x ~/test/main.pl

then I get

~$ ~/test/main.pl
Hello World, argv:[]

~$ ~/test/main.pl as,dnj asdl
Hello World, argv:[as,dnj,asdl]

In script main.pl, I used the swipl path that results from building from source without admin privileges. The SWI-Prolog build process put bin and lib under ~/bin and ~/lib

Note: the -f flag disables loading the initialization ~/.plrc, and this could be necessary to get more 'strict control' over execution...

I'm currently unsure if the documentation page is up-to-date with current SW status. From some mailing list message, and my own efforts to reuse thea, seems that command line flags changed recently...

Highchair answered 23/8, 2014 at 23:16 Comment(3)
how do you run this from the command line? still getting the same errors as before :/, when doing ./hello.plLifesaving
This came up on the mailing list several times in the last 2 years. Jan Wielemaker eventually suggested not putting anything on the shebang line appart from the swipl executable path, for compatibility reasons (this is at least what I understood). See my answer.Johnathanjohnathon
For a non-trivial working example, see also: #58868230Dashboard
J
7

The other answer is more or less correct, however, how it works might depend on your OS. The most portable way to do it is, appartently:

$ cat example.pl
#!/path/to/your/swipl

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

The difference here is that there is nothing on the shebang line apart from the path to swipl. Everything else is done using directives. On my OS, only that worked!

$ chmod u+x example.pl
$ example.pl foo bar baz
Example script
Called with [foo,bar,baz]

EDIT

It is probably cleaner to remove the shebang line altogether, and instead run from the command line:

$ swipl -s example.pl -- foo bar baz
Example script
Called with [foo,bar,baz]

Again, using a directive to set main/0 as the initialization goal saves you from having to explicitly do this on the command line. Calling swipl from the command line, on the other hand, lets your OS find where the executable is, instead of hard-coding this information in the script.

Johnathanjohnathon answered 25/8, 2014 at 5:10 Comment(7)
thanks Boris, for taking a look at this issue. Are you using bash on MacOS ? Based on my experiments, the culprit seems to be the -s flag, and the interaction with initialization script ~/.plrcHighchair
this is weird, mine is still giving me the same errors as before, I think it's treating it as a shell file for some reason. any ideas?Lifesaving
@LancePollard So what is your file at the moment? Can you add to your original question the output of ls -l and cat on your script file and which swipl and swipl --version?Johnathanjohnathon
@Highchair I am using several different Linux distributions (home, work, laptop). This answer comes from here: lists.iai.uni-bonn.de/pipermail/swi-prolog/2013/011296.htmlJohnathanjohnathon
@Boris: thanks, I wasn't unable to recovery that Jan' message, that clarifies the whole question. I've linked the documentation page to this thread...Highchair
@Highchair And regarding your comment on the documentation, see my edit.Johnathanjohnathon
On my windows box w/ version 8.2.3, running swipl -s example.pl -- foo bar baz prints Called with [--,foo,bar,baz]. Not sure if this is expected. Repros in CMD and Powershell.Abelmosk
T
2

You can use initialization/2.

#!/path/to/swipl -q

:- initialization(main, program).

main :-
    write("Hello"), nl,
    halt.

Rationale:

  • -q (--quiet) is used to suppress all informational messages, including informational messages that originate from the SWI-Prolog initialization file (~/.swiplrc). :- set_prolog_flag(verbose, silent). could be used instead, but it does not suppress informational messages that come from the initialization file.

  • :- initialization(main, program). - program causes Prolog to exit with an error code on failure of main or on encountering an exception, rather than staying in the REPL.

  • halt - Stops the program with exit code 0.

The above assumes that you wish to load the initialization file (~/.swipl) before running the program. If you do not want to load the initialization file, use #!/path/to/swipl -f -q as the shebang. This makes the script start up faster.

(Also, be sure to set the executable bit (chmod +x hello.pl) before running the script (./hello.pl))

Tc answered 6/7, 2019 at 2:19 Comment(6)
This does not work with SWI-Prolog (threaded, 64 bits, version 8.1.21) on Windows.Lafountain
@GuyCoder What happens on Windows?Tc
What happens on Windows? First is that #!/path/to/swipl -q or similar results in Syntax error: Operator expected. So that needs to be commented out our deleted for Windows.Lafountain
What happens on Windows? main is not run. You just get ?- Lafountain
@GuyCoder It's because Windows doesn't support shebangs. Note that the OP asked for a solution for OS X, a Unix-like system that supports shebangs. On Windows, you must remove the shebang, and you can probably run the program using something like swipl -q ./hello.pl instead.Tc
It was just a comment. There was no down-vote or anything else. It was just pointing out that this would not work on Windows. Many users will read just the title and then look at the answers. Also many will not look at the comments, but if they do then they might see that it is not expected to work on Windows.Lafountain

© 2022 - 2024 — McMap. All rights reserved.