• Places
    • Home
    • Graphs
    • Prefixes
  • Admin
    • Users
    • Settings
    • Plugins
    • Statistics
  • Repository
    • Load local file
    • Load from HTTP
    • Load from library
    • Remove triples
    • Clear repository
  • Query
    • YASGUI SPARQL Editor
    • Simple Form
  • Help
    • Documentation
    • Tutorial
    • Roadmap
    • HTTP Services
  • Login

SWI-Prolog Python interface
All Application Manual Name SummaryHelp

  • Documentation
    • Reference manual
    • Packages
      • SWI-Prolog Python interface
        • Introduction
        • Data conversion
        • Janus by example
        • library(janus): Call Python from Prolog
        • Calling Prolog from Python
        • Janus and threads
        • Janus as a Python package
        • Prolog and Python
        • Janus performance evaluation
        • Python or C/C++ for accessing resources?
        • Janus platforms notes
        • Compatibility to the XSB Janus implementation
        • Status of Janus

2 Data conversion

The bi-directional conversion between Prolog and Python terms is summarized in the table below. For compatibility with Prolog implementations without native dicts we support converting the {k1:v1, k2:v2, ...} to dicts. Note that {k1:v1, k2:v2} is syntactic sugar for {}(','(:(k1,v1), :(k2,v2))). We allow for embedding this in a py(Term) such that, with py defined as prefix operator, py{k1:v1, k2:v2} is both valid syntax as SWI-Prolog dict as as ISO Prolog compliant term and both are translated into the same Python dict. Note that {} translates to a Python string, while py({}) translates into an empty Python dict.

By default we translate Python strings into Prolog atoms. Given we support strings, this is somewhat dubious. There are two reasons for this choice. One is the pragmatic reason that Python uses strings both for identifiers and arbitrary text. Ideally we'd have the first translated to Prolog atoms and the latter to Prolog strings, but, because we do not know which strings act as identifier and which as just text, this is not possible. The second is to improve compatibility with Prolog systems that do not support strings. Note that py_call/3 and py_iter/3 provide the option py_string_as(string) to obtain a string if this is desirable.

Prolog Python Notes
Variable⟶ -(instantiation error)
Integer⟺ intSupports big integers
Rational⟺ fractions.Fraction()
Float⟺ float
@(none)⟺ None
@(true)⟺ True
@(false)⟺ False
Atom⟵ enum.Enum() Name of Enum instance
Atom⟷ StringExcept the above reserved three atoms
String⟶ String
#(Term)⟶ Stringstringify using write_canonical/1 if not atomic
prolog(Term)⟶ janus.Term() Represent any Prolog term
Term⟵ janus.Term()
List⟶ List
List⟵ Sequence
List⟵ IteratorNote that a Generator is an Iterator
py_set(List)⟺ Set
-(a,b, ... )⟺ (a,b, ... )Python Tuples
Dict⟺ Dict
{k:v, ...} ⟹ DictCompatibility (see above)
py({k:v, ...})⟹ DictCompatibility (see above)
eval(Term)⟹ ObjectEvaluate Term as first argument of py_call/2
py_obj blob⟺ ObjectUsed for any Python object not above
Compound⟶ -for any term not above (type error)

The interface supports unbounded integers and rational numbers. Large integers (> 64 bits) are converted using a hexadecimal string as intermediate. SWI-Prolog rational numbers are mapped to the Python class fractions:Fraction. Currently the mapping rational numbers uses an intermediate decimal string and is therefore relatively slow. Mapping from Python to Prolog relies on the ((_)_str__)() method of the instance returning +/-<num>/<den> where <num> and <den> are decimal numbers.

The conversion #(Term) allows passing anything as a Python string. If Term is an atom or string, this is the same as passing the atom or string. Any other Prolog term is converted as defined by write_canonical/1. The conversion prolog(Term) creates an instance of janus.Term(). This class encapsulates a copy of an arbitrary Prolog term. The SWI-Prolog implementation uses the PL_record() and PL_recorded() functions to store and retrieve the term. Internally, janus.Term() is used to represent Prolog exeptions that are raised during the execution of janus.once() or janus.Query().

Python Tuples are array-like objects and thus map best to a Prolog compound term. There are two problems with this. One is that few systems support compound terms with arity zero, e.g., f and many systems have a limit on the arity of compound terms. Using Prolog comma lists, e.g., (a,b,c) does not implement array semantics, cannot represent empty tuples and cannot disambiguate tuples with one element from the element itself. We settled with compound terms using the - as functor to make the common binary tuple map to a Prolog pair.

ClioPatria (version V3.1.1-48-gf653ce4)