[swift-evolution] Proposal: 'selfless' keyword for refactoring duplicate code from initialisers

Ross O'Brien narrativium+swift at gmail.com
Tue Dec 15 17:59:54 CST 2015


Hi all,

I'm a new member of the list, so apologies if this is a duplicate of an
existing idea or if there's already a way to do this in Swift 2.1 that I've
missed.

In Objective C, and C-like languages, an initialiser function represents a
stage after allocation of memory where properties are given values. In
Swift, init appears to precede (or overlap with) allocation. The benefit of
this is that for type-safety reasons, all properties of a type (or new
properties of a derived type) can be verified as having values. The
disadvantage, and one of the stumbling blocks for those who learned
Objective-C, is that until all the properties have values, the instance
does not exist and instance functions cannot be called.

There's an invisible threshold in Swift init() functions marking this
transition. In derived classes it's the point where super.init() is called
- after the derived type has provided initial values, but before any type
functions can be called.

Some types have multiple initialisers, and may be duplicating a lot of code
in those distinct inits before they cross the threshold. This code can't be
refactored into an instance function because the instance doesn't exist
yet. The instance function may not even require the use of any properties
of the type.

If the compiler can read an init function and its varied control flow and
determine a threshold where all properties have values, presumably it can
read the code of any function called before that threshold, determine which
properties they read and which they assign to, and provide a warning if a
path assigns to a constant a second time, etc.. But this isn't currently
happening.

I'm guessing there are multiple contributing factors for this: the
combinatorial explosion of possible control flow paths with functions
(particularly if they're recursive); the possibility that the function
calls are used by the compiler to mark the end of a control flow path, by
which point it can determine whether everything has a value; the function
genuinely can't exist without allocation. I don't know the reasons but I'd
be interested to learn them.

I'm proposing the keyword 'selfless' for a function which could be called
before the threshold. It either only uses local properties or properties
belonging to the type - never to the 'super' type (in the case of a derived
class). It can't call any instance functions which aren't themselves
selfless.

Example of use:
class FooView : UIView
{
    var property : Int

    init()
    {
        initialiseProperty()
        super.init()
    }

    init(frame:CGRect)
    {
        initialiseProperty()
        super.init(frame)
    }

    selfless func initialiseProperty()
    {
        property = 4
    }
}

Is this something of interest?

Regards,
Ross O'Brien
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151215/83670940/attachment.html>


More information about the swift-evolution mailing list