Re: [swift-users] Re-initializing lazy vars
Oops! forgot to add example code for resetting with non-optional public var : public struct TestStruct { private var _description: String? public var description: String { get { return _description ?? "" } set { _description = newValue } } mutating func resetDescription() { _description = nil } } Joanna -- Joanna Carter Carter Consulting ___ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users
Re: [swift-users] Re-initializing lazy vars
> It just seems so obvious to create-if-nil, and makes it nice to reset stuff > that should be re-created. In my case, after my NSURLSession gets > invalidated, I wanted to set the property to nil, and next time a session was > needed, it would just get created. The only thing I would query with the whole concept of resetting an implicitly unwrapped optional var is, with a simple example struct : public struct TestStruct { private var _description: String? public var description: String! { get { return _description ?? "" } set { _description = newValue } } } … test code would be : { var test = TestStruct() test.description = nil let str: String = test.description } The idea of setting a var to nil and then getting a valid object back seems a bit anachronistic. I think I would rather add an explicit "reset" method. Joanna -- Joanna Carter Carter Consulting ___ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users
Re: [swift-users] Can't implement generic subscript in protocol
The answer to the segmentation fault is that I was trying to assign the subscript "method" to a closure var of the same signature. It would seem Swift doesn't allow this :-( Joanna -- Joanna Carter Carter Consulting ___ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users
Re: [swift-users] Can't implement generic subscript in protocol
Xcode Version 9.0 (9A235) Hmmm. I'm now getting a segmentation fault : 11 on a constructor when trying to implement type erasure : protocol DataProvider { associatedtype ItemType subscript(index: Int) -> ItemType { get } } class _AnyDataProviderBoxBase: DataProvider { subscript(index: Int) -> itemType { fatalError() } } class _AnyDataProviderBox: _AnyDataProviderBoxBase { private let _subscript: (_ index: Int) -> providerType.ItemType init(_ base: providerType) // segmentation fault : 11 { _subscript = base.subscript } override subscript(index: Int) -> providerType.ItemType { return _subscript(index) } } final class AnyDataProvider: DataProvider { private let box: _AnyDataProviderBox init(_ base: providerType) { self.box = _AnyDataProviderBox(base) } subscript(index: Int) -> providerType.ItemType { return box[index] } } Joanna -- Joanna Carter Carter Consulting ___ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users
[swift-users] Can't implement generic subscript in protocol
Greetings Now we've got generic subscripts, I thought I'd play… protocol DataProvider { subscript(index: Int) -> itemType { get } } class Test : DataProvider // error : Type 'Test' does not conform to protocol 'DataProvider' { subscript(index: Int) -> String { return "Fred" } } Simple questions: 1. why does this not compile? 2. should it? 3. is there a workaround without declaring an associated type in the protocol? Joanna -- Joanna Carter Carter Consulting ___ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users
Re: [swift-users] Can you use @autoclosure in a setter?
Greetings > I have a class with a property that needs to be really *really* lazy. So > lazy, in fact, that when you assign to that property, the class actually > stores a closure of what you assigned, which is only evaluated if and when > you actually attempt to read the property. > > Simplified: > > class Foo { > private var valueSource: () -> Bar > private var valueCache: Bar? > > init(_ v: @escaping @autoclosure () -> Bar) { > valueSource = v > } > > var value: Bar { > get { > if let v = valueCache { return v } > let w = valueSource() > valueCache = w > return w > } > set { > /* ??? */ > } > } > > // I want this function's logic to go in the setter above > func setValue(_ v: @escaping @autoclosure () -> Bar) { > valueSource = v > valueCache = nil > } > } > > The goal is to be able to write things like “someFoo.value = bar1 / bar2” (or > even more complex expressions) and not evaluate them until/unless the result > is actually needed. > > Currently I am using “someFoo.setValue( bar1 / bar2 )”, which is not nearly > as ergonomic as the assignment syntax. So, is there a way to make this work? Unless I'm missing something, can't you just call the closure that you passed to the init ? Or do you want to use a different closure ? You could always have a var that is a tuple, with one part being the value and the other the closure. Joanna -- Joanna Carter Carter Consulting ___ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users
Re: [swift-users] CustomStringConvertible?
Greetings > Thanks for your reply, Rien. I just tried this again, and now it seems that > either is acceptable. Seems a little weird, but I guess I’d rather have more > flexibility than less. > class GPS : Powerable, CustomStringConvertible { > // Either of these work > //var description: String { > //return "I am a GPS" > //} > var description:String = "I am a GPS" You can also implement description as a let, since there is no intention to modify it : class GPS : Powerable, CustomStringConvertible { let description = "I am a GPS" … } Joanna -- Joanna Carter Carter Consulting ___ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users
Re: [swift-users] Still can't derive from a generic class
Hi Joe Thanks for your input on this. > This is likely due to the runtime not handling cycles properly in type > metadata initialization—a subclass T needs its base class metadata for > BaseObject, which in turn needs the metadata for T to instantiate the > generic type. This is something we plan to fix next year since it requires > runtime ABI changes. Hmmm. I'm finding this really frustrating, waiting for features that I have been using for years, in another popular language (C#), to see the light of day. Maybe application programmers are happy with Swift so far but, when it comes to my speciality of designing frameworks, I am constantly finding myself blocked by lack of metadata APIs :-( I am talking about a couple of frameworks that underpin one of the largest business management systems in Europe, for which the client is asking a MacOS/iOS version. > Would a protocol-based approach suffice? `Self` in a protocol extension would > give you access to the concrete type in a similar way: > > protocol Base: AnyObject { > var properties: [PartialKeyPath : AnyProperty] { get } > } > > extension Base { > func value(for keyPath: KeyPath) -> T? > { >guard let property = properties[keyPath] else >{ > return nil >} > >return property.getValue() > } > > /*etc.*/ > } > > class Test: Base { > let properties = [\Test.name: Property()] > > var name: String { >get { return value(for: \.name) } >set { set(value: newValue, for: \.name) } > } > } At first glance, I thought, Yes! But then I realised that this then requires a final class to cater for the use of Self in the protocol; something that would be a blocker for the class hierarchies that most users of the framework would want to create on top of the Base functionality. I suppose I could look at using protocol-oriented composition but trying to avoid associated types in protocols in frameworks that use generics extensively is akin to hitting yourself repeatedly on the head with a hammer ;-) And I really don't want to have to keep on repeating type-erasure boilerplate code to achieve that. I think the realisation that I may well lose the chance of a pretty massive contract and that my client will lose an important business opportunity is finally dawning :-( Joanna -- Joanna Carter Carter Consulting ___ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users
Re: [swift-users] Still can't derive from a generic class
Hi Kenny > Just curious, and because I have a distinct lack of imagination: can you > share a concrete case of this pattern? class BaseObject { private let properties: [PartialKeyPath : AnyProperty] init(properties: [PartialKeyPath : AnyProperty]) { self.properties = properties } func value(for keyPath: KeyPath) -> valueType? { guard let property = properties[keyPath] else { return nil } return property.getValue() } func set(value: valueType?, for keyPath: KeyPath ) { guard let property = properties[keyPath] else { return } property.set(value: value) } } class Test : BaseObject { var name: String? { get { return value(for: \.name)! } set { set(value: newValue, for: \.name) } } var number: Int? { get { return value(for: \.number)! } set { set(value: newValue, for: \.number) } } init() { super.init(properties: [\Test.name : Property(), \Test.number : Property()]) } } Without the generic rootType parameter, all the getter and setter methods need an explicit mention of the derived class for the keypath : class Test : BaseObject { var name: String? { get { return value(for: \Test.name)! } set { set(value: newValue, for: \Test.name) } } … } It was all so simple in C# :( Joanna -- Joanna Carter Carter Consulting ___ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users
Re: [swift-users] Still can't derive from a generic class
Hi Jon > Le 29 août 2017 à 19:20, Jon Shiera écrit : > > This works fine for me in a playground in the latest Xcode 9 beta: > > class Test { } > > class Base { } > > class Sub: Base { } > > let sub = Sub() That may well work but what I want is to be able to do is simpler than that : class Base { } class Test : Base { } let test = Test() Joanna -- Joanna Carter Carter Consulting ___ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users
[swift-users] Still can't derive from a generic class
Hi I would have hoped by now that it should be possible to do : class BaseObject { } class Test : BaseObject { } All compiles well but, at runtime, when calling let test = Test(), I get a "EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)" error. This is something I have been able to do in C# for many a year. Why oh why can I still not do it in Swift ? Joanna -- Joanna Carter Carter Consulting ___ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users
Re: [swift-users] Question with calling a method which returns `Self` on super
I really must do more research before making accusations ;-) > Which still leaves my question of why I have to reimplement the default > copy(other:) method from the protocol's extension in the base class ??? Apparently, the answer is to remove the declaration of the copy(other:) method from the protocol itself and to leave the default implementation in the extension ! So I now end up with : protocol Copyable { init(other: Self) } extension Copyable { func copy() -> Self { return type(of: self).init(other: self) } } class Shape : Copyable { var color: NSColor init(color: NSColor) { self.color = color } required init(other: Shape) { color = other.color } } … and all is well with the world :-) Mind you, the compiler error messages were hardly helpful to diagnosing this particular problem :-( Joanna -- Joanna Carter Carter Consulting ___ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users
Re: [swift-users] Question with calling a method which returns `Self` on super
> here is the scenario, I want to implement a Copying protocol which can be > used homogeneously > > protocol Copying { > func copy() -> Self > } > > Because this protocol contains neither associated-type-requirements or > self-requirements(requiring a method returning Self is different), it can > surely be used homogeneously. > > let objects: [Copying] = > for copyable in objects { > . > } But Copying does contain a Self requirement. It is used the result of the copy() method Here is how I implement Copying : protocol Copyable { func copy() -> Self init(other: Self) } // This extension provides a default implementation extension Copyable { func copy() -> Self { return type(of: self).init(other: self) } } implementing Copyable on a struct is simple : struct Struct : Copyable { var value: String init(value: String) { self.value = value } init(other: Struct) { value = other.value } } But implementing it on a class is slightly more troublesome. class Shape : Copyable { var color: NSColor init(color: NSColor) { self.color = color } } At this stage, the compiler (obviously) screams that Copyable is not implemented but the first "error" it notices it marks as being on the default implementation in the extension: Method 'copy()' in non-final class 'Shape' must return `Self` to conform to protocol 'Copyable' Marking this error on the extension method, which obviously does exactly what the error says is missing ??? Implementing the copy() method in Shape kills this error message but leaves me wondering why I have to now repeat the exact same code in the implementing method that I wrote in the default method in the protocol extension ; something that the compiler is completely ignoring. Implementing the protocol with a struct takes account of the default method but with a class ignores it. This smells remarkably like a bug ! Nonetheless, I now end up with the following code, complete with duplicate copy() method : class Shape : Copyable { var color: NSColor func copy() -> Self { return type(of: self).init(other: self) } init(color: NSColor) { self.color = color } required init(other: Shape) { color = other.color } } Then I can go on to declare subclasses : class Circle : Shape { var radius: Double = 0.0 init(color: NSColor, radius: Double) { super.init(color: color) self.radius = radius } required init(other: Shape) { super.init(other: other) if let other = other as? Circle { radius = other.radius } } } class Square : Shape { var side: Double = 0.0 init(color: NSColor, side: Double) { super.init(color: color) self.side = side } required init(other: Shape) { super.init(other: other) if let other = other as? Square { side = other.side } } } And, the, if I create an extension to Array : extension Array where Element : Copyable { func copy() -> Array { var result = [Element]() self.forEach { result.append($0.copy()) } return result } } I can then use the following code to create an array of Shapes but, obviously not of Copyable, due to its restrictions on the Self requirements on the protocol. { let shapes = [Circle(color: .black, radius: 5.0), Square(color: .black, side: 5.0)] let copies = shapes.copy() … } Thus, another possible solution to your problem is to declare the required init(other: Self) in the protocol. Which still leaves my question of why I have to reimplement the default copy(other:) method from the protocol's extension in the base class ??? Joanna -- Joanna Carter Carter Consulting ___ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users
Re: [swift-users] Constraining the conforming type of a protocol
IMHO, there is a very subtle difference between : protocol Toggling : Equatable { … } extension Toggling { … } … and : protocol Toggling { … } extension Toggling where Self : Equatable { … } The first says that any type that implements Toggling also implements Equatable. The second says that an implementing type can be Toggling without necessarily having to be Equatable. Either way around, you are providing a default implementation for toggled() and toggle(), but, with the first version, toggled requires that Self is also Equatable. Therefore, you are saying that, because the default implementation of Toggling demands that Self is Equatable, you have to also state that everything that is Toggling is also Equatable. Since : protocol Toggling where Self : Equatable … is functionally identical to : protocol Toggling : Equatable … why would you want to use a more verbose way of saying the same thing ? I would venture to suggest that there is no need for the longer syntax and that your bug report is not necessary :-) Joanna -- Joanna Carter Carter Consulting ___ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users
Re: [swift-users] Simultaneous accesses, but modification requires exclusive access
> Background: > Just a little background into what I was trying to achieve (I could be wrong): > > - I have a set of classes C1, C2, C3 which has a lot of common code > > - I would like to build something that can be reused without exposing the > implementation details. (I can subclass but would expose the underlying > functions, same applies to protocol as well) > > - I thought I would build helper class / struct which would contain the > common code. I can make the helper a private property so that the functions > wouldn’t be exposed to the instances of C1, C2, C3. In order to achieve that > I had to pass some functions from C1 into the Helper struct. > > Question 2: > - Is this problem (hiding implementation details) normally tackled using > Helper class (or struct) or is there a more better approach ? Usually, as long as the protocol doesn't reference self or have associated types, I would use a protocol as the "abstract" type and then you could implement it in either a class or struct. Joanna -- Joanna Carter Carter Consulting ___ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users
[swift-users] Swift 4 emulating Decoder behaviour
Greetings I notice that, with Swift 4, I can decode an object like this : • let retrievedSpot = try decoder.decode(ParkingSpot.self, from: retrievedData) And that will return a ParkingSpot, as expected, into retrievedSpot. However, I thought I would try the same technique with one of my pet projects… I have a protocol and an implementing struct : • public protocol PropertyProtocol • { • static var propertyType: Any.Type { get } • • var untypedValue: Any? { get } • } • • public struct Property : PropertyProtocol • { • public static var propertyType: Any.Type • { • return valueT.self • } • • public var untypedValue: Any? • { • return value • } • • public var value = valueT() • } Now, I want to be able to use a "factory" method to create an instance of Property, bound to its parameter type. So, I followed the same principal as Decoder : • struct PropertyFactory • { • static func createProperty(_ type: T.Type) -> PropertyProtocol where T : DefaultValueProvider • { • return type.createProperty() • } • } DefaultValueProvider is defined as follows and String is extended to conform to it : • public protocol DefaultValueProvider • { • init() • } • • extension String : DefaultValueProvider { } Now, this works fine if I pass a known type : • let pproperty = PropertyFactory.createProperty(String.self) But, if I hold the type to be passed in in an Any.Type or DefaultValueProvider.Type variable, then doing this : • let type: Any.Type = String.self • • if let propertyType = type as? DefaultValueProvider.Type • { • let p = PropertyFactory.createProperty(propertyType) • • … Fails to compile with the message : Cannot invoke 'createProperty' with an argument list of type '(DefaultValueProvider.Type)' Likewise Decoder.decode(…) will not accept storing the type in an Any.Type or Decodable.Type variable. I find this odd and perplexing. Is this a known issue or has nobody yet realised that this could be useful ? Joanna -- Joanna Carter Carter Consulting ___ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users