12.4.6 Unifying data
All Application Manual Name SummaryHelp

  • Documentation
    • Reference manual
      • Foreign Language Interface
        • The Foreign Include File
          • Unifying data
            • PL_unify()
            • PL_unify_atom()
            • PL_unify_bool()
            • PL_unify_chars()
            • PL_unify_atom_chars()
            • PL_unify_list_chars()
            • PL_unify_string_chars()
            • PL_unify_integer()
            • PL_unify_int64()
            • PL_unify_uint64()
            • PL_unify_float()
            • PL_unify_pointer()
            • PL_unify_functor()
            • PL_unify_compound()
            • PL_unify_list()
            • PL_unify_nil()
            • PL_unify_arg()
            • PL_unify_term()
            • PL_chars_to_term()
            • PL_wchars_to_term()
            • PL_quote()
            • PL_for_dict()
    • Packages
Availability:C-language interface function
bool PL_unify(term_t ?t1, term_t ?t2)
Unify two Prolog terms and return TRUE on success. PL_unify() does not evaluate attributed variables (see section 8.1), it merely schedules the goals associated with the attributes to be executed after the foreign predicate succeeds.222Goal associated with attributes may be non-deterministic, which we cannot handle from a callback. A callback could also result in deeply nested mutual recursion between C and Prolog and eventually trigger a C stack overflow.

Care is needed if PL_unify() returns FALSE and the foreign function does not immediately return to Prolog with FALSE. Unification may perform multiple changes to either t1 or t2. A failing unification may have created bindings before failure is detected. Already created bindings are not undone. For example, calling PL_unify() on a(X, a) and a(c,b) binds X to c and fails when trying to unify a to b. If control remains in C or if we want to return success to Prolog, we must undo such bindings. In addition, PL_unify() may have failed on an exception, typically a resource (stack) overflow. This can be tested using PL_exception(), passing 0 (zero) for the query-id argument. Foreign functions that encounter an exception must return FALSE to Prolog as soon as possible or call PL_clear_exception() if they wish to ignore the exception. Note that there can only be an exception if PL_unify() returned FALSE.

In some scenarios we need to undo partial unifications. Suppose we have a database that contains Prolog terms and we run a query over this database. We must succeed on the first successful unification. If a unification is not successful, we must stop if there is an exception or undo the partial unification and try again. Suppose our database contains f(a,1) and f(b,2) and our query is f(A,2). This should succeed with A = b, but the first unification binds A to a before failing to unify 1 with 2.

static foreign_t
find_in_db(term_t target)
{ fid_t fid = PL_open_foreign_frame();
  term_t candidate = PL_new_term_ref();

  while(get_from_my_database(candidate))
  { if ( PL_unify(candidate, target) ) /* found */
    { PL_close_foreign_frame(fid);
      return TRUE;
    } else if ( PL_exception(0) )      /* error */
    { PL_close_foreign_frame(fid);
      return FALSE;
    }

    PL_rewind_foreign_frame(fid);      /* try next */
  }
  PL_close_foreign_frame(fid);         /* not found */
  return FALSE;
}

This code is only needed if the foreign predicate does not return immediately to Prolog when PL_unify() fails - there is an implicit frame around the entire predicate, and returning FALSE undoes all bindings when that frame is closed.