I agree that the use of setarg is ugly, but sometimes you really do need something like it. There are a couple of solutions. 1) Currently our pattern for something changeable is to declare a struct, and write accessors like <struct>_set_<field> that in their simplest form just call setarg. e.g. s_set_f(Struct,Val) :- setarg(f of s, Struct, changeable(Val)). % use changeable to avoid sharing issues % mentioned in setarg/3 help page We could have a different pattern, that always had a variable with a tentative value. The tentative value would be logically updated and then set with tent_set. s_set_f(S,Val) :- S tent_get SS, update_struct(s,[f:Val],SS,SS1), S tent_set SS1. This adds some nice features, like you can do better data-driven stuff by waking on change of tentative value. This is a slightly different use of the repair library, and might necessitate things like specific copy/unify handlers depending on the functor of the tentative value. I think it solves the referential integrity issue though. This does not help in the case of large arrays or hash tables. In that case, not having setarg would be too expensive, trading off an O(1) (single element update) operation with an O(N) operation of copying the whole array, or O(logN) set and get as in tree implementations of arrays. In the case of very large structures we still need something like setarg. My preferred solution here would be a differently tagged kind of compound term. You would be able to set properties of such compound terms, such as whether it can be modified, or how the system should behave when you try to copy the term. This would not solve the referential transparency problem but would localise the setarg pattern to just those places where it is needed, and where something is explicitly created as modifiable. On meta-called do-loops. In my opinion, I believe the metacall implementation if do/2 ought simply to raise an error. The reason are: 1) There should always be away of avoiding such a meta-call, 2) We don't want to encourage people to construct and call do loops on the fly and then complain about their performance 3) All over the system we have the property that meta-called behavior is identical to compiled behavior, (with a roughly constant meta-call overhead). Here the overhead, varies dramatically and unexpectedly with the supplied data, and the behaviour is not identical if you are using ==/2 or setarg/3, and maybe other non-logical things I have not thought of. I would say if eclipse supports metacall of do/2, these differences in behaviour have to be carefully documented, but this seems to me a waste of time, much better to document that a metacall of do/2 raises an error. For compatibility call_do/2 might be defined for people that rely on the meta-called behaviour, although I doubt anybody really requires this. Stefano -----Original Message----- From: Joachim Schimpf [mailto:j.schimpf@icparc.ic.ac.uk] Sent: 29 May 2003 15:23 To: josh singer Cc: 'eclipse-bugs@icparc.ic.ac.uk'; Stefano Novello; Mark Wallace Subject: Re: Meta-called do loops and setarg Hi Josh, in brief, the solution is to remove setarg/3 from the language. We can put this on the plan for a future release. Unfortunately, it is very difficult to reconcile constant demands for impure, low-level features with an aspiration to keep the language semantics simple and clean. When you use setarg/3, you destroy the referential transparency property and simple notion of identity that you otherwise have in logic programming (the man page for setarg/3 tries to say that in its own clumsy ways). In your example, this 'feature' of setarg/3 allows you to construct a program that behaves differently, depending on the time (compile vs call time) at which the loop is translated into its recursive equivalent: In query 1, the effective loop is, as written, (count(I, 1, 4), param(X) do setarg(1, X, I) In query 2, X is already substituted, and the effective loop is (count(I, 1, 4), param(p(0, Y)) do setarg(1, p(0, Y), I)) which is equivalent to (count(I, 1, 4), param(Y) do setarg(1, p(0, Y), I) and explains the observed behaviour. Since setarg/3 breaks such a fundamental property, loops are surely not the only context in which you can construct weird behaviours. It is therefore quite important to limit and localise the use of setarg/3 as much as possible, while we still support it. Cheers, --Joachim josh singer wrote: > > Hi folks, > > Look at the following example, run on v 5.6 #28, Linux. With each iteration > of the do loop the first param of X gets set to a higher number. Fine. > > But if we meta-call the do loop, the setargs appear not to have any effect. > Seems like a bug. The bug has been there at least since 5.4. > > Wierdly, if you instantiate Y first, the bug goes away. > > cheers, > > josh > > ---- > > ECLiPSe Constraint Logic Programming System [kernel] > Copyright Imperial College London and ICL > Certain libraries copyright Parc Technologies Ltd > GMP library copyright Free Software Foundation > Version 5.6 #28, Mon Apr 21 00:13 2003 > [eclipse 1]: X = p(0, Y), (count(I, 1, 4), param(X) do setarg(1, X, I)). > > Y = Y > X = p(4, Y) > I = I > Yes (0.00s cpu) > [eclipse 2]: X = p(0, Y), call((count(I, 1, 4), param(X) do setarg(1, X, > I))). > > Y = Y > X = p(0, Y) > I = I > Yes (0.00s cpu) > [eclipse 3]: -- Joachim Schimpf / phone: +44 20 7594 8187 IC-Parc / mailto:J.Schimpf@imperial.ac.uk Imperial College London / http://www.icparc.ic.ac.uk/eclipseReceived on Thu May 29 19:31:03 2003
This archive was generated by hypermail 2.1.8 : Wed 16 Nov 2005 06:08:22 PM GMT GMT