🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.lang.prolog
Article #1142

Re: Meta-programming question

#1142
From: Richard A. O'Keefe
Date: Fri, 31 Aug 1990 02:41
96 lines
4397 bytes
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.
Technical Details
Message-ID: <3646@goanna.cs.rmit.oz.au>
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!samsung!munnari.oz.au!goanna!ok
References: <199@qt.cs.utexas.edu>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!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