Compiler complains [some A] = [X(), Y()] with error - Type of expression is ambiguous without more context
Following code compiles:
protocol A {}
struct X: A {}
struct Y: A {}
extension Array: A where Element == any A {}
var array: [A] = [X(), Y()]
func bar(a: A) {}
bar(a: array as! A)
I don't know why you're trying to do this, but you should probably use classes instead of structs here.
There is an example of chapter "Protocols" in official document "The Swift Programming Language".
extension Dice: TextRepresentable {
var textualDescription: String {
return "A \(sides)-sided dice"
}
}
extension Array: TextRepresentable where Element: TextRepresentable {
var textualDescription: String {
let itemsAsText = self.map { $0.textualDescription }
return "[" + itemsAsText.joined(separator: ", ") + "]"
}
}
let myDice = [d6, d12] // d6 and d12 is an instance of class Dice.
It is not technically impossible with structs; you could take inspiration from C and use pointers here, however that is not safe and just asking for undefined behavior.
I was trying to understand "protocol as types". In the example, Dice is a class, and d6/d12 are both instances of Dice. What I was trying was two structs.
It is not technically impossible with structs; you could take inspiration from C and use pointers here, however that is not safe and just asking for undefined behavior.
Your code compiles but you're likely just going to cause a memory error and crash, or worse, completely destroy the data.
A == B in a type constraint means that A is a type that is the same as type B, whereas A: B in a type constraint means that A is a type that conforms to protocol B.
A == B here is synonymous with A == any B because it expects B to be a type. And A: B is more or less the same as A == some B, even though the later isn't accepted as valid.
This perennial confusion about "protocol-as-constraint" vs. "protocol-as-type" was one of the major motivating factors for the introduction of the any A syntax. When you say Element: A you are saying that Element is some type conforming to the protocol A. When you say Element == A, you are saying that Elementis the type any A.
Notably, it is (usually) not the case that any A does itself conform to the protocol A. It is difficult to see why that's the case in the most trivial examples (such as here where A is an empty protocol), but there are legitimate reasons why, in the general case, it may be impossible for any A to conform to A without a bespoke implementation for the requirements of A. IOW, it may not be possible to automatically derive a conformance any A: A for an arbitrary protocol A. For a brief example of the difficulty involved, consider if we gave A a single requirement:
protocol A {
static func getA() -> any A
}
struct X: A {
static func getA() -> any A { X() }
}
struct Y: A {
static func getA() -> any A { Y() }
}
extension Array: A where Element: A {
static func getA() -> any A { Element.getA() }
}
var array: [any A] = [X(), Y()]
func bar(a: any A) {
print(type(of: a).getA())
}
bar(a: array) // what should this print?
(Edit: added any A in further places to help illustrate the distinction)
Right. What this example is attempting to illustrate is why we can't haven it be the case that any A 'automatically' conforms to A. If we said that any Adid conform to A, then the example would have to compile as written (since then Array<any A> would conform to A by the conditional conformance). But it's not at all clear what we'd do then when we get to the getA() call inside of bar(a:) what does [any A].getA() return?
To perhaps make the issue even clearer, consider that we needn't initialize array with any elements at all, or indeed without even having any concrete types in our program which conform to A unconditionally, period!
protocol A {
static func getA() -> any A
}
extension Array: A where Element: A {
static func getA() -> any A { Element.getA() }
}
var array: [any A] = []
func bar(a: any A) {
print(type(of: a).getA())
}
bar(a: array) // what should this print?