NICE-ESG-Libs Digest        Tue,  5 Sep 95       Volume 1 : Issue 288 

Today's Topics:
                     fwd: ESG-lib and clone/copy


NICE Eiffel Standards Group -- Library Committee Mailing List To post to list: NICE-ESG-Libs@atlanta.twr.com To send mail to the Chairman of the committee: NICE-ESG-Libs-chair@atlanta.twr.com Administrative matters (sign up, unsubscribe, mail problems, etc): NICE-ESG-Libs-request@atlanta.twr.com
Date: Tue, 5 Sep 95 19:18:36 EDT From: tynor (Steve Tynor) Subject: fwd: ESG-lib and clone/copy To: nice-esg-libs Jacob Gore asked me to forward this to the Library Committee. As a data point, I'll note that the current Tower implementation in 1.5.0 uses Jacob's "Possibility #2" (since possibility #1 is all but guaranteed to trigger class invariant violations). I agree with his suggestion #2 (we should document how `clone' calls `copy'), however, I don't see how thawing (unfreezing?) `clone' solves the problem. `clone' is just a helper function that makes absolutely no use of Current. In c := a.clone(b) a's value is completely unimportant since the semantics of clone are to make a copy of `b'. Polymorphically dispatching clone off of `a' is misleading at best -- error prone at worst. What you probably want is something more like the Tower's (ISE had it too in earlier versions of their kernel): `twin' (which is like `clone' except it clones Current instead of some unrelated function argument). Steve ------- start of forwarded message (RFC 934 encapsulation) ------- >From: "Jacob Gore" To: "Steve Tynor" Subject: Re: ESG-lib and clone/copy Date: Tue, 05 Sep 95 16:58:31 MDT In-Reply-To: <9508281538.aa06264@atlanta.twr.com> X-Nextstep-Mailer: Mynah 0.8bm m68k Steve, Thanks for propagating this to the library committee. The suggestion: 1. Unfreeze `clone.' 2. Document HOW `clone' uses `copy' (the postcondition is not enough). Motivation: Suppose `object1' is implemented in terms of `subobject1,' and `object2' is of the same class as `object1.' How should `copy' in `object2.copy(object1)' be implemented? The correct answer depends on how `clone' is actually implemented (hence it must be documented). Possibility 1: `clone' just allocates space for `object2' and calls `object2.copy(Object1).' Problem with it: No creation has been called, since there is no way for `clone' to know which creation routine to use. Thus, `object2' may not be a valid object at the time it's told to `copy'. Thus, `copy' must behave as a creation routine (no preconditions on `object2,' build it from scratch). Possibility 2: Clone makes `object2' a bitwise shallow copy of `object1,' and then calls `object2.copy(object1).' Problem with it: By the invariant, `object2' is a valid object before it is told to `copy' (since `object1' was valid), but it shares `subobject1' with `object1' instead of having its own subobject (this aliasing problem is NOT caught by the postcondition of `clone'!). Thus, `copy', just in case it had been called from `clone', must break the link to its subobject and create a new subobject. In effect, `copy' must behave as a creation routine. Now, if I understand the motivation for having `copy' in the first place, it is so that `a.copy(b)' can be more efficient than `a := clone(b)'. For objects that are implemented in terms of non-constant subobjects, that cannot happen if `clone' is frozen. We have the added complexity of having separate `clone' and `copy' routines without the benefit of efficiency. If `clone' is not frozen, then the efficiency can be restored by redefining it with a routine that calls a specific creation routine before calling `copy', and then making `copy' a more light-weight routine that assumes a valid AND DISTINCT object (i.e., with no subobjects accidentally aliased to the innards of another object). Jacob - --- Jacob Gore, Eastern NM U. Jacob.Gore@Math.ENMU.Edu | Jacob@ToolCASE.Com ------- end -------