12.4.4.5 Reading a list
The functions from this section are intended to read a Prolog list from C. Suppose we expect a list of atoms; the code below will print the atoms, each on a line. Please note the following:
- We need a
term_t
term reference for the elements (head). This reference is reused for each element. - We walk over the list using PL_get_list_ex()
which overwrites the list
term_t
. As it is not allowed to overwrite theterm_t
passed in as arguments to a predicate, we must copy the argumentterm_t
. - SWI-Prolog atoms are Unicode objects. The PL_get_chars()
returns a
char*
. We want it to convert atoms, return the result as a multibyte string (REP_UTF8
may also be used) and finally we want an exception on type, instantiation or representation errors (if the system's default encoding cannot represent some characters of the Unicode atom). This may create temporary copies of the atom text - PL_STRINGS_MARK() ... PL_STRINGS_RELEASE() handles that. - The *_ex() API functions are functionally the same as the
ones without the
_ex
suffix, but they raise type, domain, or instantiation errors when the input is invalid; whereas the plain version may only raise resource exceptions if the request cannot be fullfilled due to resource exhaustion. - PL_get_nil_ex() is designed to propagate an already raised exception.
foreign_t pl_write_atoms(term_t l) { term_t head = PL_new_term_ref(); /* the elements */ term_t tail = PL_copy_term_ref(l); /* copy (we modify tail) */ int rc = TRUE; while( rc && PL_get_list_ex(tail, head, tail) ) { PL_STRINGS_MARK(); char *s; if (rc=PL_get_chars(head, &s, CVT_ATOM|REP_MB|CVT_EXCEPTION)) ) rc = Sfprintf(Scurrent_output, "%s\n", s); PL_STRINGS_RELEASE(); } return rc && PL_get_nil_ex(tail); /* test end for [] */ }
Note that as of version 7, lists have a new representation unless the option --traditional is used. see section 5.1.
- int PL_get_list(term_t +l, term_t -h, term_t -t)
- If l is a list and not the empty list, assign a term reference to the head to h and to the tail to t.
- int PL_get_head(term_t +l, term_t -h)
- If l is a list and not the empty list, assign a term reference to the head to h.
- int PL_get_tail(term_t +l, term_t -t)
- If l is a list and not the empty list, assign a term reference to the tail to t.
- int PL_get_nil(term_t +l)
- Succeeds if l represents the list termination constant.
- int PL_skip_list(term_t +list, term_t -tail, size_t *len)
- This is a multi-purpose function to deal with lists. It allows for
finding the length of a list, checking whether something is a list, etc.
The reference tail is set to point to the end of the list,
len is filled with the number of list-cells skipped, and the
return value indicates the status of the list:
- PL_LIST
- The list is a‘proper’list: one that ends in the list terminator constant and tail is filled with the terminator constant.
- PL_PARTIAL_LIST
- The list is a‘partial’list: one that ends in a variable and tail is a reference to this variable.
- PL_CYCLIC_TERM
- The list is cyclic (e.g. X = [a|X]). tail points to an arbitrary cell of the list and len is at most twice the cycle length of the list.
- PL_NOT_A_LIST
- The term list is not a list at all. tail is bound to the non-list term and len is set to the number of list-cells skipped.
It is allowed to pass 0 for tail and
NULL
for len.