# How to call a predicate with arguments from command line and output its solution?

**URL:** <https://swi-prolog.discourse.group/t/how-to-call-a-predicate-with-arguments-from-command-line-and-output-its-solution/6919>\
**Category:** General\
**Tags:** how-to\
**Created:** [October 24, 2023, 3:52pm UTC](https://swi-prolog.discourse.group/t/how-to-call-a-predicate-with-arguments-from-command-line-and-output-its-solution/6919 "2023-10-24T15:52:01Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![raffael](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/raffael/32/5771_2.png) [@raffael](https://swi-prolog.discourse.group/u/raffael)\
**Post date:** [October 24, 2023, 3:52pm UTC](https://swi-prolog.discourse.group/t/how-to-call-a-predicate-with-arguments-from-command-line-and-output-its-solution/6919/1 "2023-10-24T15:52:01Z")

</div>

Hello!

My actual application is more complicated than the following illustrative predicate but I chose it as it is because it covers various features which I would need to handle. I tried around with `initialization` and some of the `swipl` attributes but cannot really get it to work and also can’t find good documentation on it.

Assuming this is stored in a file called app.pl:

```prolog
t([X1, X2|[]], X3, Y) :- 
    Y1 is X1 + X2, 
    Y2 is 2 * X3, 
    Y = [Y1, Y2]
.

```

What I eventually want to be able to do is something like that (this is just plausible pseudo code):

```prolog
swipl -f app.pl -c 't([1,2],3,Y)'

```

And then receive the response `Y = [3,6]` for further processing on STDOUT.

I don’t really want to introduce necessarily a `main` procedure. Though, it would also be interesting to see how that would work, too. But my eventual goal is to call individual predicates from Python or Bash for testing.

In fewer words, I want to emulate a single invocation in a swipl REPL session from the Linux command line.

I found a way to do it but I’m not super happy with the solution for obvious reasons.

```prolog
➜ swipl -g "[app]." -g "t([1,2],3,Y), writeln(Y)" -g halt
[3,6]

```

It’s pretty hacky. I tried at least replacing `-g "[app]."` with `-f app.pl` but that failed. Also `-F`, `-l`, `-s` didn’t work for loading the database.

Kind Regards

Raffael

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [October 24, 2023, 4:13pm UTC](https://swi-prolog.discourse.group/t/how-to-call-a-predicate-with-arguments-from-command-line-and-output-its-solution/6919/2 "2023-10-24T16:13:17Z")

</div>

> [@raffael](#):
>
> It’s pretty hacky.

What’s “hacky” about this? I’ve seen lots of `bash` scripts that use `bash -c`, similarly for Python; it seems reasonable to do the same for Prolog (except Prolog has more control over the top-level, via the `-g` option).

As for `-f` … perhaps `-f none -l app.pl` does what you want? And/or use initialization/2 ?

---

<div class="post-metadata">

**Author:** ![raffael](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/raffael/32/5771_2.png) [@raffael](https://swi-prolog.discourse.group/u/raffael)\
**Post date:** [October 24, 2023, 4:31pm UTC](https://swi-prolog.discourse.group/t/how-to-call-a-predicate-with-arguments-from-command-line-and-output-its-solution/6919/3 "2023-10-24T16:31:20Z")

</div>

First of all I made a mistake. Using `-f app.pl` does actually work:

```prolog
> ➜ swipl -f app.pl -g "t([1,2],3,Y), writeln(Y)" -g halt
> [3,6]

```

That looks much better. I find it still a bit “hacky” because the invocation requires string processing beyond the predicate call; having to append `"..., writeln(Y)"`. Also the explicit `halt` seems dubious 😉 My code smell detector is going off seeing that. But of course, it’s better than nothing.

[pyswip](https://github.com/yuce/pyswip) also looks promising for a clean integration.

Regarding `initialization`. Am I right to assume that this would be relevant for declaring a main predicate which is called implicitely?

This wouldn’t be relevant for this use case as I intend to test isolated (sets of) predicates but might be useful if I want to turn this into an executable (`chmod +x`).

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [October 24, 2023, 4:54pm UTC](https://swi-prolog.discourse.group/t/how-to-call-a-predicate-with-arguments-from-command-line-and-output-its-solution/6919/4 "2023-10-24T16:54:07Z")

</div>

> [@raffael](#):
>
> the explicit `halt` seems dubious

This is just a way of saying “don’t use the REPL and all its goodies” (the REPL is prolog/0). In other words, it’s a way of saying “this is a command line”, except it has more flexibility by allowing you to define your own REPL (or none).

> [@raffael](#):
>
> Am I right to assume that [initialization/2] would be relevant for declaring a main predicate which is called implicitely?

Yes. And for this, you would load the program using just `swipl ... app.pl` rather than `swipl .. -l appl.pl` (`-l` loads the file without invoking anything specified by initialization/1 or initialization/2, although that isn’t spelled out in the documentation - @jan perhaps this could be clarified?)

> [@raffael](#):
>
> turn this into an executable (`chmod +x`)

See `swipl -c` and qsave\_program/2.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [October 25, 2023, 7:33am UTC](https://swi-prolog.discourse.group/t/how-to-call-a-predicate-with-arguments-from-command-line-and-output-its-solution/6919/5 "2023-10-25T07:33:53Z")

</div>

> [@raffael](#):
>
> `swipl -f app.pl -g "t([1,2],3,Y), writeln(Y)" -g halt`

The current “recommended” way is

```
swipl -g "t([1,2],3,Y), writeln(Y)" -t halt app.pl

```

It would be possible to write a support file `query.pl` such that you can do e.g.

swipl query.pl app.pl “t([1,2],3,Y)”

`query.pl` would use initialization/2 to start the execution, get the query and print the results. What I think is still missing is a way to comfortably load a library like Python’s `-m module` That would allow to put query.pl in the library and run

```
swipl -m query app.pl "t([1,2],3,Y)"

```

Would this make sense? If it does, should `-m lib` terminate the option list, passing all remaining options to the application? In the above that would mean that the library must decide to load `app.pl`

---

<div class="post-metadata">

**Author:** ![raffael](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/raffael/32/5771_2.png) [@raffael](https://swi-prolog.discourse.group/u/raffael)\
**Post date:** [October 25, 2023, 10:04am UTC](https://swi-prolog.discourse.group/t/how-to-call-a-predicate-with-arguments-from-command-line-and-output-its-solution/6919/6 "2023-10-25T10:04:36Z")

</div>

> [@jan](#):
>
> The current “recommended” way is
> 
> ```prolog
> swipl -g "t([1,2],3,Y), writeln(Y)" -t halt app.pl
> 
> ```

Okay, that’s good to know. Thanks.

> [@jan](#):
>
> Would this make sense?

I’m not sure how `query` here would be different from `t(...)` but that might well be because I’m very new to Prolog and still mess up the terminology.

Generally, though, that looks great. But after a quick research I must say that my reference point Python isn’t doing this much different anyway. Seems like I was suffering from false memory here. Calculating sine would look like this.

`python3 -c "import math;x=math.sin(1);print(x);"`

Only thing different is the not required explicit halt.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [October 25, 2023, 12:39pm UTC](https://swi-prolog.discourse.group/t/how-to-call-a-predicate-with-arguments-from-command-line-and-output-its-solution/6919/7 "2023-10-25T12:39:37Z")

</div>

> [@raffael](#):
>
> I’m not sure how `query` here would be different

`swipl -m query ...` would (when implemented), be the same as

```
swipl -g '[library(query)]' -- ...

```

The (not existing) library(query) would than handle processing additional Prolog files, running a query and printing the result. More in general, using a `-m library` we would have a more friendly commandline interface for many tasks. for example, this could install an extension pack.

```
swipl -m packs install mypack

```

> [@raffael](#):
>
> Only thing different is the not required explicit halt.

You can also do

```
swipl -q -t "writeln(hello)"
hello

```

It is not recommended though as exceptions in the “toplevel” goal cause Prolog to restart it 🙂 That is what happens on an “uncaught exception”.

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [October 25, 2023, 5:25pm UTC](https://swi-prolog.discourse.group/t/how-to-call-a-predicate-with-arguments-from-command-line-and-output-its-solution/6919/8 "2023-10-25T17:25:45Z")

</div>

Possibly you’d want a `--libs` option and/or use an environment variable (`PLLIBS`), to specify the library search order. There’s already an option to disable packs (`--packs`, which is useful for testing), so the definition could get a bit messy.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [October 27, 2023, 8:44am UTC](https://swi-prolog.discourse.group/t/how-to-call-a-predicate-with-arguments-from-command-line-and-output-its-solution/6919/9 "2023-10-27T08:44:23Z")

</div>

> [@peter.ludemann](#):
>
> to specify the library search order

That is supported using `-p library:<dir>`. The `-p` flag extends the search paths maintained by file\_search\_path/2.

This is mostly about avoiding horrible syntax such as

```
 swipl -g "[library(prolog_pack)]" ...

```

This is no fun to type on the commandline and when dealing with several layers of scripting in between, quoting this properly can be a nightmare. If we have some option to load a file from some search path, this file can use initialization/2 using `main` and take over processing the remainder of the commandline. That might be a convenient way to provide Prolog based commandline tools that is platform independent.
