Navigation  without Java Scripts

Predicate Values

Visual Prolog supports a notion of predicate values.  Predicate values are the predicates that can be treated as values in the sense that they can be:

passed as parameters and returned from functions, 

stored in facts,

held in variables,

compared for identity.

Like plain predicates they can, of course, also be invoked on arguments. Predicate values do however differ from most other Visual Prolog values in the following respects:  

There exist no literals for predicate values.  

Predicate values have no persistent representation. (The text representation of a predicate value is simply a hexadecimal number (i.e. the value of a pointer)). 

Predicate values have many usages. One of the most important usages is for callbacks.  

A callback is a predicate that is used to call back from some used entity to the user of this entity. For example:   

a call back from a server to a client, or

a call back from a service to the service user, or

a call back from a routine to a routine user.  

Callbacks are normally used for one or both of the following purposes:    

to handle asynchronous events

to provide advanced/dynamic parameterization  

When dealing with asynchronous events a program registers a callback with some event source. This event source then invoke the callback whenever an event occur. “Data ready” in asynchronous communication is a typical example of such an asynchronous event. Another very typical example is a windows event handler.  

As an example of advanced/dynamic parameterization assume a tool that can create a certain kind of window. This window has the ability to change the shape of the cursor (mouse pointer) when it enters certain parts of the window. The window is however intended to work in many different situations, and therefore it can not know which cursor to use in which parts of the window. In fact the choice of cursor might depend on numerous things of which the window have no knowledge at all. Subsequently the window simply leave the choice of cursor to the program that uses the window. And the way does that is by invoking a callback predicate, asking the surrounding program what cursor to use, when the mouse enters a certain part of the window. Since the window makes such a callback each time the mouse enters a certain part it need not receive the same cursor each time, the choice of cursor may dynamically depend on things external to the window.  

Notice that predicate values are values of predicate domains (please, refer to the online Help for details about declaring predicate domains, etc).

Object Predicate Values

 Visual Prolog support a notion of object predicate values. Object predicate values is a generalization of predicate values (and as such the reader is encouraged to understand that notion first) An object predicate value is a non-static predicate of a specific object. This is opposed to ordinary/plain predicate values which are either global, local or static predicates.

Seen from outside an object predicate value, look like a plain predicate value, because the object to which it belongs is subsumed by the value itself. Therefore the invocation of an object predicate value looks exactly the same as the invocation of a plain predicate value: It is simply applied to arguments. But the execution will (nevertheless) take place in the context of the specific object to which the object predicate value relates.  

So the main reason for using object predicate values over predicate values is that the execution will occur in a specific context.

To illustrate this semantics let us consider an example:

First we declare an object predicate domain (please refer to the online help for details about declaring object predicate domains, etc):  

global domains
    objectIntInt = object procedure integer (integer)

The domain objectIntInt declares object predicates from integer to integer with procedure mode. Now let us declare a predicate of this domain. Recall that the predicate must be a non-static member predicate, and subsequently it must be declared in a class:

class cLast
    predicates
        last : objectIntInt
endclass cLast

To really illustrate that last is indeed a non-static member predicate, we let it’s return value depend on the state of the object. In fact we will let it return the parameter it was called with at the previous invocation. So we store the parameter in a fact from one invocation to the next:

 implement cLast
    facts
        % invariant: “lastParamater” holds 
% the parameter value from last 
%invocation of “last”
        % initially assume 0 as value from “last” invocation
        single lastParameter(integer Last)
    clauses
         lastParamenter(0).       
 
         last(ThisParameter, LastParameter) :-
             lastParameter(LastParameter),
             assert(lastParamenter(ThisParameter)).
endclass cLast

So far the only thing special about this example is the way the predicate last is declared. And before we really use last as a an object predicate value, let us use it like a normal non-static member predicate:

 predicates
    test1() – procedure ()
clauses
    test1() :-
        O1 = cLast::new(),
        O2 = cLast::new(),
        _ = O1:last(1),
        _ = O2:last(2),
        V1 = O1:last(3),
        V2 = O2:last(4),
        writef(“V1 = %, V2 = %”, V1, V2), nl,
        O1:delete(),
        O2:delete().

 If we invoke test1 then it will first create two objects O1 and O2. Then it invoke last on O1 with parameter 1 and on O2 with parameter 2. Both O1 and O2 will store their parameter in there respective lastParameter fact. So, when last is invoked again we will retrieve 1 and 2, respectively. Subsequently, the invocation will produce the output:

    V1 = 1, V2 = 2

 Now let us do the same again, only this time we will use the predicates as values held in variables:

 predicates
    test2() – procedure ()
clauses
    test2() :-
        O1 = cLast::new(),
        O2 = cLast::new(),
        P1 = O1:last, 
% P1 is a member of the object predicate 
%  domain objectIntInt
        P2 = O2:last,
        _ = P1(1),
        _ = P2(2),
        V1 = P1(3),
        V2 = P2 (4),
        writef(“V1 = %, V2 = %”, V1, V2), nl,
        O1:delete(),
        O2:delete().

 The first thing to notice is that an object predicate value consists of both an object and a predicate. Invocation of an object predicate value is, however, completely identical to invocation of an ordinary predicate value, i.e. you do not apply the value to an object, you simply invoke it on appropriate parameters.

  The effect of running test2 is exactly the same as when running test1: Executing P1(1) will store 1 in the lastParameter fact of O1. Likewise the next call of P1 will retrieve the value stored in the lastParamater fact of O1. And completely similarly P2 will refer to O2.

Object predicate values are at least as useful for callbacks as plain predicate values (please refer to the description of predicate values for a discussion of callbacks). The benefit from using object predicate values (over plain predicate values) is that the call back come back to a specific context, namely the object to which the callback belongs. This makes it possible to deal with several different callbacks of the same kind because each callback will end up in its own context.

Let’s walk through an example. Assume that we have a number of “things” that are interested in knowing when a certain value changes. (For the sake of the example this value is simply an integer.) These things want to be notified asynchronously about the change in value. Therefore they register a “dataReady” listener at a data ready source. In this example we choose to transfer the new value together with the data ready notification, but with more complex data we might let the listener pick up the data itself.

We represent the data ready source by an object of class cDataReadySource. If we have several pieces of data that can “become ready”, then we can use one instance of cDataReadySource per data piece, making it possible to listen to notifications for exactly those of interest. cDataReadySource supports registering and unregistering of listeners. It also have a predicate for setting the value in question.

 Listener are represented by object procedure values (i.e. object callbacks).

 class cDataReadySource
    domains
        dataReadyListener = 
object procedure (
cDataReadySource EventSource, 
integer NewValue)
    predicates
        addDataReadyListener(dataReadyListener Listener) – procedure (i)
        removeDataReadyListener(dataReadyListener Listener) – procedure (i)
    predicates
        setValue(integer NewValue) – procedure (i)
endclass cDataReadySource

 The implementation is quite straightforward. We store the currently registered listeners in a fact, and, when the data is changed, we notify all registered listeners of this.

 implement cDataReadySource
    facts
        % Invariant: listener_db contains 
% the currently registered listeners 
% (multiple registrations are ignored)
        listener_db(dataReadyListener Listner)
    clauses
        addDataReadyListener(Listener) :-
            listener_db(Listener), % already registered
            !.
        addDataReadyListener(Listener) :-
            assert(listener_db(Listener)).
 
        removeDataReadyListener(Listener) :-
            retractAll(listener_db(Listener)).
 
    predicates
        dataIsReady(integer NewValue) – procedure ()
    clauses
        dataIsReady(NewValue) :-
            this(This),
            listener_db(Listener),
                Listener(This, NewValue),
            fail.
        dataIsReady().	
   
    clauses
        setValue(NewValue) :-
            dataIsReady(NewValue).
endclass cDataReadySource

Let us also try to use the class above in a context.  Assume that we have system which count how many users that are active, this count is used in a number of places. One of these places is a status window which displays the count. For the sake of the example we imagine that there is a global predicate getUserCountSource which will return a cDataReadySource object corresponding to the count.

 global predicates
    cDataReadySource getUserCountSource() – procedure ()

We implement our status window as a class cStatusWindow. The declaration of cStatusWindow is not very interesting in this context, all we are concerned with is the implementation. In the implementation we put our dataReadyListener and in the constructor of the class we register this listener with the user count data source. We of course also unregister the listener in the destructor.

 class cStatusWindow
    predicates
        updateWindow(integer NewValue) – procedure (i)
    clauses
        updateWindow(NewValue) :- …
 
    predicates
        onUserCountChanged : cDataReadySource::dataReadyListener
    clauses
        onUserCountChanged(_Source, NewValue) :-
            updateWindow(NewValue).
 
    clauses
        new() :-
            UserCountSource = getUserCountSource(),
            UserCountSource:addListener(onUserCountChanged).  % THIS is subsumed
 
        delete() :-
            UserCountSource = getUserCountSource(),
            UserCountSource:removeListener(onUserCountChanged).
endclass cStatusWindow

No matter how many status windows we create they will all be updated when the user count change.