:orphan: ========== Clonable ========== :Author: Dave Abrahams :Author: Joe Groff :Date: 2013-03-21 :Edition: 2 .. warning:: This proposal was rejected. We decided not to introduce a language-level copying mechanism for classes. **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`` 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 { 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. Therefore 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).