
Type Erasure in Swift - ingve
https://www.mikeash.com/pyblog/friday-qa-2017-12-08-type-erasure-in-swift.html
======
runeks
> For example, if you want to write some code that accepts any Sequence of Int
> values, you can't write this:

> func f(seq: Sequence<Int>) { ...

> […] Swift provides the AnySequence type to solve this problem. AnySequence
> wraps an arbitrary Sequence and erases its type, providing access to it
> through the AnySequence type instead. Using this, we can rewrite f and g:

> func f(seq: AnySequence<Int>) { ...

> […] The Swift standard library has a bunch of these Any types, such as
> AnyCollection, AnyHashable, and AnyIndex.

Please excuse my ignorance, but what’s the point of this?

Have all these <SomeType> and their Any<SomeType> counterpart seems like
unnecessary code duplication to me.

~~~
Tyr42
Perhaps you'll be interested in someone's reverse engineering of how
AnySequence was implemented?

[https://gist.github.com/rnapier/3095ab4986fce8d4fe8d](https://gist.github.com/rnapier/3095ab4986fce8d4fe8d)

~~~
jordansmithnz
Not sure why it was reverse engineered when the source code is publicly
available:
[https://github.com/apple/swift/blob/4ddac3fbbd5b9ba8d980fa88...](https://github.com/apple/swift/blob/4ddac3fbbd5b9ba8d980fa8810472cad3d79b7e6/stdlib/public/core/ExistentialCollection.swift.gyb)

~~~
armadsen
Swift was open-sourced in December of 2015, which was a few months after that
gist was written.

------
eptcyka
Will swift not get the `impl trait` that Rust is slowly churning out?

~~~
mikeash
I believe it's coming eventually, but for the moment we need workarounds like
this.

~~~
masklinn
It looks like trait objects could also work for the essay, e.g. the original
examples could be achieved as:

    
    
        fn f(seq: &mut Iterator<Item=&u8>)
    

although due to object-safety constraints they may not be suitable for every
case.

------
squiguy7
To further my understanding this would be akin to trait objects in Rust right?
Instead of having generic type constraints in the function signature you can
`Box` your traits or use pointers to a trait and use dynamic dispatch. I'm
sure there are also some differences as well and would like to hear them.

~~~
Veedrac
If you're interested, there's a very nice talk on how Swift's generics
compile. It's different to Rust in some key ways.

[https://www.youtube.com/watch?v=ctS8FzqcRug](https://www.youtube.com/watch?v=ctS8FzqcRug)

~~~
mikeash
Thanks for posting this, I've been meaning to watch it but keep forgetting
about it.

------
eximius
> func g<S: Sequence>() -> S where S.Element == Int {

I think Rust can do this case. I think this is how a simple version of
`collect` would work (or very nearly).

------
tdburn
Saw Erasure and was expecting this instead

[https://youtu.be/CC_Y4zOUdcI](https://youtu.be/CC_Y4zOUdcI)

------
nerdponx
Is this different from structural typing?

~~~
masklinn
Why would you even think it has any relation?

~~~
nerdponx
Because it sure sounds similar. Look at Python's PEP 544, for example.

~~~
masklinn
The only commonality I can see is that both use the word "protocol"…

~~~
nerdponx
AnySequence is a behavior specification, right? That seems pretty structural
to me.

~~~
mikeash
AnySequence is a concrete type conforming to the Sequence protocol. It
implements Sequence by forwarding calls to some other implementation of
Sequence.

~~~
thewayfarer
Strictly speaking, AnySequence is a generic type, whereas AnySequence<Int>,
AnySequence<String>, and AnySequence<Any> would be three different concrete
types.

------
basic-gongfu
I recently spent a couple of weeks in Swift land to see what it's all about;
but from my experience it's still a mine field of exceptions and hoop jumping.
I feel that the problem with both Rust and Swift is that they're aiming so
hard for perfection that they're missing the point of the exercise; which is
to make it easier to write good code, period. Wasting half your energy-budget
on spoon feeding the compiler is just as bad as spending it on managing memory
manually in C.

~~~
thewayfarer
> Wasting half your energy-budget on spoon feeding the compiler is just as bad
> as spending it on managing memory manually in C.

This isn't quite a fair comparison. Manual memory management increases the
risk of producing incorrect or buggy programs. Satisfying a strict compiler
increases the chance that your program is written correctly.

And for what it's worth, this boilerplate dance for "type erasure" will be
solved with what the Swift team calls generalized existentials, where you'll
be able to use nominal types like Any<Sequence where .Iterator.Element ==
String>. "Type erasure" isn't the result of "aiming so hard for perfection" as
you say, but because Swift is still a young language and there is only so much
the creators can work on at any one time. Most Swift devs (think iOS apps)
aren't running up against this problem much, and I haven't seen a single
situation in an app where implementing a "type erased" generic type was
necessary. At this point in the Swift timeline, just making Swift code compile
faster would make devs much happier.

> it's still a mine field of exceptions

Unlike languages that actually use _exceptions_ , which really are mine fields
of exceptions in a different sense :P

