3

I'm adding library support for common term-expansion workflows (1). Currently, I have defined a "set" workflow, where sets of term-expansion rules (2) are tried until one of them succeeds, and a "pipeline" workflow, where expansion results from a set of term-expansion rules are passed to the next set in the pipeline. I wonder if there are other sensible term-expansion workflows that, even if less common, have practical uses and are thus still worth of library support.

(1) For Logtalk, the current versions can be found at:

https://github.com/LogtalkDotOrg/logtalk3/blob/master/library/hook_pipeline.lgt https://github.com/LogtalkDotOrg/logtalk3/blob/master/library/hook_set.lgt

(2) A set of expansion rules is to be understood in this context as a set of clauses for the term_expansion/2 user-defined hook predicate (also possibly the goal_expansion/2 user-defined hook predicate, although this is less likely given the fixed point semantics used for goal-expansion) defined in a Prolog module or a Logtalk object (other than the user pseudo-module/object).

Paulo Moura
  • 18,373
  • 3
  • 23
  • 33
  • 2
    Great ! I would beg for debugging support, tough, specially if side effects are allowed – CapelliC Nov 16 '15 at 16:19
  • @CapelliC I'm open to suggestions. I assume that you would want something that goes behind simply tracing the expansion hook predicates? – Paulo Moura Nov 21 '15 at 15:08

1 Answers1

2

The fixpoint is both already a set and a pipeline on a certain level during expansion. Its expand_term/2 is just the transitive closure of the one step term_expansion/2 clauses. But this works only during decending into a term, in my opinion we also need something when assembling the term again.

In rare cases this transitive closure even needs the (==)/2 check as is found in some Prolog systems. Most likely it can simply stop if none of the term_expansions/2 do anything. So we have basically, without the (==)/2 check:

expand_term(X, Y) :- term_expansion(X, H), !, expand_term(H, Y).
expand_term(.. ..) :- /* possibly decend into meta predicate */

But what I would like to see is a kind of a simplification framework added to the expansion framework. So when we decend into a meta predicate and come back, we should call a simplification hook.

It is in accordance with some theories of term rewriting, which say: the normal form (nf) of a compound is a function of the normal form of its parts. The expansion framework would thus not deal with normal forms, only deliver redefinitions of predicates, but the simplification framework would do the normal form work:

 nf(f(t_1,..,t_n)) --> f'(nf(t_1),..nf(t_n))

So the simplification hook would take f(nf(t_1), .., nf(t_n)), assuming that expand_term when decending into a meta predicate yields already nf(t_1) .. nf(t_n) for the meta arguments, and then simply give f(nf(t_1), .., nf(t_n)) to the simplifier.

The simplifier would then return f'(nf(t_1), .., nf(t_n)), namely do its work and return a simplified form, based on the assumption that the arguments are already simplified. Such a simplifier can be quite powerful. Jekejeke Prolog delivers such as stage after expansion.

The Jekejeke Prolog simplifier and its integraton into the expansion framework is open source here and here. It is for example used to reorder conjunction, here are the example rules for this purpose:

/* Predefined Simplifications */
sys_goal_simplification((  (  A, B), C), J) :-
   sys_simplify_goal((  B, C), H),
   sys_simplify_goal((  A, H), J).

Example:
     (((a, b), c), d) --> (a, (b, (c, d)))

The Jekejeke Prolog simplifier is extremly efficient, since it can work with the assumption that it receives already normalized terms. It will not unnecessarely repeatedly do pattern matching over the whole given term.

But it needs some rewriting system common practice to write simplfication rules. A simplficiation rule should call simplification when ever it constructs a new term.

In the example above these are the two sys_simplify_goal/2 calls, we do for example not simply return a new term with (B,C) in it, as an expansion rule would do. Since (B,C) was not part of the normalized arguments for sys_goal_simplification/2, we have to normalize it first.

But since the simplifier framework is interwined with the expansion framework, I doubt that it can be called a workflow architecture. There is no specific flow direction, the result is rather a ping pong. Nevertheless the simplfication framework can be used in a modular way.

The Jekejeke Prolog simplifier is also used in the forward chaining clause rewriting. There it does generate from one forward clause multiple delta computation clauses.

Bye