It depends on what "knowledge" you want to provide to or hide from callers.
This returns an Array
. The elements in the array are of some concrete type that conforms to Food
. The actual element type (DogFood
) is not known to the caller.
This returns some concrete type that conforms to Sequence
. Neither the concrete type of sequence (Array
) nor the element type of the sequence (DogFood
) are known to the caller. The caller doesn't even know that the elements conform to Food
. For all the caller knows, this function could return a Set<Int>
or a Dictionary<String, Int>
or …. The only thing that is known to the caller is that the returned type will be the same every time the function is called (this is a property of opaque result types).
In most cases, the first variant [some Food]
is probably more useful because it gives the caller information about the element type. Without knowing anything about the element type, callers probably won't be able to do much with the elements.
Here's another desirable variant that should work but unfortunately doesn't in Swift 5.10:
// Error: 'some' types are only permitted in properties, subscripts, and functions
func createFood3() -> some Sequence<some Food> {
[DogFood(), DogFood()]
}
This claims to return some concrete sequence type (the actual type is unknown, could be an array or set or …) where the elements all have the same concrete type that conforms to Food
, but the actual type is unknown to the caller. Unfortunately, this doesn't compile. See Nested constrained opaque result type example from SE-0346 doesn't compile · Issue #61409 · apple/swift · GitHub.
Lastly, another variant:
struct CatFood: Food {}
func createFood4() -> some Sequence<any Food> {
[DogFood(), CatFood()]
}
Here, some Sequence<any Food>
says that the elements in the sequence are boxed values (also called "existentials"). Each value inside the boxes conforms to Food
, but now it's not guaranteed that all those values have the same underlying type. So the sequence can contain both (boxed) DogFood
and CatFood
values at the same time.
This was also possible with your second variant (alsoCreateFood
) because it didn't put any constraints on the element type, but not with your first because [some Food]
guarantees that every element in the array has the same concrete type (the caller just doesn't know what it is).