[Up] [Contents] [Index] [Summary]

5.6.5 Unifying data

The functions of this sections unify terms with other terms or translated C-data structures. Except for PL_unify(), the functions of this section are specific to SWI-Prolog. They have been introduced to make translation of old code easier, but also because they provide for a faster mechanism for returning data to Prolog that requires less term-references. Consider the case where we want a foreign function to return the host name of the machine Prolog is running on. Using the PL_get_*() and PL_put_*() functions, the code becomes:

foreign_t pl_hostname(term_t name) { char buf[100]; if ( gethostname(buf, sizeof(buf)) ) { term_t tmp = PL_new_term_ref(); PL_put_atom_chars(tmp, buf); return PL_unify(name, buf); } PL_fail; }

Using PL_unify_atom_chars(), this becomes:

foreign_t pl_hostname(term_t name) { char buf[100]; if ( gethostname(buf, sizeof(buf)) ) return PL_unify_atom_chars(name, buf); PL_fail; }

int PL_unify(term_t ?t1, term_t ?t2)
Unify two Prolog terms and return non-zero on success.

int PL_unify_atom(term_t ?t, atom_t a)
Unify t with the atom a and return non-zero on success.

int PL_unify_atom_chars(term_t ?t, const char *chars)
Unify t with an atom created from chars and return non-zero on success.

int PL_unify_list_chars(term_t ?t, const char *chars)
Unify t with a list of ASCII characters constructed from chars.

int PL_unify_string_chars(term_t ?t, const char *chars)
Unify t with a Prolog string object created from chars.

int PL_unify_integer(term_t ?t, long n)
Unify t with a Prolog integer from n.

int PL_unify_float(term_t ?t, double f)
Unify t with a Prolog float from f.

int PL_unify_pointer(term_t ?t, void *ptr)
Unify t with a Prolog integer describing the pointer. See also PL_put_pointer() and PL_get_pointer().

int PL_unify_functor(term_t ?t, functor_t f)
If t is a compound term with the given functor, just succeed. If it is unbound, create a term and bind the variable, else fails. Not that this function does not create a term if the argument is already instantiated.

int PL_unify_list(term_t ?l, term_t -h, term_t -t)
Unify l with a list-cell (./2). If successful, write a reference to the head of the list to h and a reference to the tail of the list in t. This reference may be used for subsequent calls to this function. Suppose we want to return a list of atoms from a char **. We could use the example described by PL_put_list(), followed by a call to PL_unify(), or we can use the code below. If the predicate argument is unbound, the difference is minimal (the code based on PL_put_list() is probably slightly faster). If the argument is bound, the code below may fail before reaching the end of the word-list, but even if the unification succeeds, this code avoids a duplicate (garbage) list and a deep unification.

foreign_t pl_get_environ(term_t env) { term_t l = PL_copy_term_ref(env); term_t a = PL_new_term_ref(); extern char **environ; while(*environ) { if ( !PL_unify_list(l, a, l) || !PL_unify_atom_chars(a, *environ) ) PL_fail; } return PL_unify_nil(l); }

int PL_unify_nil(term_t ?l)
Unify l with the atom .

int PL_unify_arg(int index, term_t ?t, term_t ?a)
Unifies the index-th argument (1-based) of t with a.

int PL_unify_term(term_t ?t, ...)
Unify t with a (normally) compound term. The remaining arguments is a sequence of a type identifier, followed by the required arguments. This predicate is an extension to the Quintus and SICStus foreign interface from which the SWI-Prolog foreign interface has been derived, but has proved to be a powerful and comfortable way to create compound terms from C. Due to the vararg packing/unpacking and the required type-switching this interface is slightly slower than using the primitives. Please note that some bad C-compilers have fairly low limits on the number of arguments that may be passed to a function.

The type identifiers are:

PL_VARIABLE none
No op. Used in arguments of PL_FUNCTOR.

PL_ATOM atom_t
Unify the argument with an atom, as in PL_unify_atom().

PL_INTEGER long
Unify the argument with an integer, as in PL_unify_integer().

PL_FLOAT double
Unify the argument with a float, as in PL_unify_float(). Note that, as the argument is passed using the C vararg conventions, a float must be casted to a double explicitly.

PL_STRING const char *
Unify the argument with a string object, as in PL_unify_string_chars().

PL_TERM term_t
Unify a subterm. Note this may the return value of a PL_new_term_ref() call to get access to a variable.

PL_CHARS const char *
Unify the argument with an atom, constructed from the C char *, as in PL_unify_atom_chars().

PL_FUNCTOR functor_t, ...
Unify the argument with a compound term. This specification should be followed by exactly as many specifications as the number of arguments of the compound term.

PL_LIST int length, ...
Create a list of the indicated length. The following arguments contain the elements of the list.

For example, to unify an argument with the term language(dutch), the following skeleton may be used:

static functor_t FUNCTOR_language1; static void init_constants() { FUNCTOR_language1 = PL_new_functor(PL_new_atom("language"), 1); } foreign_t pl_get_lang(term_t r) { return PL_unify_term(r, PL_FUNCTOR, FUNCTOR_language1, PL_CHARS, "dutch"); } install_t install() { PL_register_foreign("get_lang", 1, pl_get_lang, 0); init_constants(); }