mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
I don't know why my machine at home is suddenly being stricter than the one at work, but it found these legitimate formatting mistakes. Swift SVN r13635
148 lines
4.7 KiB
ReStructuredText
148 lines
4.7 KiB
ReStructuredText
:orphan:
|
|
|
|
.. @raise litre.TestsAreMissing
|
|
|
|
==========
|
|
Clonable
|
|
==========
|
|
|
|
:Author: Dave Abrahams
|
|
:Author: Joe Groff
|
|
:Date: 2013-03-21
|
|
:Edition: 2
|
|
|
|
**Abstract:** to better support the creation of value types, we
|
|
propose a “magic” ``Clonable`` protocol and an annotation for describing
|
|
which instance variables should be cloned when a type is copied. This
|
|
proposal **augments revision 1** of the Clonable proposal with our
|
|
rationale for dropping our support for ``val`` and ``ref``, a
|
|
description of the programming model for generics, and a brief
|
|
discussion of equality. It is **otherwise unchanged**.
|
|
|
|
Rationale
|
|
=========
|
|
|
|
By eliminating ``val``, we lose the easy creation of
|
|
runtime-polymorphic value types. Instead of merely writing::
|
|
|
|
val x : MyClass
|
|
|
|
one has to engage in some kind of wrapping and forwarding::
|
|
|
|
struct MyClassVal {
|
|
var [clone] value : MyClass
|
|
|
|
constructor(x : A, y : B) {
|
|
value = new MyClass(x, y)
|
|
}
|
|
|
|
func someFunction(z : C) -> D {
|
|
return value.someFunction(z)
|
|
}
|
|
|
|
// ...etc...
|
|
}
|
|
|
|
Although such wrapping is awful, this is not the only place where one
|
|
would want to do it. Therefore, some kind of ability to forward an
|
|
entire interface wholesale could be added as a separate extension
|
|
(getter/setter for ``This``?), which would solve more problems. Then it
|
|
would be easy enough to write the wrapper as a generic struct and
|
|
``Val<T>`` would be a reality.
|
|
|
|
By eliminating ``ref``, we lose the easy creation of references to
|
|
value types. However, among those who prefer programming with values,
|
|
having an explicit step for dereferencing might make more sense, so we
|
|
could use this generic class:
|
|
|
|
class Reference<T> { value : T }
|
|
|
|
If explicit dereferencing isn't desired, there's always manual (or
|
|
automatic, if we add that feature) forwarding.
|
|
|
|
By dropping ``val`` we also lose some terseness aggregating ``class``
|
|
contents into ``struct``\ s. However, since ``ref`` is being dropped
|
|
there's less call for a symmetric ``val``. The extra “cruft” that
|
|
``[clone]`` adds actually seems appropriate when viewed as a special
|
|
bridge for ``class`` types, and less like a penalty against value
|
|
types.
|
|
|
|
Generics
|
|
========
|
|
|
|
There is actually a straightforward programming model for generics.
|
|
If you want to design a generic component where a type parameter ``T``
|
|
binds to both ``class``\ es and non-``class`` types, you can view
|
|
``T`` as a value type where—as with C pointers—the value is the
|
|
reference rather than the object being referred to.
|
|
|
|
Of course, if ``T`` is only supposed to bind to ``class``\ es, a
|
|
different programming model may work just as well.
|
|
|
|
Implications for Equality
|
|
=========================
|
|
|
|
We think the programming model suggested for generics has some pretty
|
|
strong implications for equality of ``class``\ es: ``a == b`` must
|
|
return true iff ``a`` and ``b`` refer to the same object.
|
|
|
|
Details *(unchanged from Revision 1)*
|
|
=====================================
|
|
|
|
When a type with reference semantics ``R`` is to be used as a part of
|
|
(versus merely being referred-to-by) a type with value semantics ``V``,
|
|
a new annotation, ``[clone]`` can be used to indicate that the ``R``
|
|
instance variable should be ``clone()``\ d when ``V`` is copied.
|
|
|
|
A ``class`` can be ``clone()``\ d when it implements the built-in ``Clonable``
|
|
protocol::
|
|
|
|
protocol Clonable {
|
|
func clone() -> Self { /* see below */ }
|
|
}
|
|
|
|
The implementation of ``clone()`` (which will be generated by the
|
|
compiler and typically never overridden) performs a primitive copy of
|
|
all ordinary instance variables, and a ``clone()`` of all instance
|
|
variables marked ``[clone]``::
|
|
|
|
class FooValue : Clonable {}
|
|
|
|
class Bar {}
|
|
|
|
class Foo : Clonable {
|
|
var count : Int
|
|
var [clone] myValue : FooValue
|
|
var somethingIJustReferTo : Bar
|
|
}
|
|
|
|
struct Baz {
|
|
var [clone] partOfMyValue : Foo
|
|
var anotherPart : Int
|
|
var somethingIJustReferTo : Bar
|
|
}
|
|
|
|
When a ``Baz`` is copied by any of the “big three” operations (variable
|
|
initialization, assignment, or function argument passing), even as
|
|
part of a larger ``struct``, its ``[clone]`` member is ``clone()``\ d.
|
|
Because ``Foo`` itself has a ``[clone]`` member, that is ``clone()``\ d
|
|
also. Therfore copying a ``Baz`` object ``clone()``\ s a ``Foo`` and
|
|
``clone()``\ ing a ``Foo`` ``clone()``\ s a ``FooValue``.
|
|
|
|
All ``struct``\ s are ``Clonable`` by default, with ``clone()`` delivering
|
|
ordinary copy semantics. Therefore, ::
|
|
|
|
var x : Baz
|
|
var y = x.clone()
|
|
|
|
is equivalent to ::
|
|
|
|
var x : Baz
|
|
var y = x
|
|
|
|
Note that ``Clonable`` is the first protocol with a default
|
|
implementation that can't currently be written in the standard library
|
|
(though arguably we'd like to add the capability to write that
|
|
implementation).
|
|
|