bradley@cs.utexas.edu (Bradley L. Richards) (08/29/90)
I'm working on a meta-programming project and have run across something I just can't figure a way to do. 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. 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. Can anyone suggest alternate approaches to this problem? --------------------------------------------------------------------------- Bradley L. Richards uucp: cs.utexas.edu!bradley bradley@cs.utexas.edu CompuServe: 75216,1744 ---------------------------------------------------------------------------
vu0310@bingvaxu.cc.binghamton.edu (R. Kym Horsell) (08/30/90)
In article <199@qt.cs.utexas.edu> bradley@cs.utexas.edu (Bradley L. Richards) writes: >I'm working on a meta-programming project and have run across something I just >can't figure a way to do. I want to locate a clause via unification with its >head, and then be able to retrieve the clause *without binding any variables*. I hope RO'K will provide a more definitive answer, but until the post makes it to Oz this will have to do. A general technique (note ``logic programming'' degenerates to a matter of ``technique'') is to use double negation to verify whether something can be proved. For example: verify(X) :- not(not(X)). ?- verify(X=1). produces X=_ The extension to unification of clause headds with goals is straightforward. -Kym Horsell
NEUMANN@awiwuw11.wu-wien.ac.at (Gustaf Neumann) (08/30/90)
> I'm working on a meta-programming project and have run across something > I just can't figure a way to do. 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. I am not sure wether the following Prolog-clause is exactly what you want, but maybe you can use it as a first approximation: %get_clause(+,-,-) get_clause(Match,Head,Body) :- functor(Match,F,A), functor(Head,F,A), clause(Head,Body), \+ \+ Head=Match. ?- get_clause(member(a,[X|Y]),Head,Body). Body = true, Head = member(_199,[_199|_202]), X = _65, Y = _79 ? ; Body = member(_199,_202), Head = member(_199,[_201|_202]), X = _65, Y = _79 ? If this version is not fast enough for your application, one should think about a more clever representation of the clauses. -gustaf ------------------------------------------------------------------- Gustaf Neumann neumann@dec4.wu-wien.ac.at, neumann@awiwuw11.bitnet Vienna University of Economics and Business Administration Augasse 2-6, A-1090 Vienna, Austria Tel: +43 (222) 347-541 x533 Fax 347-555
ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (08/31/90)
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.
bradley@cs.utexas.edu (Bradley L. Richards) (08/31/90)
First, many thanks to all the folks who responded to my question! >ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) writes: >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). Indeed this is exactly what I want to do. And I'm in strong agreement with your first comment, because Arity *does not* support the clause/3 predicate. I attempted to write one using recorded/3 when I found that it can in fact access clauses--but, sadly, it doesn't do so in a consistent manner. So, it looks like I'm stuck with the effective but slow version > head_nobind_clause_nobind(Head, Clause) :- > functor(Head, F, N), > functor(Skel, F, N), > clause(Skel, Body), > \+ \+ Skel = Head, > make_clause(Skel, Body, Clause). >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. Indeed you are right. I've been away from Prolog for a while so I'm not sure if this is "standard," but Arity provides the option of creating different "code worlds," and I keep the meta-programming stuff isolated this way. This has the advantage that when I want to execute a predicate in the object program, I can merely change worlds and call the appropriate predicate. Presuming it doesn't go off in never-never land, and that I don't want any intermediate results, this is faster than running a metainterpreter. Thanks again! Bradley --------------------------------------------------------------------------- Bradley L. Richards uucp: cs.utexas.edu!bradley bradley@cs.utexas.edu CompuServe: 75216,1744 ---------------------------------------------------------------------------