Swift Generics vs Any
Asked Answered
C

1

8

I read swift documentation in apple site. There is a function swapTwoValues, which swaps two any given values

func swapTwoValues1<T>(_ a: inout T, _ b: inout T) {
    let temporaryA = a
    a = b
    b = temporaryA
}

Now I want to write similar function but instead of using T generic type I want to use Any

func swapTwoValues2(_ a: inout Any, _ b: inout Any) {
    let temporaryA = a
    a = b
    b = temporaryA
}

to call this functions I write

var a = 5
var b = 9


swapTwoValues1(&a, &b)

swapTwoValues2(&a, &b)

I have two questions.

1) Why the compiler gives this error for second function (Cannot pass immutable value as inout argument: implicit conversion from 'Int' to 'Any' requires a temporary)

2) What is the difference between Generic types and Any

Cathode answered 26/7, 2017 at 8:43 Comment(8)
2) Generics are strongly typed at compile time: you may compare it to any implementation using a concrete statically typed type. Generics simply lets you avoid manually duplicating the implementations for each type (which uses the method): the compiler will generate this duplicated functionality for your. In your second example, you fall back on dynamically representing various types as the "anything"-container Any. The compiler cannot know at compile time what concrete type is actually contained within a and b in your Any implementation.Stipe
what would happen if you pass in a String and an Int? How would you imagine a swap to work in this case?Lactoflavin
Compare https://mcmap.net/q/206374/-what-is-the-in-practice-difference-between-generic-and-protocol-typed-function-parameters/2976878 & https://mcmap.net/q/1325966/-why-do-we-need-a-generic-here-isn-39-t-the-protocol-enough/2976878Hauger
How do I solve compiler error ?Cathode
Ponder over @luk2302:s comment above and then ask yourself why you'd even want a swap function for two arguments typed as Any (as the only use case for these are when both arguments actually "wraps" the same concrete types: but this case if fully covered by the generic approach).Stipe
You "solve" the compiler error by using the generic version.Lactoflavin
What if I don't want to swap two values just want to call that function. Why the compiler gives that error ?Cathode
Because simply spoken: you have an Int but want to pass it to a method as an Any pointer which looses type information - the only reason you would want to pass a pointer / inout is that you want to set its value from inside the function. And that is not possible for the reason(s) given already.Lactoflavin
S
13

Any has nothing to do with generics, it is just a Swift type that can be used to represent an instance of any type at all, including function types (see the official documentation) hence you can cast an instance of any type to Any. However, when using Any with a specific type, you have to cast the Any instance back to your actual type if you want to access functions/properties that are specific to the subclass.

When using generics there is no casting involved. Generics allow you to implement one function that works with all types that satisfy the type constraint (if you specify any), but when calling the function on a specific type, it will actually work with the specific type and not with non-specific type, like Any.

In general, using generics for this kind of a problem is a better solution, since generics are strongly typed at compile time, while up/downcasting happens at runtime.

Spay answered 26/7, 2017 at 8:49 Comment(6)
Which type inherit from Any ?Cathode
According to the official documentation, Any can represent an instance of any type at all, including function types.Spay
Yes, but it doesn't mean that most standard types inherit from Any.Cathode
They can be casted to Any, which is the relevant thing to your question, but you are right, I wasn't precise enough, so I've updated my answer.Spay
@KarenKarapetyan Any is the top type. It is a supertype of all types, and therefore all types are a subtype of it.Hauger
As @Hauger writes, Any can be considered as the top type, but as of Swift 3, it is implemented and documented as a builtin keyword, meaning inheritance isn't strictly in action here (rather the almighty "representability by"), but rather Any being a well-defined creature of its own.Stipe

© 2022 - 2024 — McMap. All rights reserved.