Path: utzoo!utgpu!jarvis.csri.toronto.edu!clyde.concordia.ca!uunet!samsung!munnari.oz.au!bruce!goanna!ok From: ok@goanna.oz.au (Richard O'keefe) Newsgroups: comp.lang.prolog Subject: Re: incrementing values Summary: ask for comments and you'll get them... Message-ID: <2834@goanna.oz.au> Date: 2 Feb 90 05:46:01 GMT References: <17467@megaron.cs.arizona.edu> Organization: Comp Sci, RMIT, Melbourne, Australia Lines: 70 In article <17467@megaron.cs.arizona.>, debray@cs.arizona.edu (Saumya K. Debray) writes: [someone else wrote in another newsgroup that] :> increment(Variable) :- :> retract(value(Variable, OldValue)), :> NewValue is OldValue + 1, :> assert(value(Variable, NewValue)). [is the way to implement x +:= 1 in Prolog and asked] > Comments? 1. There are three good ways of implementing X +:= 1 in Prolog, depending on what your Prolog has built in (there may be more): X1 is X0+1, % portable plus(X0, 1, X1), % C Prolog, NU Prolog, some others succ(X0, X1) % C Prolog, insists that X0 >= 0. This is perfectly general: any Pascal program using scalar variables can be transliterated to one where Prolog variables represent states of Pascal variables. For example: function gcd(x, y: integer): integer; begin assert((x > 0) and (y > 0)); while x <> y do if x > y then x := x-y else y := y-x; gcd := x end {gcd}; transliterates to gcd(X, Y, Gcd) :- X > 0, Y > 0, gcd_loop(X, Y, Gcd). gcd_loop(X, Y, Gcd) :- ( X =\= Y -> ( X > Y -> X1 is X-Y, gcd_loop(X1, Y, Gcd) ; Y1 is Y-X, gcd_loop(X, Y1, Gcd) ) ; Gcd is X ). I'm not suggesting that this is the best way to write gcd/3 in Prolog, only that the transliteration is entirely mechanical and doesn't involve any asserts or retracts. 2. It's often a good idea to use some other data structure to represent a number. Instead of X1 is X0+1, a good choice may be X1 = [?|X0] (there is often something useful to put in the place of the ?). 3. The code which the anonymous author provided has at least two flaws. (a) If a keyboard interrupt is received at the wrong time, and the program is then aborted, the counter may be destroyed. Don't laugh, don't say it can't happen, I've known cases where it DID happen. The more you hack variables in the data base instead of writing Prolog, the more likely it is. In Quintus Prolog you can write clause(value(Var, N0), true, Ref), N1 is N0+1, begin_critical, erase(Ref), assert(value(Var, N1)), end_critical {note how the arithmetic was done _outside_ the critical region so that overflows and other errors don't leave the critical region unclosed. (b) retract/1 is NOT a determinate predicate. In C Prolog, it can never be sure that it has reached the end of the predicate, so it has to leave a choice point. In Quintus Prolog, retract/1 uses first-argument indexing like everything else, but if first-argument indexing is not enough to spot the determinacy (e.g. if you try to hack an array this way by doing value(array(1,2,1020)) ) then you're still going to get a choice point. There are other problems, but I'll leave them for other commentators.