2.14 The class PlQuery (version 2)
AllApplicationManualNameSummaryHelp

  • Documentation
    • Reference manual
    • Packages
      • A C++ interface to SWI-Prolog
        • A C++ interface to SWI-Prolog (Version 2)
          • The class PlQuery (version 2)
            • The class PlFrame (version 2)

2.14.1 The class PlFrame (version 2)

The class PlFrame provides an interface to discard unused term-references as well as rewinding unifications (data-backtracking). Reclaiming unused term-references is automatically performed after a call to a C++-defined predicate has finished and returns control to Prolog. In this scenario PlFrame is rarely of any use. This class comes into play if the toplevel program is defined in C++ and calls Prolog multiple times. Setting up arguments to a query requires term-references and using PlFrame is the only way to reclaim them.

PlFrame :: PlFrame()
Creating an instance of this class marks all term-references created afterwards to be valid only in the scope of this instance.
~ PlFrame()
Reclaims all term-references created after constructing the instance.
void PlFrame::rewind()
Discards all term-references and global-stack data created as well as undoing all unifications after the instance was created.

A typical use for PlFrame is the definition of C++ functions that call Prolog and may be called repeatedly from C++. Consider the definition of assertWord(), adding a fact to word/1:

void
assertWord(const char *word)
{ PlFrame fr;
  PlTermv av(1);

  av[0] = PlCompound("word", PlTermv(word));
  PlQuery q("assert", av);
  PlCheck(q.next_solution());
}

This example shows the most sensible use of PlFrame if it is used in the context of a foreign predicate. The predicate's thruth-value is the same as for the Prolog unification (=/2), but has no side effects. In Prolog one would use double negation to achieve this.

PREDICATE(can_unify, 2)
{ PlFrame fr;

  int rval = (A1=A2);
  fr.rewind();
  return rval;
}

PlRewindOnFail(f) is a convenience function that does a frame rewind if unification fails. Here is an example, where name_to_term contains a map from names to terms (which are made global by using the PL_record() function):

static const std::map<const std::string, record_t> name_to_term =
    { {"a", PlTerm(...).record()}, ...};

bool lookup_term(const std::string name, PlTerm result)
{ const auto it = name_to_term.find(name);
  if ( it == name_to_term.cend() )
    return false;

  PlTerm t = PlTerm_recorded(it->second);
  return PlRewindOnFail([result,t]() -> bool { return result.unify_term(t); });
}