[swift-evolution] [Proposal] Property behaviors

davesweeris at mac.com davesweeris at mac.com
Mon Jan 18 21:57:24 CST 2016


Can we use “#” or something other than “.”, both to make it clear we’re referencing a behavior rather than a property, and so that we can avoid naming collisions when x has a property “lazy” and is declared with the lazy behavior?
x.lazy.clear() // a property named “lazy” which has a clear() method
x#lazy.clear() // the behavior named “lazy”
I kinda like “#” (or whatever) for declaring them, too:
var x #(lazy) = 6



I’m a definite +1 on the concepts behind your proposal, but there are really two distinct things going on here: behaviors that mess with the type, and those that don’t. I mean, if you define your Lazy “behavior” like this:
struct Lazy<T> {
    private let closure: () -> T
    private var storage: T? = nil
    var value: T {
	mutating get {
	    if storage == nil { storage = closure() }
            return storage!
	}
	mutating set {
	    storage = newValue
	}
    }
    init(_ closure: () -> T) {
        self.closure = closure
    }
}

then the only difference between
lazy var foo = {
    return 4
}
and
var foo = Lazy {
    return 4
}
is that in the former case, the property is implicitly accessed:
var bar = foo
foo = 10
and in the latter, we have to access it explicitly:
var bar = foo.value
foo.value = 10

If we expose the mechanism currently used by `T!` to convert between itself and T, and allow structs, enums, classes, and maybe even protocols to provide type accessors as well as property accessors, Lazy, Optional, and ImplicitlyUnwrappedOptional could then be implemented like this:
struct Lazy<T> {
    // or whatever the magic syntax is
    mutating static get { () -> T in // $0 is an instance of Lazy<T>
	if $0.value == nil { $0.value = $0.closure() }
	return $0.value!
    }
    mutating static set { (newValue:T) in $0.value = newValue }

    private let closure: () -> T
    private var value: T? = nil
    init(_ closure: () -> T) {
        self.value = closure
    }
}
enum Optional<T> {
    // no need for a custom getter, since you have to manually unwrap optionals
    mutating static set { (newValue: T) in $0 = .Some(newValue) } // $0 is an instance of Optional<T>
    mutating static set { () in $0 = .None }

    case None
    case Some(T)
    init() { self = .None }
    init(nilLiteral: ()) { self = .None }
    init(_ value: T) { self = .Some(value) }
}
enum ImplicitlyUnwrappedOptional<T> {
    mutating static get { () -> T in // $0 is an instance of ImplicitlyUnwrappedOptional<T>
        switch $0 {
        case .None: fatalError("Error unwrapping ImplicitlyUnwrappedOptional")
        case .Some(let value): return value
        }
    }
    mutating static set { (newValue: T) in $0 = .Some(newValue) }
    mutating static set { () in $0 = .None }

    case None
    case Some(T)
    init() { self = .None }
    init(nilLiteral: ()) { self = .None }
    init(_ value: T) { self = .Some(value) }
}

One of the stated goals of Swift 3 is to move stuff out of the core language and into the standard library, right? Well, this would get rid of all the “magic” behind Lazy, Optionals, and ImplicitlyUnwrappedOptionals and it’d let us implement our own type-related custom behaviors. It’s a win-win!



Thoughts?

- Dave Sweeris

> On Jan 13, 2016, at 08:43, Joe Groff via swift-evolution <swift-evolution at swift.org> wrote:
> 
> Yes. I'm working on a revision I hope to post soon.
> 
> -Joe
> 
>> On Jan 13, 2016, at 7:36 AM, Wallacy <wallacyf at gmail.com <mailto:wallacyf at gmail.com>> wrote:
>> 
>> Just to clarify a little, this proposal is (will be) addressed to 3.0?
>> 
>> Em qui, 17 de dez de 2015 às 15:41, Joe Groff via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> escreveu:
>> Hi everyone. Chris stole my thunder already—yeah, I've been working on a design for allowing properties to be extended with user-defined delegates^W behaviors. Here's a draft proposal that I'd like to open up for broader discussion. Thanks for taking a look!
>> 
>> -Joe
>> 
>> https://gist.github.com/jckarter/f3d392cf183c6b2b2ac3 <https://gist.github.com/jckarter/f3d392cf183c6b2b2ac3>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160118/824c6fe2/attachment.html>


More information about the swift-evolution mailing list