prohoney
(mfaani)
1
Watching: Embrace Swift generics - WWDC22 - Videos - Apple Developer
protocol Animal {
func eat()
}
struct Cow: Animal {
func eat() {
print("eats grass")
}
}
struct Cat: Animal {
func eat() {
print("eats meat")
}
}
func feed <T>(animal: T) where T: Animal {
animal.eat()
}
In the talk, it is said that the function an be simplified to
func simplifiedFeed (animal: some Animal) {
animal.eat()
}
But what if the generic parameter was for a returning type? How can I write the following using some?
func feedB <T>(animal: T) -> T where T: Animal {
animal.eat()
return animal
}
Neither of the following functions offer protection (throw errors) to ensure the parameter type and returning types are the same.
func feedSomeB (animal: some Animal) -> Animal {
animal.eat()
return Cat() // NO ERROR - BAD
}
func feedSomeC (animal: some Animal) -> some Animal {
animal.eat()
return Cat() // NO ERROR - BAD
}
feedSomeB(animal: Cow())
feedSome(animal: Cow())
Joe_Groff
(Joe Groff)
2
Every use of some introduces a new independent generic parameter, so it's not the best tool for communicating cases where there is a relationship required between two parameters or returns. This is one time when it's better to use explicitly named generic parameters.
6 Likes
prohoney
(mfaani)
3
That makes sense. Like I can't even do the same for
func feedSomeC (animal: some Animal, another: some Animal)
Any other limitation of some?
You cannot do
func getAnimal(dog: Bool) -> some Animal {
if dog { Dog() } else { Cat() }
}
with struct Dog: Animal { … }.
In other words, all branches need to return the same actual type.