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

488 views Asked by At

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:

  • nonvar(X)
  • ground(X)
  • ?=(X, Y)
  • (Cond1, Cond2)
  • (Cond2; Cond2)

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)).
1

There are 1 answers

1
Jan Wielemaker On BEST ANSWER

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.