Any ideas why MyStack doesn't conform to ProtoStack? - swift

I have put together what should have been a simple piece of sample in an Xcode 8β2 playground. Unfortunately, I can't see why the struct does not conform to the protocol. I'm sure it's something very simple but can't, for the life of me, see it.
protocol ProtoStack {
associatedtype ItemType
func push(item: ItemType)
func pop() -> ItemType
func isEmpty() -> Bool
func size() -> Int
}
struct MyStack: ProtoStack {
var contents = [Int]()
typealias ItemType = Int
mutating func push(item: Int) { contents.append(item) }
mutating func pop() -> Int { return contents.popLast()! }
func isEmpty() -> Bool { return contents.count == 0 }
func size() -> Int { return contents.count }
}

In order to conform to your ProtoStack protocol as it's currently written, your push and pop methods in your MyStack can't be mutating, as you cannot satisfy a non-mutating protocol requirement with a mutating struct/enum method. Therefore if you want these methods to be mutating, then you also need to mark them in the protocol as being so.
As the Swift language guide says (emphasis mine):
If you define a protocol instance method requirement that is intended to mutate instances of any type that adopts the protocol, mark the method with the mutating keyword as part of the protocol’s definition. This enables structures and enumerations to adopt the protocol and satisfy that method requirement.
A mutating method in a protocol requirement can either be satisfied by a mutating1 instance method in a value type (e.g a struct or enum) or a regular instance method in a class, as class instances can be mutated freely.
1. A mutating protocol requirement can also be satisfied by a non-mutating method in a value type, as this doesn't break the contract with the protocol (nothing depends on a mutation actually taking place within that method).

Related

Swift protocol conformance when returning a generic

Here's an example:
protocol Feed {
func items<T>() -> [T]? where T: FeedItem
}
protocol FeedItem {}
class FeedModel: Feed, Decodable {
func items<T>() -> [T]? where T : FeedItem {
return [FeedItemModel]() // Error: Cannot convert return expression of type '[FeedItemModel]' to return type '[T]?'
}
}
class FeedItemModel: FeedItem, Decodable {}
Why does it:
A) try to convert to T when T is a generic, not a type?
B) does not recognize FeedItemModel as conforming to FeedItem?
func items<T>() -> [T]? where T : FeedItem
This says that the caller can define T to be whatever they want, as long as T conforms to FeedItemModel, and this function will return an optional array of those.
FeedItemModel is something that conforms to FeedItem, but it is not promised to be the type T that the caller requested.
As an example, consider:
class OtherModel: FeedItem {}
According to your function signature, I can do this:
let ms: [OtherModel]? = FeedModel().items()
But your function won't then return [OtherModel]? to me. I suspect you don't actually mean this to be generic. I expect you mean:
func items() -> [FeedItemModel]?
or possibly
func items() -> [FeedItem]?
(Though I would think very hard before doing the latter one and make sure that the protocol existential is really doing useful work here.)
A)
T is a type, a homogenous concrete type specified at runtime.
Imaging T is class Foo : FeedItem it's obvious that FeedItemModel cannot be converted to Foo
B)
FeedItemModel is recognized as conforming to FeedItem but this is irrelevant.
It's often a mix-up of generics and protocols. Generic types are not covariant. If you need covariant types use an associated type.
Either you can ignore generics because because it only applies to that one function and it isn't needed since directly saying that the return type is [FeedItem]? yields the same result
protocol Feed {
func items() -> [FeedItem]?
}
class FeedModel: Feed, Decodable {
func items() -> [FeedItem]? {
return [OtherModel]()
}
}
If you on the other hand want a generic protocol then you should use a associated type
protocol Feed2 {
associatedtype T: FeedItem
func items() -> [T]?
}
class FeedModel2: Feed2, Decodable {
typealias T = FeedItemModel
func items() -> [T]? {
return [FeedItemModel]()
}
}

Swift protocol with associated type and shadow type erasure

I need to pass an object which implements a protocol with associated type into a method, which accepts a protocol. This is not possible in Swift (up to the latest Swift 5) so I use type erasure with a shadow protocol based on this blog.
protocol ShadowA {
func test(data: Any) -> String
}
extension ShadowA {
func test(data: Any) -> String {
return "shadow"
}
}
protocol A: ShadowA {
associatedtype AT
func test(data: AT) -> String
}
class SpecificA: A {
typealias AT = Int
func test(data: Int) -> String {
return "specific"
}
}
Problem is that when I pass the object into the method then the "shadow's default implementation" is called instead of the "generic" one's. You can check the playground to see what is happening.
Is there something wrong or this use case is not possible in Swift at all?
This dynamic Dispatch and direct dispatch Magic for more explain about that check this swift-method-dispatch
Dynamic dispatch is the process of selecting which implementation of a
polymorphic operation (method or function) to call at run time.
Any method that implemented in protocol extension is Direct dispatched
i will explain more
because ShadowA is protocol and have default implementation in extension so compiler mind have this hint "Any class can adopt to this protocol without implement this method because it have default implementation"
Direct Dispatch
So at this Line What compiler know about test(data:Any) from item and because item is protocol with default implementation so it direct it to call direct default implementation
return "in method: \(item.test(data: 0))"
func passedIntoMethod(item: ShadowA) -> String {
return "in method: \(item.test(data: 0))"
}
Also At this line
let a2: ShadowA = SpecificA() // becuse compiler know only about a2 at this line that it is Protocol so it direct dispatch it
print(a2.test(data: 0))
Dynamic Dispatch
Here compiler know that a1 is concreate type so it call test Method that implemented inside it . if not implemented then it will call default implementation
let a1 = SpecificA()
print(a1.test(data: 0))

Swift: Any Kind of sequence as a function parameter

I have created my custom sequence type and I want the function to accept any kind of sequence as a parameter. (I want to use both sets, and my sequence types on it)
Something like this:
private func _addToCurrentTileset(tilesToAdd tiles: SequenceType)
Is there any way how I can do it?
It seems relatively straightforward, but I can't figure it out somehow. Swift toolchain tells me:
Protocol 'SequenceType' can only be used as a generic constraint because it has Self or associated type requirements, and I don't know how to create a protocol that will conform to SequenceType and the Self requirement from it.
I can eliminate the associatedType requirement with, but not Self:
protocol EnumerableTileSequence: SequenceType {
associatedtype GeneratorType = geoBingAnCore.Generator
associatedtype SubSequence: SequenceType = EnumerableTileSequence
}
Now if say I can eliminate self requirement, then already with such protocol definition other collectionType entities like arrays, sets won't conform to it.
Reference:
my custom sequences are all subclasses of enumerator type defined as:
public class Enumerator<T> {
public func nextObject() -> T? {
RequiresConcreteImplementation()
}
}
extension Enumerator {
public var allObjects: [T] {
return Array(self)
}
}
extension Enumerator: SequenceType {
public func generate() -> Generator<T> {
return Generator(enumerator: self)
}
}
public struct Generator<T>: GeneratorType {
let enumerator: Enumerator<T>
public mutating func next() -> T? {
return enumerator.nextObject()
}
}
The compiler is telling you the answer: "Protocol 'Sequence' can only be used as a generic constraint because it has Self or associated type requirements".
You can therefore do this with generics:
private func _addToCurrentTileset<T: Sequence>(tilesToAdd tiles: T) {
...
}
This will allow you to pass in any concrete type that conforms to Sequence into your function. Swift will infer the concrete type, allowing you to pass the sequence around without lose type information.
If you want to restrict the type of the element in the sequence to a given protocol, you can do:
private func _addToCurrentTileset<T: Sequence>(tilesToAdd tiles: T) where T.Element: SomeProtocol {
...
}
Or to a concrete type:
private func _addToCurrentTileset<T: Sequence>(tilesToAdd tiles: T) where T.Element == SomeConcreteType {
...
}
If you don't care about the concrete type of the sequence itself (useful for mixing them together and in most cases storing them), then Anton's answer has got you covered with the type-erased version of Sequence.
You can use type-eraser AnySequence for that:
A type-erased sequence.
Forwards operations to an arbitrary underlying sequence having the same Element type, hiding the specifics of the underlying SequenceType.
E.g. if you will need to store tiles as an internal property or somehow use its concrete type in the structure of you object then that would be the way to go.
If you simply need to be able to use the sequence w/o having to store it (e.g. just map on it), then you can simply use generics (like #originaluser2 suggests). E.g. you might end up with something like:
private func _addToCurrentTileset<S: SequenceType where S.Generator.Element == Tile>(tilesToAdd tiles: S) {
let typeErasedSequence = AnySequence(tiles) // Type == AnySequence<Tile>
let originalSequence = tiles // Type == whatever type that conforms to SequenceType and has Tile as its Generator.Element
}

protocol with same associated type name

If I have two protocols whose associated type happens to be the same, such as
protocol Read {
associatedtype Element
func read() -> Element
}
protocol Write {
associatedtype Element
func write(a: Element)
}
Then I would like to have a class to read integer from and write string to:
class ReadWrite: Read, Write {
func read() -> Int {
return 5
}
func write(a: String) {
print("writing \(a)")
}
}
but the compiler complains and suggests changing String to Int. Ideally the type should be inferred, or at least compiles if I explicitly declare
associatedtype Read.Element = Int
associatedtype Write.Element = String
within ReadWrite. Any work around?
update
Workaround inspired by this question is to create two auxiliary protocols
protocol ReadInt: Read {
associatedtype Element = Int
}
protocol WriteString: Write {
associatedtype Element = String
}
and have the class inherit from these two instead:
class ReadWrite: ReadInt, WriteString {
func read() -> Int {
return 5
}
func write(a: String) {
print("writing \(a)")
}
}
This seems to compile, but I am afraid of any gotcha following this way.
update again
I found the issue in Swift's issue tracker. Anyone require this missing feature (like me) should vote for it. As a comparison, this pattern is possible in Rust, which also supports associated types (although this is not an idiomatic usage).
Another workaround is to create a third, combined protocol:
protocol ReadWrite {
associatedtype R
associatedtype W
func read() -> R
func write(a: W)
}
It's not pretty, since it forces you to redeclare the protocol members, but it does keep it generic (you're not limited to String and Int).

Self in protocol

I am learning swift and playing with Xcode.
and I always dig into the definitions. I have seen that:
public protocol GeneratorType {
typealias Element
#warn_unused_result
public mutating func next() -> Self.Element?
}
A struct that conforming this protocol:
public struct IndexingGenerator<Elements : Indexable> : GeneratorType, SequenceType {
public init(_ elements: Elements)
public mutating func next() -> Elements._Element?
}
I know 'Self' means that returning the conforming type. But what does 'Self.Element' mean?
and the function that implemented the requirement that returning 'Elements._Element?', I can’t see 'Elements._Element?' is equal to 'Self.Element?'.
Can anyone explain to me this?
and tell me more about this. thank you.
Self.Element refers to the concrete type that any type implementing GeneratorType protocol will declare as its Element typealias.
For example, in this generator of Fibonacci numbers:
struct Fibonacci: GeneratorType {
typealias Element = Int
private var value: Int = 1
private var previous: Int = 0
mutating func next() -> Element? {
let newValue = value + previous
previous = value
value = newValue
return previous
}
}
... you implement GeneratorType protocol and indicate what will be its Element typealias (Int in this case), and that's the type that generator's next() will be returning (well, actually the optional of that type).
Quite often, though, you would not have to explicitly specify typealiases when implementing parametrised protocols, as Swift is smart enough to infer them for you. E.g. for the Fibonacci numbers generator from the above example the following will also do:
struct Fibonacci: GeneratorType {
private var value: Int = 1
private var previous: Int = 0
mutating func next() -> Int? {
let newValue = value + previous
previous = value
value = newValue
return previous
}
}
... Swift knows from the signature of next() that it returns Int?, and that GeneratorType implementors also must have next() in their to-do list, and that these methods must return Element? types. So, Swift just puts 2 and 2 together, and infers that Element? must be the same thing as Int?, and therefore Element == Int.
About this:
public struct IndexingGenerator<Elements : Indexable> : GeneratorType, SequenceType {
public init(_ elements: Elements)
public mutating func next() -> Elements._Element?
}
Here we have four things going on:
We declare generic type IndexingGenerator that takes a parameter-type called Elements.
This Elements type has a constraint that it must implement Indexable protocol.
The generator that we implement is supposed to return values of the type that is accessible via Indexable interface of Elements, which is known to IndexingGenerator via dot-syntax as Elements._Element.
Swift infers that Element of IndexingGenerator is the same thing as Elements._Element.
So, essentially the above delclaration is equivalent to:
public struct IndexingGenerator<Elements : Indexable> : GeneratorType, SequenceType {
public typealias Element = Elements._Element
public init(_ elements: Elements)
public mutating func next() -> Element?
}
Finally, if curious why _Element and not just Element like in GeneratorType, here is what they write in the open-source Swift repository (under swift/stdlib/public/core/Collection.swift):
The declaration of _Element and subscript here is a trick used to break a cyclic conformance/deduction that Swift can't handle. We need something other than a CollectionType.Generator.Element that can be used as IndexingGenerator<T>'s Element. Here we arrange for the CollectionType itself to have an Element type that's deducible from its subscript. Ideally we'd like to constrain this Element to be the same as CollectionType.Generator.Element, but we have no way of expressing it today.