projog

6.2. Adding Extra Functionality to Prolog Using Java

Projog provides a mechanism for "plugging in" or "injecting" implementations of PredicateFactory at runtime. This mechanism provides an easy way to configure and extend the functionality of Projog - including adding functionality not possible to define in pure Prolog syntax.

Rather than directly implementing PredicateFactory it is recommended to extend either AbstractSingleResultPredicate or AbstractPredicateFactory.

Example usage

If your project is configured using Maven then you can add a dependency on Projog by adding the following to your project's pom.xml:

<dependency>
   <groupId>org.projog</groupId>
   <artifactId>projog-core</artifactId>
   <version>0.10.0</version>
</dependency>

Contents of com/example/SingleResultPredicateExample.java:

package com.example;

import static org.projog.core.term.TermUtils.getAtomName;

import org.projog.core.predicate.AbstractSingleResultPredicate;
import org.projog.core.term.Atom;
import org.projog.core.term.Term;

/**
 * uppercase(X,Y) - succeeds if the atom represented by Y is equal to an upper case version of the atom
 * represented by X.
 *
 * @see RetryablePredicateExample
 */
public class SingleResultPredicateExample extends AbstractSingleResultPredicate {
   @Override
   public boolean evaluate(Term term1, Term term2) {
      Atom upperCaseTerm1 = new Atom(getAtomName(term1).toUpperCase());
      return term2.unify(upperCaseTerm1);
   }
}

Example of integrating org.projog.example.SingleResultPredicateExample into Projog:

?- pj_add_predicate(uppercase/2, 'org.projog.example.SingleResultPredicateExample').

yes

?- uppercase('The quick brown fox jumps over the lazy dog', X).
X = THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG

yes

?- uppercase('The quick brown fox jumps over the lazy dog', 'THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG').

yes

?- uppercase('The quick brown fox jumps over the lazy dog', 'THE QUICK BROWN BOX JUMPS OVER THE LAZY FOG').

no

Contents of com/example/RetryablePredicateExample.java:

package com.example;

import org.projog.core.predicate.AbstractPredicateFactory;
import org.projog.core.predicate.Predicate;
import org.projog.core.term.Atom;
import org.projog.core.term.Term;
import org.projog.core.term.TermUtils;

/**
 * split(X,Y) - compares Y to each of the comma-separated values represented by X.
 *
 * @see SingleResultPredicateExample
 */
public class RetryablePredicateExample extends AbstractPredicateFactory {
   @Override
   public Predicate getPredicate(Term arg1, Term arg2) {
      String csv = TermUtils.getAtomName(arg1);
      String[] split = csv.split(",");
      return new RetryablePredicate(split, arg2);
   }

   private static class RetryablePredicate implements Predicate {
      private final String[] split;
      private final Term target;
      private int idx;

      RetryablePredicate(String[] split, Term target) {
         this.split = split;
         this.target = target;
      }

      @Override
      public boolean evaluate() {
         while (idx < split.length) {
            target.backtrack();
            String next = split[idx++];
            if (target.unify(new Atom(next))) {
               return true;
            }
         }

         return false;
      }

      @Override
      public boolean couldReevaluationSucceed() {
         return idx < split.length;
      }
   }
}

Example of integrating com.example.RetryablePredicateExample into Projog:

?- pj_add_predicate(split/2, 'com.example.RetryablePredicateExample').

yes

?- split('dog,cat,bird', X).
X = dog

yes ;

X = cat

yes ;

X = bird

yes ;

no

See Also