prologprolog-coroutining

SWI-Prolog: How to use my own predicate as a condition in when/2


I am trying to implement a Prolog program that can interact with java. To do this I use JPL as the Prolog/Java interface.

I am looking for a mechanism that allows me to execute actions automatically when the conditions become true.

The conditions are also represented by predicates. I have tried to use the predefined predicate "when/2", the problem is that as specified in the documentation here, the condition must be one of these:

The last two conditions seem the ones I should use, but I could not make them work.

What do I need to change to make make my own conditions ?

Please, consider J as a local Prolog variable here.

:- use_module(library(jpl)).
:- use_module(library(when)).


should_engage(J) :-
  jpl_get(J, 'shouldEngage', V),
  V==true,
  jpl_get(J, 'players', P),
  jpl_call(P, 'canSeeEnemies', [], R),
  R==true,
  jpl_get(J, 'weaponry', W),
  jpl_call(W, 'hasLoadedWeapon', [], R),
  R==true.


call_java(J) :-
  jpl_call(J, 'stateEngage', [], R).


when(should_engage(X), call_java(X)).

Solution

  • When/1 is part of the coroutining infrastructure that triggers actions on variable instantiation. It uses attributed variables in the background. So, if your J is normally a variable that can get bound at some time you can do

       ...,
       when(nonvar(X), propagate(X)).
    
    propagate(X) :-
        should_engage(X),
        call_java(X).
    

    Or

    propagate(X) :-
        (   should_engage(X)
        ->  call_java(X)
        ;   true
        ).
    

    The first version will cause the instantiation of X to fail if should_engage/1 fails. The latter version not.

    If it is not the binding of a variable that may make should_engage/1 true you'll need to find some other trigger or possibly have a thread that monitors the environment at intervals and propagates.

    Note that calling non-logical constructs from when/1 typically makes little sense because Prolog's computation may backtrack, unbinding X and rebinding it again to the same or a different value and thus your propagation may be called many times with different or the same value.