• Places
    • Home
    • Graphs
    • Prefixes
  • Admin
    • Users
    • Settings
    • Plugins
    • Statistics
  • Repository
    • Load local file
    • Load from HTTP
    • Load from library
    • Remove triples
    • Clear repository
  • Query
    • YASGUI SPARQL Editor
    • Simple Form
  • Help
    • Documentation
    • Tutorial
    • Roadmap
    • HTTP Services
  • Login

2.17 The PREDICATE and PREDICATE_NONDET macros (version 2)
All Application Manual Name SummaryHelp

  • Documentation
    • Reference manual
    • Packages
      • A C++ interface to SWI-Prolog
        • A C++ interface to SWI-Prolog (Version 2)
          • The PREDICATE and PREDICATE_NONDET macros (version 2)
            • Variations of the PREDICATE macro (version 2)
            • Non-deterministic predicates (version 2)
            • Controlling the Prolog destination module (version 2)

2.17.2 Non-deterministic predicates (version 2)

Non-deterministic predicates are defined using PREDICATE_NONDET(plname, cname, arity) or NAMED_PREDICATE_NONDET(plname, cname, arity).

A non-deterministic predicate returns a "context", which is passed to a subsequent retry. Typically, this context is allocated on the first call to the predicate and freed when the predicate either fails or does its last successful return (the context is nullptr on the first call). To simplify this, a template helper function PlControl::context_unique_ptr<ContextType>() provides a "smart pointer" that frees the context on normal return or an exception; when used with PL_retry_address(), the context's std:unique_ptr<ContextType>::release() is used to pass the context to Prolog for the next retry, and to prevent the context from being freed. If the predicate is called with PL_PRUNE, the normal return true will implicitly free the context.

The skeleton for a typical non-deterministic predicate is:

struct PredContext { ... }; // The "context" for retries

PREDICATE_NONDET(pred, <arity>)
{
  auto ctxt = handle.context_unique_ptr<PredContext>();
  switch( PL_foreign_control(handle) )
  { case PL_FIRST_CALL:
      ctxt.reset(new PredContext(...));
      ...
      break;
    case PL_REDO:
      break;
    case PL_PRUNED:
      return true;
  }

  if ( ... )
    return false; // Failure (and no more solutions)
    // or throw PlFail();

  if ( ... )
    return true;  // Success (and no more solutions)

  ...

  PL_retry_address(ctxt.release()); // Succeed with a choice point
}

ClioPatria (version V3.1.1-48-gf653ce4)