7

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

Karen Karapetyan
  • 444
  • 5
  • 16
  • 2
    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. – dfrib Jul 26 '17 at 08:46
  • 1
    what would happen if you pass in a `String` and an `Int`? *How* would you imagine a swap to work in this case? – luk2302 Jul 26 '17 at 08:47
  • Compare https://stackoverflow.com/q/38446487/2976878 & https://stackoverflow.com/q/44387949/2976878 – Hamish Jul 26 '17 at 08:50
  • How do I solve compiler error ? – Karen Karapetyan Jul 26 '17 at 08:54
  • 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). – dfrib Jul 26 '17 at 08:56
  • You "solve" the compiler error by using the generic version. – luk2302 Jul 26 '17 at 08:57
  • What if I don't want to swap two values just want to call that function. Why the compiler gives that error ? – Karen Karapetyan Jul 26 '17 at 08:59
  • 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. – luk2302 Jul 26 '17 at 09:21

1 Answers1

9

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.

Dávid Pásztor
  • 40,247
  • 8
  • 59
  • 80
  • Which type inherit from Any ? – Karen Karapetyan Jul 26 '17 at 09:09
  • According to the [official documentation](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TypeCasting.html#//apple_ref/doc/uid/TP40014097-CH22-ID342), _`Any` can represent an instance of any type at all, including function types._ – Dávid Pásztor Jul 26 '17 at 09:10
  • Yes, but it doesn't mean that most standard types inherit from Any. – Karen Karapetyan Jul 26 '17 at 09:17
  • 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. – Dávid Pásztor Jul 26 '17 at 09:19
  • 1
    @KarenKarapetyan `Any` is the [top type](https://en.wikipedia.org/wiki/Top_type). It is a supertype of all types, and therefore all types are a subtype of it. – Hamish Jul 26 '17 at 09:52
  • 2
    As @Hamish writes, `Any` can be considered as the top type, but as of Swift 3, [it is implemented and documented as a builtin keyword](https://stackoverflow.com/questions/45324315/where-is-any-declared-implemented-in-swift-3-and-onwards), meaning inheritance isn't strictly in action here (rather the almighty _"representability by"_), but rather `Any` being a well-defined creature of its own. – dfrib Jul 26 '17 at 10:35