Of course, the error message is misleading. The correct solution is indeed to use initialization/2, preferably with type main. Typically you want to combine that with library(main), which provides Ctrl-C handling and option parsing.
Let me explain what is wrong with initialization/1.
initialization/1 is executed after loading a file. This implies that if you call initialization/1 to run the entry point, you can only do so from the “main” file. Embedding this goal in some indirectly loaded file will cause it to executed before all code is loaded.
The second problem is that SWI-Prolog loads files while protecting against interrupts. This includes running the initialization goals. This is needed to avoid partial lazy loading due to interrupts/timeout.
IMO, initialization/1 only makes sense to perform preparation steps that cannot be part of the compilation process itself.
SWI-Prolog introduced initialization/2 to give more control over when the initialization is performed. Notably :- initialization(mygoal, main). will run the entry point. This is executed after all code is loaded and the interrupt protection is released. The nice thing of this is also that the entry point is not executed if
- The file was loaded with
swipl -l file.pl ...
- The file was loaded from the interactive toplevel.
This makes debugging and running comfortable. To run, use
swipl script.pl <script arg ...>
To debug, run
swipl -l script.pl <script arg ...>
Setup your debugging and call the entry point from the toplevel.
I’ve changed the message to
> src/swipl top.pl aap
Hello aap
Warning: [Thread main] /home/jan/src/swipl-devel/build/top.pl:1: top
Warning: [Thread main] Initialization goal called halt(0).
Warning: [Thread main] The program entry point should be called using initialization/2.
Warning: [Thread main] Consider using library(main).
The problem is the non-standard behaviour. Alternatively we could opt to make the initialization goals for the toplevel script special? I’m afraid that will be a bit fragile though.
Suggestions?