ftl
ftl

Reputation: 647

Prolog: Passing Implicit Parameter / Predicated Evaluation

I am looking for a reliable way to pass an implicit parameter among predicates, e.g.,

p(Context, Args) :- goal(Args).

where goal(Args) should be expanded to something like interpret(Context, goal, Args).

However, since I don't know whether a term will be evaluated as a goal or used as data, I'd like to attach Context to goal as extra data without modifying its actual structure.

Is there any way to do this?

Also, I'd need some way to hook into the evaluation of a term, then fetch its context and call interpret.

Any Ideas?

I am using SWI Prolog, a portable solution would be fine, but is not required.

Edit:

In pseudocode, what I am roughly looking for is the following:

term_expansion((Head :- Body), (Head :- Body)) :-
   arg(1, Head, Context),

   forall T: CompoundTerm in Body =>
       set_term_attribute(T, context, Context).

on_evaluate(T) :-
  get_term_attribute(T, context, Context) -> interpret(Context, T) ;
  call(T).

Upvotes: 4

Views: 588

Answers (2)

Paulo Moura
Paulo Moura

Reputation: 18683

Easy. Use a Logtalk parametric object. You can use this solution with twelve Prolog systems, including SWI-Prolog. For example:

:- object(foo(_Parameter1, _Parameter2)).

    :- public(p1/1).
    p1(Parameter1) :-
        parameter(1, Parameter1).

    :- public(p2/1).
    p2(Parameter2) :-
        parameter(2, Parameter2).

:- end_object.

?- foo(1,2)::p1(P1).
P1 = 1.

?- foo(1,2)::p2(P2).
P2 = 2.

The parameters are logical variables, with all the benefits and potential that entails. The parameters are implicitly shared by all object predicate clauses. In SWI-Prolog, you can even use dicts for parameter values.

It's also easy to provide default parameter values. For example:

:- object(foo, extends(foo(a,b))).

:- end_object.

?- foo::p1(P1).
P1 = a.

?- foo::p2(P2).
P2 = b.

You can find several examples of using parametric objects in the Logtalk distribution.

Upvotes: 1

mat
mat

Reputation: 40768

Check out the important predicates term_expansion/2 and goal_expansion/2.

They allow you to rewrite clauses at compilation time, and these or similar constructs are supported by all serious Prolog systems to provide an expansion mechanism for Prolog code.

Definite clause grammars (see for more information) are often implemented using such mechanisms. In fact, to pass around a context, DCG notation is itself often already sufficient, so you may not even have to rewrite the code yourself in your use case.

See the DCG resources for more information.

Upvotes: 2

Related Questions