# Swiplserver: store the result in a string Prolog can handle?

**URL:** <https://swi-prolog.discourse.group/t/swiplserver-store-the-result-in-a-string-prolog-can-handle/4957>\
**Category:** Help!\
**Created:** [January 30, 2022, 3:54pm UTC](https://swi-prolog.discourse.group/t/swiplserver-store-the-result-in-a-string-prolog-can-handle/4957 "2022-01-30T15:54:56Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Losbarthos](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/losbarthos/32/4037_2.png) [@Losbarthos](https://swi-prolog.discourse.group/u/Losbarthos)\
**Post date:** [January 30, 2022, 3:54pm UTC](https://swi-prolog.discourse.group/t/swiplserver-store-the-result-in-a-string-prolog-can-handle/4957/1 "2022-01-30T15:54:56Z")

</div>

I search some way to translate the output of swiplserver queries into some result string SWI-Prolog can handle with

E.g. the query:

**Example 1**

```prolog
from swiplserver import *

with PrologMQI() as mqi:
    with mqi.create_thread() as prolog_thread:
        result = prolog_thread.query("A = point{x:1, y:2}.put([x=3,z=0]).")
        print(result)

```

results in:  
**Python output**

> [{‘A’: {‘args’: [{‘x’: 1, ‘y’: 2}, {‘args’: [[{‘args’: [‘x’, 3], ‘functor’: ‘=’}, {‘args’: [‘z’, 0], ‘functor’: ‘=’}]], ‘functor’: ‘put’}], ‘functor’: ‘.’}}]

**Output in SWI-Prolog**

> A = point{x:3, y:2, z:0}.

If I now want to change the result (maybe with `A=point{x:3, y:2, z:0}.put([z=4]).`), my first task is, to translate the result in some string prolog is able to accept as parameter (in an easy way).

The easiest way to do this is maybe to store the result string in some .txt-file and read that out with python.

This can be done for an arbitrary predicate in SWI-Prolog by

**Output in SWI-Prolog**

```prolog
?- protocol('text.txt').
true.

?- A = point{x:1, y:2}.put([x=3,z=0]).
A = point{x:3, y:2, z:0}.

?- noprotocol.
true.

```

But for some reason the simulation in swiplserver doesn’t generate some file, means if I try to simulate it with code:

**Example 2**

```prolog
from swiplserver import *

with PrologMQI() as mqi:
    with mqi.create_thread() as prolog_thread:
        prolog_thread.query("protocol('text.txt').")
        result = prolog_thread.query("A = point{x:1, y:2}.put([x=3,z=0]).")
        prolog_thread.query("noprotocol.")
        print(result)

```

The server generates some file “test.txt” but doesn’t store the result of my query inside of it. In summary my two questions are:

1. Is their some simple way to manage the outputs swiplserver gives me for further inputs in prolog predicates (see result of example 1)?
2. What is the reason the result of my query in example 2 is not stored in the file “text.txt”?

---

<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:** [January 31, 2022, 7:42am UTC](https://swi-prolog.discourse.group/t/swiplserver-store-the-result-in-a-string-prolog-can-handle/4957/2 "2022-01-31T07:42:35Z")

</div>

> [@Losbarthos](#):
>
> Is their some simple way to manage the outputs [swiplserver](https://pypi.org/project/swiplserver/) gives me for further inputs in prolog predicates (see result of example 1)?

Here you seem to want the Prolog textual representation of an answer. You can use e.g. term\_string/2,3. In the toplevel REPL running a query proves the query and prints the result.

> [@Losbarthos](#):
>
> What is the reason the result of my query in example 2 is not stored in the file “text.txt”?

protocol/1 logs the output that is sent to the `user_output` and `user_error` streams. Running a query doesn’t send anything there unless the query uses write/format/…

---

<div class="post-metadata">

**Author:** ![Losbarthos](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/losbarthos/32/4037_2.png) [@Losbarthos](https://swi-prolog.discourse.group/u/Losbarthos)\
**Post date:** [January 31, 2022, 8:58am UTC](https://swi-prolog.discourse.group/t/swiplserver-store-the-result-in-a-string-prolog-can-handle/4957/3 "2022-01-31T08:58:24Z")

</div>

Thank your for your reply, how exactly can I call term\_string/2, if my prolog queryin swiplserver is

```prolog
A = point{x:1, y:2}.put([x=3,z=0]).

```

means

```prolog
from swiplserver import *

with PrologMQI() as mqi:
    with mqi.create_thread() as prolog_thread:
        result = prolog_thread.query("A = point{x:1, y:2}.put([x=3,z=0]).")
        print(result)

```

and my result should be  
`

> A = point{x:3, y:2, z:0}.  
> `

I just tried as left and right hand parameter both the query itself and the result string but it is not the desired result.

---

<div class="post-metadata">

**Author:** ![ericzinda](https://avatars.discourse-cdn.com/v4/letter/e/b3f665/32.png) [@ericzinda](https://swi-prolog.discourse.group/u/ericzinda)\
**Post date:** [February 2, 2022, 2:41am UTC](https://swi-prolog.discourse.group/t/swiplserver-store-the-result-in-a-string-prolog-can-handle/4957/4 "2022-02-02T02:41:45Z")

</div>

At least part of the question here is why:

> A = point{x:1, y:2}.put([x=3,z=0]).

returns this from the top level:

> A = point{x:3, y:2, z:0}.

but this from the MQI:

> [{‘A’: {‘args’: [{‘x’: 1, ‘y’: 2}, {‘args’: [[{‘args’: [‘x’, 3], ‘functor’: ‘=’}, {‘args’: [‘z’, 0], ‘functor’: ‘=’}]], ‘functor’: ‘put’}], ‘functor’: ‘.’}}]
> 
> which is the JSON form of:
> 
> A = point{x:1, y:2}.put([x=3,z=0])
> 
> i.e. the top level seems to be evaluating the right side before unifying with `A` but the MQI is not.

@jan do you have insight into what the top level is doing here that is different than a basic query like `A = term(a, b, c)`?

---

<div class="post-metadata">

**Author:** ![CapelliC](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/capellic/32/17_2.png) [@CapelliC](https://swi-prolog.discourse.group/u/CapelliC)\
**Post date:** [February 2, 2022, 6:40am UTC](https://swi-prolog.discourse.group/t/swiplserver-store-the-result-in-a-string-prolog-can-handle/4957/5 "2022-02-02T06:40:45Z")

</div>

Absolutely not sure this will help, but did you noticed that MQI loses ‘point’ (i.e. the dict tag) ?  
Could be an indicator of a glitch in the interface ?

---

<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:** [February 2, 2022, 7:54am UTC](https://swi-prolog.discourse.group/t/swiplserver-store-the-result-in-a-string-prolog-can-handle/4957/6 "2022-02-02T07:54:27Z")

</div>

> [@ericzinda](#):
>
> @jan do you have insight into what the top level is doing here that is different than a basic query like `A = term(a, b, c)` ?

Most likely that you need to call expand\_goal/2 on the goal you receive before calling it.

> [@CapelliC](#):
>
> but did you noticed that [MQI](https://www.swi-prolog.org/pldoc/doc_for?object=section(%27packages/mqi.html%27)) loses ‘point’ (i.e. the dict tag) ?  
> Could be an indicator of a glitch in the interface ?

Well spotted. It isn’t the cause of this problem though. The dict `put` operation does not depend on the tag.

---

<div class="post-metadata">

**Author:** ![ericzinda](https://avatars.discourse-cdn.com/v4/letter/e/b3f665/32.png) [@ericzinda](https://swi-prolog.discourse.group/u/ericzinda)\
**Post date:** [February 2, 2022, 6:17pm UTC](https://swi-prolog.discourse.group/t/swiplserver-store-the-result-in-a-string-prolog-can-handle/4957/7 "2022-02-02T18:17:29Z")

</div>

> [@jan](#):
>
> Most likely that you need to call [expand\_goal/2](https://www.swi-prolog.org/pldoc/doc_for?object=expand_goal/2) on the goal you receive before calling it.

Yes, this fixes the first problem so that the MQI now returns `[{'A': {'x': 3, 'y': 2, 'z': 0}}]` from `result = prolog_thread.query("A = point{x:1, y:2}.put([x=3,z=0]).")`. Thanks @Jan!

The fix for losing the dict tag (thanks for pointing this out @CapelliC) is different. It looks like I need to pass an option to json\_write/2 to get that to be output (example below from the docs for that predicate).

Is it not on in json\_write/2 by default since the `type` JSON dict entry it generates could conflict with an existing entry called `type`? The JSON format allows (but discourages) duplicate keys. Python (and C#, I don’t know about others) accept it fine and just throw out one of the duplicates. It seems to me that the confusion of losing a duplicate key is worse than the confusion of losing the dict type, so I’m inclined to change the MQI to always included. However, I’m not a user of dicts and don’t know the history of why json\_write/2 chose to go this way.

Any thoughts?

```prolog
?- json_write(current_output, point{x:1,y:2}).
{
  "x":1,
  "y":2
}

?- json_write(current_output, point{x:1,y:2}, [tag(type)]).
{
  "type":"point",
  "x":1,
  "y":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:** [February 3, 2022, 8:39am UTC](https://swi-prolog.discourse.group/t/swiplserver-store-the-result-in-a-string-prolog-can-handle/4957/8 "2022-02-03T08:39:05Z")

</div>

Dicts map pretty much naturally to JSON, but JSON does not have a notion of a _tag_ (which was added first of all to resolve syntax ambiguity). Just adding the tag as “type” is dubious. The dict tag often has no (useful) meaning. You could also add it as e.g. `"$tag"`?

---

<div class="post-metadata">

**Author:** ![ericzinda](https://avatars.discourse-cdn.com/v4/letter/e/b3f665/32.png) [@ericzinda](https://swi-prolog.discourse.group/u/ericzinda)\
**Post date:** [February 3, 2022, 6:06pm UTC](https://swi-prolog.discourse.group/t/swiplserver-store-the-result-in-a-string-prolog-can-handle/4957/9 "2022-02-03T18:06:47Z")

</div>

Ahh! I didn’t realize the name ‘type’ was user settable from the docs on json\_write/3.

If knowing tag is not that useful, I see two options:

1. Just leave it off (as it is now) and see if there are actual requests to include it
2. Provide an (off by default) option to include it and allow the user to set the name (same approach as json\_write/3). I could start by having this be an option on mqi\_start/1. If users end up wanting more granularity we can add overrides to the setting on the connection, or even per query, later.

Seems like #1 is the easiest approach since I haven’t seen a real request for this yet, but let me know if you think it is important enough to add the option.

---

<div class="post-metadata">

**Author:** ![ericzinda](https://avatars.discourse-cdn.com/v4/letter/e/b3f665/32.png) [@ericzinda](https://swi-prolog.discourse.group/u/ericzinda)\
**Post date:** [February 15, 2022, 7:09pm UTC](https://swi-prolog.discourse.group/t/swiplserver-store-the-result-in-a-string-prolog-can-handle/4957/10 "2022-02-15T19:09:33Z")

</div>

I have just [submitted a fix](https://github.com/SWI-Prolog/packages-mqi/commit/49a732655a782dd16c911723f88208ee53ec4b9e) for your original issue @Losbarthos:

```prolog
from swiplserver import *

with PrologMQI() as mqi:
    with mqi.create_thread() as prolog_thread:
        result = prolog_thread.query("A = point{x:1, y:2}.put([x=3,z=0]).")
        print(result)

```

now works like the top level and does goal expansion. So it prints:

```prolog
[{'A': {'x': 3, 'y': 2, 'z': 0}}]

```

It doesn’t change the protocol so you don’t need a new swiplserver Python library, just a new version of MQI.pl which you can get from [here](https://github.com/SWI-Prolog/packages-mqi/blob/49a732655a782dd16c911723f88208ee53ec4b9e/mqi.pl). Download that version and install it (see [the documentation](https://www.swi-prolog.org/packages/mqi/prologmqi.html) for the full instructions), like this on the command line:

```prolog
swipl -s mqi.pl -g "mqi:install_to_library('mqi.pl')" -t halt

```

I went with option 1 (above) for how dicts get written out, so no changes there.
