Subject: Re: Did this message ever arrive (inserting/replacing clauses)?

From: Jan Wielemaker <[email-masked]>
Date: Tue, 4 Apr 2000 11:51:29 +0200

[ It appears not.  I get all messages, even if they are rejected by
  the server and I don't always read the headers carefully
]

Date: Wed, 15 Mar 2000 12:41:46 +1300 (NZDT)
From: "Richard A. O'Keefe" <ok>
Message-Id: <[email-masked]>
To: [email-masked], [email-masked]
Subject: Re:  inserting/replacing clauses?

	I've got someone who wants to insert clauses in the middle.

This occasionally came up at Quintus, but there was *never* a good reason
for it and it was *always* possible to do something far better when we
understood what problem the would-be inserter was really trying to solve.
Practically the only known use was in some Prolog systems which had
in-core editors, and even those would have been better to work with a
data structure and replace the _entire_ predicate at the end.

	Slightly cleaner would be
	
		replace(OldClause, NewClause)
	
	which has the nice property of allowing for a database update without
	reordering the clauses.
	
When you have the design right, you _don't_ find yourself asking
"what happens if OldClause and NewClause refer to different predicates?"
or "what if there are _two_ clauses identical (up to renaming of
variables) to OldClause, which gets replaced?".

	Anyone around with strong feeling on whether or not to add such a
	beast to the system, and if yes, name and semantics?
	
I am strongly opposed because I have never yet seen a clean design.
Anything that says "insert in the middle" has to say _where_ in the
middle.  Some of the ways are

    assertn(N, Clause)
	assert Clause as the Nth clause of its predicate.
	What if N < 1?  What if N-1 > #clauses(predicate_of(Clause))?

    assert_after(DbRef, Clause)
	assert Clause just after the clause identified by DbRef.
	What if DbRef identifies a record, not a clause?
	What if the thing DbRef used to point to has been erased?
	What if DbRef points to a clause in a different predicate?
	How do you use this to insert into an empty predicate?

    assert_after(OldClause, NewClause)
	assert Clause just after the last clause equivalent to OldClause,
	pretending that there is such an equivalent clause just before
	the first real clause of the predicate.
	What if OldClause and NewClause belong to different predicates?
	I broke the tie by choosing the last such clause, but that's
	arbitrary; why not the first such clause?
	Just how hard should you work to tell if two clauses are
	equivalent anyway?  Do
	    assert_after((p :- q, (r, s)), X)
	and
	    assert_after((p :- (q, r), s), X)
	always do the same thing, sometimes do the same thing, or
	never do the same thing?  (If they never do the same thing,
	some implementations that wanted to flatten clauses for
	good reason can't; if they always do the same thing, some
	implementations that wanted NOT to flatten clauses, for
	good reason, must; if they only sometimes do the same thing
	the operation is too unreliable to use).

Maintaining an index as one adds clauses at either end is tricky enough;
maintaining an index as one adds clauses at arbitrary places, just to
support bad design, would be silly.

What is this person's *real* problem?