From ok@atlas.otago.ac.nz Thu Mar  8 00:44:19 2001
Received: from atlas.otago.ac.nz (atlas.otago.ac.nz [139.80.32.250])
	by swi.psy.uva.nl (8.11.2/8.11.2) with ESMTP id f27NiIZ27855
	for <prolog@swi.psy.uva.nl>; Thu, 8 Mar 2001 00:44:18 +0100 (MET)
Received: (from ok@localhost)
	by atlas.otago.ac.nz (8.9.3/8.9.3) id MAA13332;
	Thu, 8 Mar 2001 12:42:49 +1300 (NZDT)
Date: Thu, 8 Mar 2001 12:42:49 +1300 (NZDT)
From: "Richard A. O'Keefe" <ok@atlas.otago.ac.nz>
Message-Id: <200103072342.MAA13332@atlas.otago.ac.nz>
To: dietmar@sigma.upb.de, prolog@swi.psy.uva.nl
Subject: Re:  [SWIPL] generating dynamic rules?

"Dietmar Harlos" <dietmar@sigma.upb.de> wrote:
	I have the following problem with SWI-Prolog.  I have to
	generate a dynamic rule at runtime, but the variables don't
	match.  Please see this short example:
	
	    knot(1, fetch(Variable)).
	    knot(2, write(Variable)).

	    dynrule :-
		knot(1, Rule1),
		knot(2, Rule2),
		assert(( testme :- Rule1, Rule2 )),
		listing(testme),
		testme.

	    fetch(A) :-
		A = 4.

	The output at the prolog prompt is as follows:
	
	?- dynrule.
	
	testme :-
	        fetch(A),
	        write(B).
	_L114
	
	Yes

A *fundamental* aspect of any programming language is scope of variables.
In Prolog, the scope of a variable is the clause that contains it.

In the fact knot(1, fetch(Variable)) you have a variable whose scope is
that fact ONLY.  It could use as well have been written
	knot(1, fetch(Rumpelstiltskin)).
In the fact knot(2, write(Variable)) you have a completely unrelated
variable whose scope is that clause.  It could have been written
	knot(2, write(Goldilocks)).

There is no connection between variables in different clauses.
For a parallel, consider

	void knot_1(void) { int Variable; Variable = fetch(); }
	void knot_2(void) { int Variable; printf("%d", Variable); }

in C.  Just as you would expect the two variables in the C code to be
unrelated variables despite their names being spelled the same, so you
should expect variables in different clauses in C to be unrelated.

What you should do is

	knot(1, X, fetch(X)).
	knot(2, X, write(X)).

	dynrule :-
	    knot(1, X, Body1), % NOT Rule1, because it isn't a rule
	    knot(2, X, Body2), % NOT Rule2, because it isn't a rule
	    assert(( testme :- Body1, Body2 )),
	    listing(testme),
	    testme.

	fetch(4).

and then you'll get

	?- dynrule.
	testme :-
		fetch(A),
		write(A).
	4

	Can anyone help me?  Have I to process the two parts of the rule
	as strings?

Of course not.  You have to treat them as Prolog data structures.
You just have to *say* which parts of the data structures are to be
shared with other contexts.

I suggest as a matter of urgency that you get yourself a good Prolog
textbook such as Sterling & Shapiro "The Art of Prolog" and read it.

