Terms
Updated 09 Oct 2002
Upper levels:
Amzi Python Interface 0.2...
4. Manual

 4.3. Terms

 [ Prev - Up - Next ] 

Prolog terms are wrapped in the Python class AmziTerm, which is the output of the various query methods, and can also be built and manipulated directly from Python.


 Index


 Building

  [ Top ] 

Terms are returned by the query methods discussed in 'Calling Prolog from Python', and can also be assembled by the engine methods .strTerm() and pyTerm:

.strTerm(<string>)
Produces the term designated by the string, just as would the StrTerm lsapi methods. This term can then be fed to a calling method:
query = eng.strTerm('parent(X,avery)')
for answer in eng.calls(query):
    print answer
.pyTerm(<pyobject>)
Produces a term from a python object, convertinh types as follows:

PythonProlog
string string
integer integer
float float
list list
None unbound VAR
1-member tuple atom
>1-member tuple functor-arg structure
AmziTerm Amzi TERM
other ADDR

For example:

query = eng.pyTerm(('parent',None,(avery,)))
Non-Pythonistas note the peculiar (,) notation for 1-member tuples. These conversions are also supplied when a tuple is submitted to one of the query calling engine methods.

Significant Limitations: Several important types are missing (e.g. Unicode strigs). There is no direct way to express that two positions are to be filled by the same free variable, although the effect can be achieved with the unification methods presented below.

Two term-building methods seem to be necessary because sometimes we might want to represent a Prolog term with a string, other times to assemble ones from various objects that are around, and a single term-building method couldn't tell whether a string was representing a Prolog string, or a term.


 Conversion to Python

  [ Top ] 

AmziTerms print out as a string, and numerical types can be coerced to their corresponding Python type, e.g.

term = strTerm(2.3)
f = float(term)
will set f to a regular Python float. At the moment there are no automatic cross-type coercions other than to string, if you want to convert term to a Python integer, convert it to float first:
i = int(float(term))
Maybe later for this one.


 Accessing Members

  [ Top ] 

AmziTerm members can be accessed by indexes, 0 for the functor, etc., as illustrated in 'Basic Ideas and Use'

Tuples of their members can also be gotten by slicing. So after executing:

term = eng.strTerm('gave(john,mary,book)')
term[2:4] will yield a 2-tuple whose members are AmziTerms wrapping the Prolog atoms 'book' and 'mary'. (termtest.py in the Test folder illustrates some of this).


 Unification

  [ Top ] 

Two terms can be unified with a term-method unify:

term1.unify(term2)
The argument term can also be constructed from Python objects:
term1.unify(('likes',None,('lizards',))
When unification succeeds, the AmziTerm the methodis applied to is returned as value, otherwise None.

But to unify in parts of term, it's better to use item and slice-assignment"

term1[2] = ('lizards',)
term2[1:3] = ('bill',),('snakes',)
Since terms have fixed arity, 'wrapped indexes' such as [-1] for the last element, are not supported.

A wart is that in Python, assignment is meant to succeed, unless there's a serious error, so there's no built-in way to signal a benign failure, as when the terms just aren't unifiable. So when this happens with the item/slice methods, the esception AmziProlog.FailedUni is thrown, which can be caught with the try/except construction. (example in tests.py).

Some examples are in test.py in the Tests folder.

It might be cool to be able to do unification by assignment, e.g.:

term1 = term2
would unify the two terms, but I can't figure out a way to make this happen (but I think it might be doable in C++). Perhaps it would be seen as a perversion of Python semantics, since the assignment would affect the content of term2 as well as term1. If this is a perversion, slice and item assignment as above are partakers.



 [ Prev - Top - Next ]