Language Reference/Terms/Anonymous Predicates

An anonymous predicate is an expression that evaluates to a predicate value. The predicate value can be bound to a variable, passed as arguments or returned as result, but the value does not have a name in any class, interface or implementation.

Anonymous predicates have the ability to capture values from the context in which the expression occurs, this is a rather powerful ability that can be used to avoid rather excessive amount of strange/unpleasant code.

Syntax
Anonymous predicates are terms:

 : one of   ...  ...

An anonymous predicate is a nameless clause in curly brackets. Certain parts are optional, giving these forms:

 : one of   { ( -comma-sep-list ) =  } { ( -comma-sep-list ) =  :-  } { ( -comma-sep-list ) :-  } { =  } { =  :-  } { :-  } Leaving out the argument list means "the required number of arguments" and can be used whenever the arguments are not used.

Semantics
An anonymous predicate expression evaluates to a predicate value. Consider this code:

clauses run :- Inc = { (X) = X+1 }, A = Inc(4), B = Inc(23), stdio::writef("A = %, B = %", A, B). Inc becomes an increment predicate, so the program will write:

The code in this example corresponds to this code:

clauses run :- Inc = inc, A = Inc(4), B = Inc(23), stdio::writef("A = %, B = %", A, B).

class predicates inc : (integer X) -> integer R. clauses inc(X) = X+1. Where the clause (X) = X+1 can be found in the last line. I.e. this time in a named predicate.

Variables that are bound outside (i.e. before the occurrence of) an anonymous predicate can be used inside the anonymous predicate. The value of variable will be captured by the anonymous predicate.

Variables that are bound in an anonymous predicate are local variables in the anonymous predicate.

Capturing context
An anonymous predicate can capture context, which means that it can refer to things that are defined in its context, especially facts and variables from the clause.

Capturing Variables
Anonymous predicate occurs in a clause, and this clause may contain variables. Those variables that are bound before the anonymous predicate is met can be used inside the anonymous predicate. This code illustrates how a variable is captured:

domains pred = (integer) -> integer.

class predicates createAdder : (integer A) -> pred Adder. clauses createAdder(A) = { (X) = X+A }.

clauses run :- Add17 = createAdder(17), A = Add17(4), B = Add17(20), stdio::writef("A = %, B = %", A, B). We call createAdder</vp> with 17</vp> as argument. So in the createAdder</vp> clause A</vp> is 17</vp>, and therefore the result is { (X) = X+17 }</vp>. We say that the anonymous predicate has captured the variable A</vp>.

Since Add17</vp> is a predicate that adds 17</vp> to its argument, the output of the code will be:

Capturing ellipsis (...)
An anonymous predicate can capture the ellipsis variable (i.e. ...):

clauses ppp(...) :- W = { :- stdio::write(...) }, qqq(W). W</vp> captures the ellipsis variable. qqq</vp> receives a zero-arity predicate, when this predicate is invoked the captured ellipsis variable will be written to the standard output device.

Capturing Facts
An anonymous predicate can access facts. If it is created by a class predicate it can access class facts. If it is created by an object predicate it can access both object and class facts. Consider this code that captures a class fact:

class facts count : integer := 0. clauses seq = { = count :- count := count+1 }. clauses run :- A = seq, B = seq, stdio::writef("A1 = %, ", A), stdio::writef("B1 = %, ", B), stdio::writef("A2 = %, ", A), stdio::writef("B2 = %", B). Both A</vp> and B</vp> increment the class fact count, so the result is

In object predicates we can capture object facts. So assuming that seq</vp> is an object predicate in myClass</vp>, this code illustrates the capture of an object fact:

facts count : integer := 0. clauses seq = { = count :- count := count+1 }. clauses run :- A = myClass::new:seq, B = myClass::new:seq, stdio::writef("A1 = %, ", A), stdio::writef("B1 = %, ", B), stdio::writef("A2 = %, ", A), stdio::writef("B2 = %", B). In this case A</vp> and <vp>B</vp> comes from two different objects, which each have a count fact, so the output will be:

Technically, the class version actually doesn't capture anything, it merely have access to the fact. Likewise, the object version doesn't actually capture the fact, instead it captures This and through This it obtains access to the object facts.

Capturing This
As described above it is possible to capture <vp>This</vp> and thereby gaining access to objects facts. The same mechanism gives access to calling object predicates.

clauses seq = { = count :- inc }.

clauses inc :- count := count+1. <vp>This</vp> can also be used directly: clauses ppp = { = aaa::rrr(This) }.

Nesting
Anonymous predicates can be nested:

clauses run :- P = { (A) = { (B) = A+B } }, Q = P(3300), R = P(2200), stdio::writef("Q(11) = %, ", Q(11)), stdio::writef("R(11) = %", R(11)). To obtain <vp>Q</vp> we call <vp>P</vp> with <vp>3300</vp>, so <vp>A</vp> is <vp>3300</vp> and <vp>Q</vp> therefore becomes <vp>{ (B) = 3300+B } }</vp>, likewise R becomes <vp>{ (B) = 2200+B } }</vp>. So, the output is:

Syntactic Sugar
If you don't need the arguments they can be skipped. So this code-fragment:

P = { (_) :- succeed }, Q = { (_, _) = 0 }, R = { (_, _, _) = _ :- fail } Can be shortened down to this: P = { :- succeed }, Q = { = 0 }, R = { = _ :- fail }

Notice that the arguments are completely skipped. If you write <vp></vp> it means zero arguments, whereas skipping the arguments means "a suitable amount" of arguments.

Examples of practical usage
This section shows some cases where anonymous predicates are very handy. The examples assume that the PFC scopes core, std, stdio, list and string are open.

Dummy predicates
Anonymous predicates are good for creating dummy predicate values:

ppp( { = true } ), % don't filter (boolean) qqq( { :- succeed } ), % don't filter (determ) rrr( { = 17 } ), % all rows must have height 17

Adaptation
In cases where you need a predicate and have one that is almost suitable, you can make the adaptation using an anonymous predicate.

Index adaptation
Consider the predicate write3:

class predicates write3 : (function{integer, string} Indexer). clauses write3(Indexer) :- foreach I = std::fromTo(0,2) do           write(Indexer(I), "\n") end foreach. Indexer implements an "array" of strings, <vp>write3</vp> will write the three strings found at the indexes <vp>0</vp>, <vp>1</vp> and <vp>2</vp>. So <vp>write3</vp> assumes that the "array" index is zero-based. However, the "array" we have uses a one-based index:

class predicates myArray : (integer N) -> string Value. clauses myArray(1) = "First" :- !. myArray(2) = "Second" :- !. myArray(3) = "Third" :- !. myArray(_) = _ :- raiseError. But using an anonymous predicate we can easily adapt the one-based array to the zero-based usage:

% myArray is 0-based, write3 requires 1-based Arr = { (N) = myArray(N+1) }, write3(Arr)

So we get the expected output:

Parameter adaptation
In this code <vp>listChildren</vp> will call a <vp>ChildWriter</vp> predicate for each "<vp>C</vp> is the child of <vp>P</vp>"-pair:

class predicates listChildren : (predicate{string,string} ChildWriter). clauses listChildren(CW) :- CW("Son1", "Father"), CW("Son2", "Father"). We will however prefer to list the "<vp>P</vp> is the parent of <vp>C</vp>" using the predicate <vp>wParent</vp>:

class predicates wParent : (string Parent, string Child). clauses wParent(P, C) :- writef("% is the parent of %\n", P, C). <vp>wParent</vp> takes the arguments in the opposite order, but we can easily adapt using an anonymous predicate:

Swap = { (A,B) :- wParent(B,A) }, listChildren(Swap)

And then the out becomes the expected:

We can also throw away arguments, for example when calling this predicate that only needs a <vp>Child</vp>:

class predicates wKnowParent : (string Child). clauses wKnowParent(C) :- writef("We know a parent of %\n", C). The adaptation looks like this:

Fewer = { (C,P) :- wKnowParent(C) }, listChildren(Fewer)

The output will be:

We can also supply dummy arguments:

More = { (_,P) :- addChildren(P, 1) } listChildren(More)

Here <vp>addChildren</vp> will "add a count of children to <vp>P</vp>". Since each invocation corresponds to one child we will call <vp>addChild</vp> supplying <vp>1</vp> as a "dummy" argument. The More is thus an adaptor that both throws away an argument and supplies a dummy argument.

Filters
Assume this predicate:

class predicates writeFiltered : (string L, predicate_dt{integer} Filter). clauses writeFiltered(Label, Filter) :- List = [1,2,3,4,5,6,7,8,9], FilteredList = filter(List, Filter), writef("%\t%\n", Label, FilteredList). Filter is used to filter the list <vp>[1,2,3,4,5,6,7,8,9]</vp>; the filtered list and the Label are written to the standard output.

First we use the allow-all filter:

All = { :- succeed }, writeFiltered("All", All)

This filter simply succeeds for any element, so the output is the entire list:

It is just as easy to create a filter that fails for all elements and thus allow-none:

None = { :- fail }, writeFiltered("None", None)

The output from this is the empty list:

We can also create filters for elements greater than <vp>3</vp> and elements dividable by <vp>3</vp>:

GreaterThan3 = { (X) :- X > 3 }, writeFiltered("> 3", GreaterThan3), Rem3 = { (X) :- 0 = X rem 3 }, writeFiltered("Rem3", Rem3)

The output from this is:

Sorting
The list package has a sort predicate. But sometimes the default order is not what you need. Therefore the list package also has a predicate sortBy, which sorts the elements using a programmer defined compare operation. Let us first consider string sorting, using this predicate:

class predicates writeStringsSorted : (string Label, comparator{string} Comp). clauses writeStringsSorted(Label, C) :- List = ["John Wayne", "Uma Thurman", "Harrison Ford", "Nicolas Cage", "Elizabeth Taylor", "Cary Grant", "Jerry Lewis", "Robert De Niro"], Sorted = sortBy(C, List), write(Label, "\n"), foreach S = list::getMember_nd(Sorted) do           writef("    %\n", S)        end foreach. We can call the predicate with the "normal" comparator, and using an anonymous predicate we can easily sort it descending as well:

Normal = compare, writeStringsSorted("Normal", Normal), Descending = { (A,B) = compare(B,A) }, writeStringsSorted("Descending", Descending)

The output looks like this:

Let us also sort some more complex elements. Here a person has a first name and a last name, using this domain:

domains person = p(string First, string Last). For the demonstration we will use this test predicate: class predicates writePersonsSorted : (string Label, comparator{person} Comparator). clauses writePersonsSorted(Label, C) :- List = [p("John","Wayne"), p("Uma","Thurman"), p("Harrison","Ford"), p("Nicolas","Cage"), p("Elizabeth","Taylor"), p("Cary","Grant"), p("Jerry","Lewis"), p("Robert","De Niro")], Sorted = sortBy(C, List), write(Label, "\n"), foreach p(F,L) = list::getMember_nd(Sorted) do           writef("    % %\n", F, L)        end foreach. Again we can sort using the normal and a descending comparator:

Normal = compare, writePersonsSorted("Normal", Normal), Descending = { (A,B) = compare(B,A) }, writePersonsSorted("Descending", Descending)

Since the compare predicate uses left-to-right lexicographic order on the <vp>p</vp>-functor, the result is the same as before:

But with the more complex domain we can create a comparator that will sort on last name:

LN = { (p(_,L1), p(_, L2)) = compare(L1,L2) }, writePersonsSorted("LastName", LN)

The result is what we expect:

Capturing context
As mentioned a very powerful feature of anonymous predicates is the ability to capture context. The examples in this section show some ways you can use this.

Background threads
The routine for starting a thread takes a null-ary predicate and runs it in the new thread. But you nearly always need to pass some input data to the job in the new thread. This is possible in several ways, but the absolutely simplest way is to use anonymous predicates. The project <vp>bgDemo</vp> from the Visual Prolog example collection (that can be installed from the IDE) use this method. The project has a form that can start a background job and display status information from the job in a <vp>jobControl</vp> that is added to the form. A background job is a predicate that will receive a <vp>jobLog</vp>, which it can use to report status and completion degree:

domains job = (jobLog Log). A jobLog looks like this: interface jobLog

properties completion : real (i).

properties status : string (i).

end interface jobLog The job can report completion degree by setting the completion property (range <vp>0</vp> to <vp>1</vp>). Likewise, the status property can be used to reflect the current status of the job.

The status and completion will be shown in the form together with a job name. A job is started by calling the form's <vp>addJob</vp> predicate:

clauses addJob(JobName, Job) :- JobCtrl = jobControl::new(This), JobCtrl:name := JobName, JobCtrl:show, assert(jobCtrl_fact(JobCtrl)), arrange, JobLog = jobLog::new(JobCtrl), Action = { :- Job(JobLog) }, _ = thread::start(Action). In this context it is the last three lines that are interesting. <vp>thread::start</vp> takes a null-ary predicate as argument, but a job is a predicate that takes a <vp>jobLog</vp> as argument. Therefore we create an anonymous predicate <vp>Action</vp>, which takes no arguments but invokes <vp>Job</vp> on the <vp>JobLog</vp>. The anonymous predicate has captured both <vp>Job</vp> and <vp>JobLog</vp> from the context, and subsequently both these values are transferred to the new thread even though this thread only receives a null-ary predicate. The jobs in the <vp>bgDemo</vp> project are merely dummy jobs that only manipulate their <vp>jobLog</vp>. One of them looks like this:

clauses job(Log, From, To) :- Log:status := "Step 1", foreach N1 = std::fromTo(From, To) do           Log:completion := (N1-From) / (To-From) / 2, programControl::sleep(3) end foreach, Log:status := "Step 2", foreach N2 = std::fromTo(From, To) do           Log:completion := (N2-From) / (To-From) / 2 + 0.5, programControl::sleep(3) end foreach, Log:status := "finished". It has two loops which run from <vp>From</vp> to <vp>To</vp> and calculates the completion and sets it on the <vp>Log</vp>. It also sets the status text before, between and after the loops. You may notice that the job does not have the proper job type, because a proper job only has one argument (the <vp>jobLog</vp>), this job has three arguments. Again it is anonymous predicates that help us. The code that adds the jobs to the form looks like this:

predicates onFileNew : window::menuItemListener. clauses onFileNew(_Source, _MenuTag) :- JF = jobForm::display(This), Job11 = {(L) :- job1::job(L, 1, 1000)}, Job12 = {(L) :- job1::job(L, 200, 600)}, Job13 = {(L) :- job1::job(L, 1200, 3000)}, Job14 = {(L) :- job1::job(L, 1, 1000)}, JF:addJob("job1.1", Job11), JF:addJob("job1.2", Job12), JF:addJob("job1.3", Job13), JF:addJob("job1.4", Job14), ... In a more realistic program, it is most likely that <vp>From</vp> and <vp>To</vp> would not be constants, but rather parameters passed from some outer place. In that case these anonymous predicates would also capture variables from the context. The <vp>jobLog</vp> in the <vp>bgDemo</vp> illustrates one more usage of anonymous predicates. The <vp>jobLog</vp> pass the completion and the status information to a <vp>jobControl</vp>. The <vp>jobControl</vp> is a GUI control on the <vp>jobForm</vp> capable of doing a suitable rendering of the information. This however gives a synchronization problem, because GUI controls are not thread safe and here we want to update some controls from a background thread. This can lead to conflicts, because it is the main thread that draws the controls. The solution is to make transfer the the update of the control to the GUI thread. We do this by posting actions to the control. The implementation of the status update looks like this:

clauses status(Status) :- Action = { :- jobCtrl:status := Status }, jobCtrl:postAction(Action). <vp>Action</vp> is a null-ary predicate that will set the status in the <vp>jobCtrl</vp>. We post this action to the <vp>jobCtrl</vp>. When the <vp>jobCtrl</vp> receives the action it invokes it and is thus updated. This way, the actual update of the control will be performed by the GUI thread. This anonymous predicate not only captures the <vp>Status</vp> variable it also captures the <vp>jobCtrl</vp> fact.

Asynchronous callbacks
Assume that we send commands to a remote service. The command execution is asynchronous, so when we execute a command we also give a callback action which will be invoked when the execution of the command is finished. To execute a command we must call this predicate:

predicates executeCommand : (command Cmd, predicate{} OnDone). Based on this predicate we want to create a similar predicate that can execute a list of commands. A certain command should be executed when the previous command completes. We will also make our list executor asynchronous, so we supply an action that will be invoked when the entire script of commands are finished. Our script executer will have the form:

predicates executeScript : (command* Script, predicate{} OnDone). If the script is empty we simply invoke the <vp>OnDone</vp> action. If the script has a command <vp>H</vp> and a rest script <vp>T</vp>, we must first execute <vp>H</vp>, and when it is finished we must execute the rest of the script <vp>T</vp>. So the <vp>OnDone</vp> action we supply when executing <vp>H</vp> must execute <vp>T</vp>. All in all, the implementation can look like this:

clauses executeScript([], OnDone) :- OnDone. executeScript([H|T], OnDone) :- DoneH = { :- executeScript(T, OnDone) }, executeCommand(H, DoneH). We have used an anonymous predicate to perform the execution of the rest of the script. This anonymous predicate captures <vp>T</vp> and <vp>OnDone</vp>.