Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!samsung!munnari.oz.au!goanna!ok From: ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) Newsgroups: comp.lang.prolog Subject: Re: Meta-programming question Message-ID: <3646@goanna.cs.rmit.oz.au> Date: 31 Aug 90 02:41:31 GMT References: <199@qt.cs.utexas.edu> Organization: Comp Sci, RMIT, Melbourne, Australia Lines: 96 In article <199@qt.cs.utexas.edu>, bradley@cs.utexas.edu (Bradley L. Richards) writes: > I want to locate a clause via unification with its > head, and then be able to retrieve the clause *without binding any variables*. > The goal here is to modify the clause and replace it, so it's essential that > I avoid making unintended changes via bindings. Sigh. This is why we wanted a Prolog standard... It isn't perfectly clear what you don't want bound. If you are probing for a clause with a pattern, and you are happy for that pattern to get instantiated, but you want (a copy of) the original clause, do head_clause_nobind(Head, Clause) :- clause(Head, _, Ref), instance(Ref, Clause). in any Edinburgh-compatible Prolog. If you don't want the pattern to be bound either, do head_nobind_clause_nobind(Head, Clause) :- findall(Clause, head_clause_nobind(Head,Clause), [Clause]). /* There is a subtle detail here. This would work in DEC-10 Prolog, but head_nobind_clause_nobind(Head, Clause) :- findall(Ref, clause(Head, _, Ref), [Ref]), instance(Ref, Clause). would _not_ work in DEC-10 Prolog. C Prolog, Quintus Prolog, SICStus Prolog, NU Prolog, and others would have no problem. */ > In Arity Prolog I can achieve most of this effect by accessing the clause > using their database predicate "recorded," which returns both the clause > (which I verify via unification) and a reference number I can use for later > access. The catch is that any comparator predicates (e.g. N \== 2) are > loused up in the returned clause. Arity tells me that they hadn't intended > for users to access clauses with database predicates, so this isn't a > supported feature. I am rather surprised that 'recorded' can get at ordinary program clauses; a large part of the reason for having 'recorded' in DEC-10 Prolog was to make it _impossible_ to confuse database terms with clauses. It's rather hard to suggest anything without an Arity manual. Let's see what we might do. head_nobind_clause_nobind(Head, Clause) :- functor(Head, F, N), functor(Skel, F, N), clause(Skel, Body), \+ \+ Skel = Head, make_clause(Skel, Body, Clause). make_clause(Head, true, Clause) :- !, Clause = Head. make_clause(Head, Body, :-(Head,Body)). This will do what I _think_ is wanted. It is, of course, rather slow. May I respectfully suggest that trying to use the "raw" clause store is almost always a bad idea? Suppose you are doing your meta-programming and start tinkering with the append/3 predicate. What if your meta-program uses append/3? You want to keep the levels separate. I would be strongly inclined to keep the "object" clauses in their own table. (I'd rather keep them in a term, but on a PC the 8086's addressing limitations are such that that's likely to be hard.) For example, the very simplest way of solving _this_ problem is, whenever you store an "object" clause, instead of doing assert((Head :- Body)) do assert(object_clause(Head, Head, Body)). What does that buy you? Why this: head_clause_nobind(Goal, (Head :- Body)) :- object_clause(Goal, Head, Body). In fact, for meta-programming (as John Lloyd and others have pointed out) it may be better to use a representation in which object clauses are ground. You could then do store_object_clause(Head, Body) :- /* Head and Body are ground terms */ unnumbvervars(Head, Goal), assert(object_clause(Goal, Head, Body)). fetch_object_clause(Goal, Head, Body) :- /* Goal may be instantiated; Head, Body come back ground */ object_clause(Goal, Head, Body). Whether you use a ground representation or not, I strongly suggest keeping the "object" clauses in their own table. Amongst other benefits, that way you can be sure that assert won't rewrite the body of one of your clauses, because it won't realise that it _is_ a clause body. -- You can lie with statistics ... but not to a statistician.