19

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

Lance
  • 75,200
  • 93
  • 289
  • 503
  • 1
    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). –  Aug 27 '14 at 06:00
  • What's the point of `-q -f` ? – theonlygusti Dec 17 '22 at 16:56

3 Answers3

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

CapelliC
  • 59,646
  • 5
  • 47
  • 90
  • 1
    how do you run this from the command line? still getting the same errors as before :/, when doing `./hello.pl` – Lance Aug 24 '14 at 06:14
  • 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. –  Aug 25 '14 at 11:16
  • For a non-trivial working example, see also: https://stackoverflow.com/questions/58867730/how-do-i-run-a-prolog-file-from-the-command-line-and-not-drop-to-the-repl – dariox Feb 24 '22 at 16:44
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.

  • 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 ~/.plrc – CapelliC Aug 26 '14 at 06:42
  • 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? – Lance Aug 26 '14 at 07:34
  • @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`? –  Aug 26 '14 at 07:38
  • @CapelliC 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.html –  Aug 26 '14 at 08:00
  • @Boris: thanks, I wasn't unable to recovery that Jan' message, that clarifies the whole question. I've linked the [documentation](http://www.swi-prolog.org/pldoc/man?section=plscript) page to this thread... – CapelliC Aug 26 '14 at 08:06
  • @CapelliC And regarding your comment on the documentation, see my edit. –  Aug 26 '14 at 09:47
  • 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. – Paul Williams Dec 08 '20 at 15:55
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))

Flux
  • 9,805
  • 5
  • 46
  • 92
  • This does not work with SWI-Prolog (threaded, 64 bits, version 8.1.21) on Windows. – Guy Coder Feb 13 '20 at 13:01
  • @GuyCoder What happens on Windows? – Flux Feb 13 '20 at 13:11
  • `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. – Guy Coder Feb 13 '20 at 13:23
  • `What happens on Windows?` `main` is not run. You just get `?- ` – Guy Coder Feb 13 '20 at 13:25
  • @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. – Flux Feb 13 '20 at 13:45
  • 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. – Guy Coder Feb 13 '20 at 13:56