2 A C++ interface to SWI-Prolog (Version 2)
AllApplicationManualNameSummaryHelp

  • Documentation
    • Reference manual
    • Packages
      • A C++ interface to SWI-Prolog
        • A C++ interface to SWI-Prolog (Version 2)
          • Summary of changes between Versions 1 and 2
          • Introduction (version 2)
          • The life of a PREDICATE (version 2)
          • Overview (version 2)
          • Examples (version 2)
          • Rational for changes from version 1 (version 2)
          • Porting from version 1 to version 2
          • The class PlFail (version 2)
            • PlCheck() convenience function
          • The class PlTerm (version 2)
          • The class PlTermv (version 2)
          • The class PlAtom - Supporting Prolog constants (version 2)
          • Unification and foreign frames (version 2)
          • The class PlRegister (version 2)
          • The class PlQuery (version 2)
          • The PREDICATE and PREDICATE_NONDET macros (version 2)
          • Exceptions (version 2)
          • Embedded applications (version 2)
          • Considerations (version 2)
          • Conclusions (version 2)

2.8 The class PlFail (version 2)

The PlFail class is used for short-circuiting a function when failure or an exception occurs and any errors will be handled in the code generated by the PREDICATE() macro. See also section 2.18.2).

For example, this code:

PREDICATE(unify_zero, 1)
{ if ( !PL_unify_integer(A1.C_, 0) )
    return false;
  return true;
}

can instead be written this way:

void
PREDICATE(unify_zero, 1)
{ if ( !PL_unify_integer(A1.C_, 0) )
    throw PlFail();
  return true;
}

or:

PREDICATE(unify_zero, 1)
{ PlCheck(PL_unify_integer(t.C_, 0));
  return true;
}

or:

PREDICATE(unify_zero, 1)
{ PlCheck(A1.unify_integer(0));
  return true;
}

or:

PREDICATE(unify_zero, 1)
{ return A1.unify_integer(0);
}

Using throw PlFail() in performance-critical code can cause a signficant slowdown. A simple benchmark showed a 15x to 20x slowdown using throw PlFail() compared to return false (comparing the first code sample above with the second and third samples; the speed difference seems to have been because in the second sample, the compiler did a better job of inlining). However, for most code, this difference will be barely noticeable.

There was no significant performance difference between the C++ version and this C version:

static foreign_t
unify_zero(term_t a1)
{ return PL_unify_integer(a1, 0);
}

2.8.1 PlCheck() convenience function

In general, wherever there is a method that wraps a C "PL_" function, PlCheck() can be used to return failure to Prolog from the "PL_" function.

The code for PlCheck() is very simple - it checks the return code and throws PlFail if the return code isn't "true". If the return code is from a Prolog function (that is, a function starting with "PL_"), the return code can be "false" either because of failure or because an exception happened. If the cause is an exception, then the only sensible thing is to return to Prolog immediately; throwing PlFail will do this. See also section 2.18.2.