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 -------
