# Ann: SWI-Prolog 9.1.19

**URL:** <https://swi-prolog.discourse.group/t/ann-swi-prolog-9-1-19/6978>\
**Category:** Releases\
**Created:** [November 16, 2023, 4:35pm UTC](https://swi-prolog.discourse.group/t/ann-swi-prolog-9-1-19/6978 "2023-11-16T16:35:42Z")\
**Posts on this page:** 15\
**Page:** 1

<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:** [November 16, 2023, 4:35pm UTC](https://swi-prolog.discourse.group/t/ann-swi-prolog-9-1-19/6978/1 "2023-11-16T16:35:42Z")

</div>

Dear SWI-Prolog user,

SWI-Prolog 9.1.19 is ready fro download. The ChangeLog is quite long.  
Highlights:

- More work on Janus resulting from ongoing discussions. Introduced  
py\_setattr/3 to set attributes on objects (or modules). Added  
py\_module/2 to define Python modules from Prolog. Synchronised  
naming and semantics of Python functions with XSB. Mostly affects  
infrequently used functions.

- A lot of portability work. The ultimate target is to get a fully  
supported version running under Conda. The main bottleneck are  
serveral issues building the Windows version using MSVC with the  
Conda directory structure, which is similar to what is used in  
e.g., Linux. We are not there yet. We can claim robust builds  
using VS2022 that support the whole system and passes all tests.

- Introduce the already disussed `-Dflag=value` commandline option.  
In addition, this patch introduces flags whose domain is a set  
of atoms (oneof) and clarifies the relation to presetting a  
flag and later defining it using create\_prolog\_flag/3. Still  
needs to deal with flags that must be changed before booting  
the system. Please have a look and comment on what you think  
can be done better.

- Some more types to must\_be/2, has\_type/2: compound(Term) and  
type construction using conjunction, disjunction and negation.  
So, we can do `must_be((atom,\oneof([none])), X)` to indicate  
X shall be an atom, but not `none`.

- More (and more streamlined) control over rewriting optimizations  
as applied by library(apply\_macros), library(debug) and library(clpfd).  
More may follow.

- Make show\_coverage/2 using `dir(SomeDir)` to dump line-by-line  
coverage analysis data work together with unit tests.

- Several fixes to source code position reconstruction. Affects  
the above mentioned coverage tools as well as the source level  
debugger.

- Fixes in LibBF arithmetic. In part platform independent, in  
part for VS2022 and in part on 32-bit platforms.

- Fixed a few crashes (undo/1, tracer ‘S’ command)

- Fixed CVE-2023-45853 in included minizip source code. Isn’t  
that relevant for our usage, see below for details.

- Updated Emacs sweep interface.

P.s. Update of Ubuntu PPA is stalled due to bug  
[Bug #2043679 “dput is failing with 550 internal server error” : Bugs : Launchpad itself](https://bugs.launchpad.net/launchpad/+bug/2043679)

# SWI-Prolog Changelog since version 9.1.18

- SECURITY: CVE-2023-45853 Upstream bug in the _minizip_ library  
used to create and load Prolog saved states. Not very relevant  
to SWI-Prolog as it unlikely that SWI-Prolog is used in a way that  
provides uncontrolled access to the involved parameters.

- ADDED: create\_prolog\_flag/3: `type(oneof(ListOfAtoms))` This patch  
also cleans up the relation to create\_prolog\_flag/3 and existence of  
a flag with some value. Adds test cases.

- MODIFIED: set\_prolog\_flag/2: convert Booleans If set\_prolog\_flag/2 is  
used to create a new flag and the value is an atom that is recognised  
as a Boolean, normalise the value.

- ADDED: must\_be/2 and friends: constructed types and compounds Allow  
for e.g. compound(atom-integer) to express a pair mapping an atom to  
an integer. Also introduces constructed types such as `(atom;integer)`

- FIXED: #1205: sandbox:format\_calls/3 to handle non-list format args  
correctly.

- ADDED: Provide a mechanism to warn on unused Prolog flags

- ADDED: Allow `-Dno-flag`

- MODIFIED: library(apply\_macros) flags Now listens to `optimise_apply`,  
which defaults to `optimize`, while the flag `apply_macros_scope`  
defines whether the optimization applies to the files that import  
this library or all files (default).

- CLEANUP: Make `optimise_debug` flag library-only.

- MODIFIED: Renamed Prolog flag `clpfd_goal_expansion` to  
`optimise_clpfd` Improves consistency

- FIXED: Source position preservation of string tereminals in DCG.

- ADDED: Rewrite positions for function evaluation in meta-predicate  
arguments This fixes source location handling for clauses that  
call a meta-predicate where one of the non-meta arguments uses  
e.g. `Dict.attr`.

- FIXED: clause\_info/4: perform full body matching.

- FIXED: Clause position handling of plunit test/1,2 clauses.

- FIXED: ‘$notrace’/2 + ‘$restore\_trace’/2 pair to properly restore This  
pair now reliably restores LCO and VMI instruction optimization such  
that e.g., the coverage tools work properly after this pair is called.

- ENHANCED: load library(apply\_macros) globally on `-O`.

- FIXED: #1204: undo/1: crash if a single undo is scheduled that fails.

- FIXED: clause\_info/5 for unification moved into the head

- FIXED: clause/2: moved unifications If a unification is moved into  
the head and the variable is unified against some other variable,  
we must move the unification back.

- MODIFIED: Control transformations by library(apply\_macros). The new  
Prolog flag `apply_macros` controls when this library rewrites the  
code. Values are `true` (old default), `false` (no-op), `optimise`  
(only wwith -O) and `imported` (only apply to modules where it is  
explicitly imported to).

- ADDED: Process `-Dname=value` to set Prolog flags.

- FIXED: tracer `S` command to save the  
current goal. Reported by Wolfram Diestel  
([Stacktrace after hitting t S u while browsing through query solutions - #2 by wdiestel](https://swi-prolog.discourse.group/t/stacktrace-after-hitting-t-s-u-while-browsing-through-query-solutions/6963/2))

- PORT: MSVC install: there is no `libswipl.ddl.a`.

- PORT: Windows: deal with OpenSSL when using per-module CRT support.

- ADDED: Swin\_open\_osfhandle()

- PORT: Fixed integer addition overflow check when using MSVC

- PORT: Allow using Windows HANDLE in communicating about Prolog streams.

- BUILD: Make installation work again Broken with  
71caaeb72188627f0d717d251cab14d3e557a241

- BUILD: Simplify forced building of the library indices.

- PORT: Improve support for Conda on Windows. Adds a flag  
`conda`. Windows versions added `%CONDA_PREFIX%\Library\bin` and  
`%PREFIX%\Library\bin` to dependent DLL search path. This extends  
a similar work-around for MSYS2.

- DOC: Non-ISO behavior of `\+/1`

- PORT: Use uint64\_t for LibBF mpz\_ui\_pow\_ui() Switch to using the 64  
bit versions on all platforms. Requires some more 64 bit init/set  
versions, but overflow checking intrinsic \_\_umulh() for MSVC only  
exists of 64 bit.

- FIXED: gcd function for LibBF on platforms with 32 bit long.

- FIXED: mpz\_ui\_pow\_ui() emulation on LibBF on systems with 32 bit long.  
Breaks e.g. `A is 2^65`, succeeding with A = 0.

- ADDED: PL\_get\_delay\_list() API.

- CLEANUP: PL\_new\_term\_refs() now takes `size_t` argument (was `int`).

- DOC: Fix return types of Sfread() and Sfwrite() (`size_t` instead of  
`int`)

## Package chr

- BUILD: Another missing use\_module for maplist/3.

- BUILD: Avoid relying on autoloding during bootstrapping.

## Package clib

- ENHANCED: Make rewrite\_host/3 hook work fot tcp\_connect/3 Also allows  
tcp\_connect/3 to accept an IP number. These two enhancements avoid  
the need to lookup `localhost` on Windows.

- ADDED: socket:rewrite\_host/3 hook for tcp\_connect/2 This multifile  
hook allows for mapping hostnames, either directly to an IP address or  
another host. Currently a work-around for Windows broken handling of  
`localhost`, mapping it directly to the IP address 127.0.0.1.

- PORT: CRT handles for the process pipes must be owned by libswipl.dll.

- PORT: Work around inconsistent definitions for ETIMEDOUT on Windows.

- PORT: We cannot share Windows CRT stream handles with the Prolog core.

- PORT: Windows: create\_process/3: make stream(S) work. This patch  
fixes the options stdin(stream(S)), etc. when S denotes a file stream  
by enabling inheritance for the handle before calling ProcessCreate().

- FIXED: process\_create/3: Allow `user_input` (file\_no 0) for stream(S)

## Package cpp

- PORT: Removed check\_rc(). Seems not all C++ compilers can deal  
with this.

- ENHANCED: added unwrap() method and PlUnwrapPtr()

## Package http

- ENHANCED: http\_stop\_server/2: try to avoid connecting This sends  
a signal to the HTTP accept thread. To make sure the signal is  
processed it connects after the signal. Unfortunately this takes 2  
seconds before raising an error on Windows. We now first check that  
the signal is processed within 0.1 second. If so, we are happy.  
If not, we try to connect anyway.

## Package jpl

- PORT: Avoid conversion messages and warnings for MSVC

## Package plunit

- FIXED: show\_coverage/2: details for non-module files with tests.  
A non-module file that defines a test was not considere a non-module  
file due to the existence of the test module and as a result, coverage  
details were no shown for such files.

## Package ssl

- PORT: Add OPENSSL\_Applink() to ssl4pl.dll This function is used by  
OpenSSL to get module-consistent of the MS CRT library. It is expected  
at the application level. This patch tries to keep it locally in the  
ssl binding with a small relay function from the SWI-Prolog executable.

- PORT: Make use of OpenSSL “applink” Consistency use OpenSSL applink.c  
if this is defined. This patch itself does not enable applink.

- TEST: Allow running SSL test suite from main build directory.

- PORT: Create test certificates when running under Conda

## Package sweep

- ADDED: in-buffer completions for arithmetic functions \* sweep.pl  
(sweep\_function\_functors\_collection/2) (sweep\_functions\_collection/2):  
New predicates. (sweep\_context\_callable\_arg/4): Recognize arithmetic  
functions.

- ADDED: in-buffer completions for predicate options \* sweep.pl  
(sweep\_option\_functors\_collection/2) (sweep\_options\_collection/2)  
(sweep\_option\_arguments\_collection/2): New predicates.  
(sweep\_context\_callable\_arg/4): Recognize predicate options.

- ADDED: in-buffer completions for source file specs

- ENHANCED: Improve ‘sweeprolog-extract-region-to-predicate’ Teach  
‘sweeprolog-extract-region-to-predicate’ about existentially quantified  
goals and lambda terms.

- ADDED: new command ‘sweeprolog-query-replace-term’ This patch  
extends the Term Search infrastructure to support search-and-replace  
operations. Namely, we replace the predicate ‘sweep\_term\_search/2’  
with a new predicate ‘sweep\_term\_replace/2’ that subsumes the  
functionality of the former. The command ‘sweeprolog-term-search’  
is greatly simplified and adjusted to work with this new predicate,  
and we introduce a new command, ‘sweeprolog-query-replace-term’, that  
exposes the new search-and-replace facility of ‘sweep\_term\_replace/2’  
in an interactive UI inspired by ‘query-replace’.

- ENHANCED: Support pty top-level communication instead of TCP Add  
the ability for top-level buffers to communicate with their backing  
threads via pty instead of a local TCP connection. This is controlled  
by a new user option, enabled by default on systems where Emacs can  
creates a pty.

- ADDED: New command ‘sweeprolog-extract-region-to-predicate’ Add  
a command for extracting a part of a clause body into a separate  
predicate.

## Package swipy

- BUILD: Fix finding swipl for building pip Python package.

- MODIFIED: py\_call(Obj:Attr = Value) is now py\_setattr(Obj, Attr,  
Value). py\_call/1 still accepts this construct, printing a deprecation  
warning on the first encounter. Future versions will remove support.

- PORT: Fixed MSVC emulation of \_\_sync\_bool\_compare\_and\_swap() Could  
lead to an infinite loop in the atom garbage collector thread.

- ADDED: py\_load/2 to define a Python module from Prolog The name should  
not yet be considered “set in stone”

- STANDARD: janus.cmd() Moved the implementation to C to get max  
performance and return the truth value (True, False, janus.undefined).

- MODIFIED: Renamed XSB compatibility functions janus.px\_\* to remove  
the px\_

## Package xpce

- FIXED: Huge spacing in PceEmacs on some fixed width fonts.

---

<div class="post-metadata">

**Author:** ![kwon-young](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/kwon-young/32/4841_2.png) [@kwon-young](https://swi-prolog.discourse.group/u/kwon-young)\
**Post date:** [November 17, 2023, 6:56am UTC](https://swi-prolog.discourse.group/t/ann-swi-prolog-9-1-19/6978/2 "2023-11-17T06:56:38Z")

</div>

Thank you for your hard work !

> [@jan](#):
>
> Some more types to [must\_be/2](https://www.swi-prolog.org/pldoc/doc_for?object=must_be/2), [has\_type/2](https://www.swi-prolog.org/pldoc/doc_for?object=has_type/2): compound(Term)

About compound term types, the docuentation says:

> Compound with same name/arity as term; checks arguments

How are arguments checked ?

---

<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:** [November 17, 2023, 8:20am UTC](https://swi-prolog.discourse.group/t/ann-swi-prolog-9-1-19/6978/3 "2023-11-17T08:20:06Z")

</div>

> [@kwon-young](#):
>
> How are arguments checked ?

As types, so we can do `compound(atom-integer)` to specify `a-97` to be valid and `2-42` to be invalid.

Not that this does not allow for recursive definitions. If we want to do proper typing we need a proper type language. These do exist. Possibly that should be the next step towards typing that would be acceptable to everyone.

---

<div class="post-metadata">

**Author:** ![kwon-young](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/kwon-young/32/4841_2.png) [@kwon-young](https://swi-prolog.discourse.group/u/kwon-young)\
**Post date:** [November 17, 2023, 8:44am UTC](https://swi-prolog.discourse.group/t/ann-swi-prolog-9-1-19/6978/4 "2023-11-17T08:44:44Z")

</div>

> [@jan](#):
>
> Not that this does not allow for recursive definitions.

Does this mean that we still can’t do things like this ?

```prolog
compound(seg(
  compound(point(int, int)),
  compound(point(int, int)))).

```

---

<div class="post-metadata">

**Author:** ![Boris](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/boris/32/7486_2.png) [@Boris](https://swi-prolog.discourse.group/u/Boris)\
**Post date:** [November 17, 2023, 9:41am UTC](https://swi-prolog.discourse.group/t/ann-swi-prolog-9-1-19/6978/5 "2023-11-17T09:41:30Z")

</div>

After installing the [relocatable application bundle](https://www.swi-prolog.org/download/devel/bin/swipl-9.1.19-1.fat.dmg) I find on the [downloads page](https://www.swi-prolog.org/download/devel), I see the following in my terminal:

```prolog
$ swipl
Welcome to SWI-Prolog (threaded, 64 bits, version 9.1.18-70-g955571d43)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.

For online help and background, visit https://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).

?- ^D
% halt
$ swipl --version
SWI-Prolog version 9.1.19 for fat-darwin

```

Note that `9.1.18-70-g955571d43` up there.

Not sure what happened.

---

<div class="post-metadata">

**Author:** ![Boris](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/boris/32/7486_2.png) [@Boris](https://swi-prolog.discourse.group/u/Boris)\
**Post date:** [November 17, 2023, 10:52am UTC](https://swi-prolog.discourse.group/t/ann-swi-prolog-9-1-19/6978/6 "2023-11-17T10:52:08Z")

</div>

> [@kwon-young](#):
>
> Does this mean that we still can’t do things like this ?
> 
> ```prolog
> compound(seg(
> compound(point(int, int)),
> compound(point(int, int)))).
> 
> ```

We can do this:

```prolog
foo(X) :-
    must_be(
        compound(
            seg(
                compound(point(integer,integer)),
                compound(point(integer,integer)))),
        X),
    format(user_error, "~w", [X]).

```

And with it:

```prolog
?- foo(seg(point(1,2), point(3,4))).
seg(point(1,2),point(3,4))
true.

?- foo(seg(point(0.1,2), point(3,4))).
ERROR: Type error: `compound(seg(compound(point(integer,integer)),compound(point(integer,integer))))' expected, found `seg(point(0.1,2),point(3,4))' (a compound)

```

The error message is not super useful but at least it throws as it should.

I guess what you _cannot_ do is define say a “stack” which would be something like (made up code):

```prolog
stack(empty).
stack(Value, stack).

```

This stack is de facto a list but you still can’t define other recursive structures like for example a binary tree.

---

<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:** [November 17, 2023, 11:14am UTC](https://swi-prolog.discourse.group/t/ann-swi-prolog-9-1-19/6978/7 "2023-11-17T11:14:16Z")

</div>

> [@Boris](#):
>
> Note that `9.1.18-70-g955571d43` up there.
> 
> Not sure what happened.

Forgot to pull the git tag ☹ Thanks for noting. I should fix this in the release building script. It will remain like this for this version as security audits (and the server itself) doesn’t like executables with the same name to exists with different content.

> [@Boris](#):
>
> The error message is not super useful but at least it throws as it should.

Yes. Could be more human friendly ☹

> [@Boris](#):
>
> you still can’t define other recursive structures like for example a binary tree.

Indeed. To do that, you need something that allows referring to the type you are defining. As is, you can define this using the error:has\_type/2 multifile predicate. I consider this a bit too ad-hoc to be considered a proper type language though. There are better type definition languages for Prolog around 🙂

---

<div class="post-metadata">

**Author:** ![kwon-young](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/kwon-young/32/4841_2.png) [@kwon-young](https://swi-prolog.discourse.group/u/kwon-young)\
**Post date:** [November 17, 2023, 12:14pm UTC](https://swi-prolog.discourse.group/t/ann-swi-prolog-9-1-19/6978/8 "2023-11-17T12:14:02Z")

</div>

> [@jan](#):
>
> There are better type definition languages for Prolog around 🙂

Do you have an example in mind ?  
Things like lambda prolog ?  
What would be the alternative of using the prolog database ?

---

<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:** [November 17, 2023, 12:53pm UTC](https://swi-prolog.discourse.group/t/ann-swi-prolog-9-1-19/6978/9 "2023-11-17T12:53:07Z")

</div>

> [@kwon-young](#):
>
> Do you have an example in mind ?

Not particularly. There are type definitions in Ciao, the type library by Tom Schrijvers, Mercury and as you say lambda Prolog (I’m not familiar with its details). If we want to take typing to the next level, we need to define our goals and see what to choose or reuse.

Typing dynamic languages is a hard topic. Recent progress in other dynamic languages give some hope. But, Prolog comes with its own complications. First of all, rather satisfying some type or not, we have terms that (1) satisfy a type, (2) are _compatible_ with a type and (3) are incompatible with a type. A term is compatible with a type if it is non-ground and can still get a shape that satisfies the type (thus, a variable is compatible with all types). So, _instantiation_ (or modes) cannot be ignored. Second, a conjunction may refine types down the road, e.g., `bla(X), atom(X), atom_concat(X, aap, Y)` is type safe, even if `bla/1` may succeed with non-atoms. What we would like here is to prove that `bla/1` never succeeds with an atom, in which case we can warn the user this never succeeds or always succeeds with an atom, in which case we can tell the user that the atom/1 call is redundant. Probably work on dynamically typed languages do this correctly as such languages can implement control based on dynamic type tests.

My take on this is that we should provide an easy to use type, mode and determinism language. That can first be used as basis for documentation and can later be used for dynamic type checking and static type analysis. Ciao is beyond doubt most advanced here. I have the impression it could/should be done simpler, but maybe I’m wrong. It is quite a while ago I looked at the Ciao assertion language. There is a tradeoff between simplicity and preciseness here. I lean towards simplicity, accepting that we cannot proof type (in)correctness of more code.

---

<div class="post-metadata">

**Author:** ![anon419083](https://avatars.discourse-cdn.com/v4/letter/a/53a042/32.png) [@anon419083](https://swi-prolog.discourse.group/u/anon419083)\
**Post date:** [November 17, 2023, 4:14pm UTC](https://swi-prolog.discourse.group/t/ann-swi-prolog-9-1-19/6978/10 "2023-11-17T16:14:43Z")

</div>

```prolog
% python
Python 3.11.6 (main, Oct 17 2023, 14:36:46) [Clang 15.0.0 (clang-1500.0.40.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import janus_swi as janus
ERROR: Exported procedure janus:py_setattr/3 is not defined
>>> 

```

Now I get this error message I didn’t get before.

Or maybe it’s my fault and I have to update something…🤔

---

<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:** [November 17, 2023, 4:35pm UTC](https://swi-prolog.discourse.group/t/ann-swi-prolog-9-1-19/6978/11 "2023-11-17T16:35:22Z")

</div>

> [@anon419083](#):
>
> Or maybe it’s my fault and I have to update something…🤔

You have to re-build the Python module using pip. If you got the whole thing setup, go to packages/swipy in the source tree and run

```
 pip install .

```

---

<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:** [November 17, 2023, 5:15pm UTC](https://swi-prolog.discourse.group/t/ann-swi-prolog-9-1-19/6978/12 "2023-11-17T17:15:40Z")

</div>

> [@anon419083](#):
>
> Or maybe it’s my fault and I have to update something…🤔

It is to me still an open question what to do here. Should the build process (by default) check for `pip` and try to build the Python package? Is something like that considered good practice? One of the issue is that `pip install .` actually installs. Possibly better is to do `pip wheel .` to just build the package. How do I then install this wheel? It is also problematic that the pip build creates files in the source directory. Is there a way around that?

---

<div class="post-metadata">

**Author:** ![anon419083](https://avatars.discourse-cdn.com/v4/letter/a/53a042/32.png) [@anon419083](https://swi-prolog.discourse.group/u/anon419083)\
**Post date:** [November 17, 2023, 5:57pm UTC](https://swi-prolog.discourse.group/t/ann-swi-prolog-9-1-19/6978/13 "2023-11-17T17:57:38Z")

</div>

You’re not asking me, I guess…you’re asking the community. The matter is extremely technical and it’s far above my head and my competence so to say. Nonetheless I reinstalled and now I don’t get the error message anymore

---

<div class="post-metadata">

**Author:** ![kwon-young](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/kwon-young/32/4841_2.png) [@kwon-young](https://swi-prolog.discourse.group/u/kwon-young)\
**Post date:** [November 18, 2023, 2:11am UTC](https://swi-prolog.discourse.group/t/ann-swi-prolog-9-1-19/6978/14 "2023-11-18T02:11:43Z")

</div>

> [@Boris](#):
>
> This stack is de facto a list but you still can’t define other recursive structures like for example a binary tree.

Just for curiosity, how is the `list` type defined in swi prolog ?

---

<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:** [November 18, 2023, 12:19pm UTC](https://swi-prolog.discourse.group/t/ann-swi-prolog-9-1-19/6978/15 "2023-11-18T12:19:05Z")

</div>

> [@kwon-young](#):
>
> Just for curiosity, how is the `list` type defined in swi prolog ?

See library(error). “types” are defined as rules for has\_type/2. The list type is simply defined by the built-in predicate is\_list/1. There is much more to say about types than SWI-Prolog does …
