Path: utzoo!utgpu!jarvis.csri.toronto.edu!cs.utexas.edu!usc!zaphod.mps.ohio-state.edu!uakari.primate.wisc.edu!aplcen!uunet!mcsun!ukc!strath-cs!cs.glasgow.ac.uk!icdoc!sappho!cdsm From: cdsm@sappho.doc.ic.ac.uk (Chris Moss) Newsgroups: comp.lang.prolog Subject: Re: What does/should your Prolog make of this ? Keywords: cut assert fail backtracking Message-ID: <1681@gould.doc.ic.ac.uk> Date: 7 Mar 90 17:03:25 GMT References: <1990Mar1.210219.5687@Neon.Stanford.EDU> <1557@maestro.htsa.aha.nl> Sender: news@doc.ic.ac.uk Reply-To: cdsm@doc.ic.ac.uk (Chris Moss) Organization: Logic Group, Dept. of Computing, Imperial College, London, UK. Lines: 63 In article <1557@maestro.htsa.aha.nl> jand@maestro.htsa.aha.nl (Jan Derriks) writes: >In the book 'AI Through Prolog', Neil Rowe uses something like this: > >(1) doo :- agenda(X), assertz(agenda(next)), write(X), fail. > >When this rule starts there is ONE fact 'agenda(start)' in the database, >so the first query agenda(X) succeeds with X=start. ... >And following assertz'ed agenda's are NOT found by backtracking, so This is a standard problem with the semantics of assert and retract in Prolog. The problem is of course that when you enter the clause "agenda" the Prolog system wants to know if it has to set up a backtracking point. Any sensible system won't, a naive interpreter will anyway, but will set the address of the next clause in the backtracking frame. Since this is nil at this point, the effect is the same. It will only be non-nil if it bothers to do an extra dereference at backtracking time. Almost the same thing is happening here: >From: feldman@Neon.Stanford.EDU (Todd J. Feldman) > >Can someone please help me with a bug in the following Prolog fragment: > >process_entries:- > wait(X), > abolish(wait,1), > goal1(.....), > goal2(.....), > goal3(.....), > goal4(.....). > >The intention I had in writing this code was for backtracking to occur >between goals 1 and 4. Finally, goal1 will no longer be able to succeed. But this is one of the easiest ways to crash a fragile Prolog system. Why? The reference to the next "wait" clause has already been stored, when the abolish goes ahead and deletes the clause. Now one of several things can happen. If the "orphaned" next clause happens still to be lying around in store, it will still be executed. If however its space has been reclaimed and in the meanwhile your process has put something else there which is NOT a clausehead, then the system will probably crash. The Edinburgh compiler and its offsprings guarded against this by not recovering space until the end of the program. The better way is make the semantics of assert and retract more logical: that is to copy the "readers and writers" approach to file consistency. Once you've started reading (executing) a predicate, it will stay static and any changes will not be visible. But any subsequent reads (executions) will see the new copy. Not all Prologs do this yet. But Quintus started and the Prolog standard has also incorporated this notion, so hopefully more are following. Does anyone know of others? Mail to me and I'll post. In both cases the problem can be solved by backtracking PAST the goal and then reentering, though some recoding will be needed (e.g. asserta not assertz). I'm not convinced that either program should use assert or retract however. Chris Moss.