{"id":14682,"date":"2016-06-01T11:21:32","date_gmt":"2016-06-01T15:21:32","guid":{"rendered":"http:\/\/mjtsai.com\/blog\/?p=14682"},"modified":"2019-01-22T15:45:34","modified_gmt":"2019-01-22T20:45:34","slug":"swift-type-erasure","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2016\/06\/01\/swift-type-erasure\/","title":{"rendered":"Swift Type Erasure"},"content":{"rendered":"<p><a href=\"http:\/\/robnapier.net\/erasure\">Rob Napier<\/a>:<\/p>\n<blockquote cite=\"http:\/\/robnapier.net\/erasure\">\n<p>Once upon a time, when Swift was young, there were a couple of types called <code>SequenceOf<\/code> and <code>GeneratorOf<\/code>, and they could type erase stuff. &ldquo;Type erase?&rdquo; you may ask. &ldquo;I thought we <em>loved<\/em> types.&rdquo; We do. Don&rsquo;t worry. Our types aren&rsquo;t going anywhere. But sometimes we want them to be a little less&#8230;precise.<\/p>\n<p>In Swift 2, our little type erasers got a rename and some friends. Now they&rsquo;re all named &ldquo;Any&rdquo;-something. So <code>SequenceOf<\/code> became <code>AnySequence<\/code> and <code>GeneratorOf<\/code> became <code>AnyGenerator<\/code> and there are a gaggle of indexes and collections from <code>AnyForwardIndex<\/code> to <code>AnyRandomAccessCollection<\/code>.<\/p>\n<p>[&#8230;]<\/p>\n<p>Not only is the type overwhelming, but it ties us to this particular implementation. [&#8230;] Clearly we&rsquo;re leaking too much information about our implementation. What&rsquo;s the point of <code>reverseZip<\/code>? Is it to return a <code>Zip2Sequence&lt;...&gt;<\/code>? No. It&rsquo;s to return a sequence of tuples. We want a type that means &ldquo;a sequence of tuples.&rdquo;<\/p>\n<p>[&#8230;]<\/p>\n<p>These &ldquo;Any&rdquo; type erasers also aren&rsquo;t like <code>Any<\/code> and <code>AnyObject<\/code>, which are protocols that just &ldquo;hide&rdquo; the type. You can still <code>as!<\/code> an <code>AnyObject<\/code> back to its original type. <code>AnySequence<\/code> and its kin completely encapsulate the underlying data. You can&rsquo;t get the original back. This creates a very strong abstraction layer and strengthens type safety by making <code>as!<\/code> casting impossible.<\/p>\n<p>[&#8230;]<\/p>\n<p>This kind of type eraser lets us convert a protocol with associated types into a generic type. That means we can put it in properties and return values and other places that we can&rsquo;t use protocols directly.<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/realm.io\/news\/type-erased-wrappers-in-swift\/\">Samuel E. Giddins<\/a>:<\/p>\n<blockquote cite=\"https:\/\/realm.io\/news\/type-erased-wrappers-in-swift\/\"><p>To start out, we&rsquo;re going to write a small class that also conforms to <code>SequenceType<\/code> and is also generic over the <code>Element<\/code> we want [&#8230;]<\/p><p>&ldquo;But wait!&rdquo; you probably want to say, &ldquo;that doesn&rsquo;t <em>really<\/em> conform to <code>SequenceType<\/code>!&rdquo; It does. This is using the same <code>fatalError<\/code> trick I mentioned earlier, to gloss over the holes in the <code>SequenceType<\/code> type signatures we can&rsquo;t possibly know how to fill.<\/p><p>[&#8230;]<\/p><p>The most important thing to notice about this class declaration is that <code>_AnySequenceBox<\/code> is generic over a <em>particular <code>SequenceType<\/code> implementation<\/em>. In fact, it&rsquo;s generic over the very type that our <code>AnySequence<\/code> wrapper is erasing. It&rsquo;s also a subclass of <code>_AnySequenceBoxBase<\/code>, with the base&rsquo;s generic element being that of the erased type&rsquo;s <code>Generator.Element<\/code>. This is the point of translation from our associated type protocol into the world of generics. The rest of the implementation for <code>AnySequence<\/code> is basically just boilerplate (albeit a vast quantity thereof).<\/p><p>[&#8230;]<\/p><p>Yes, we&rsquo;ve implemented the methods of <code>SequenceType<\/code> three times. And you&rsquo;d need to do this again for every protocol you wish to provide a type-erased wrapper for. It&rsquo;s rather a lot of code to write, but doing this work will make your protocols feel more like first class citizens.<\/p><\/blockquote>\n\n<p><a href=\"https:\/\/realm.io\/news\/tryswift-gwendolyn-weston-type-erasure\/\">Gwendolyn Weston<\/a>:<\/p>\n<blockquote cite=\"https:\/\/realm.io\/news\/tryswift-gwendolyn-weston-type-erasure\/\">\n<p>This is where type reification comes in: We make an abstract type concrete by filling in its placeholder types.<\/p>\n<p>[&#8230;]<\/p>\n<p>Wrapper classes are conventionally prefixed with the word &ldquo;Any&rdquo;, in order to guarantee that you will instantiate an object that implements our protocol and fills the generic type, without necessarily having the implementation on hand.<\/p>\n<p>[&#8230;]<\/p>\n<p>I feel the best definition that I have at the end of my road of preparing this talk is that type erasure is this design pattern where you have a wrapper class that has a constraint in the initializer method such that you can only initialize it with an instance of an implementation of the protocol you are trying to make concrete.<\/p>\n<\/blockquote>\n\n<p><a href=\"http:\/\/www.russbishop.net\/type-erasure\">Russ Bishop<\/a>:<\/p>\n<blockquote cite=\"http:\/\/www.russbishop.net\/type-erasure\"><p>More specifically, what is type erasure <em>in the context of Swift and Protocols with associated types<\/em>? If I could boil it down to one sentence:<\/p>\n<p>Passing a generic type <em>parameter<\/em> to a protocol&rsquo;s associated type member.<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/www.natashatherobot.com\/swift-type-erasure\/\">Natasha Murashev<\/a>:<\/p>\n<blockquote cite=\"https:\/\/www.natashatherobot.com\/swift-type-erasure\/\"><p>This still feels like an overly complex fix for something that should just work and hopefully it will in the future. For now, this is a super good pattern to know when working with protocols with associated types.<\/p><\/blockquote>\n\n<p>See also: <a href=\"http:\/\/stackoverflow.com\/questions\/6324694\/type-erasure-in-c-how-boostshared-ptr-and-boostfunction-work\/6324714#6324714\">Type erasure in C++: how boost::shared_ptr and boost::function work<\/a>.<\/p>\n\n<p>Previously: <a href=\"http:\/\/mjtsai.com\/blog\/2016\/02\/19\/swift-protocols-with-associated-types\/\">Swift Protocols With Associated Types<\/a>.<\/p>\n\n<p>Update (2016-06-01): <a href=\"https:\/\/twitter.com\/owensd\/status\/738038072714113024\">David Owens II<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/owensd\/status\/738038072714113024\"><p>If you have to keep using type erasures to actually work with your types, doesn&rsquo;t that suggest something? Maybe I don&rsquo;t get it.<\/p><\/blockquote>\n\n<p><a href=\"https:\/\/twitter.com\/jckarter\/status\/738058366841298944\">Joe Groff<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/jckarter\/status\/738058366841298944\"><p>Being only as precise as you need to be lets you stay flexible and avoid unnecessary refactoring.<\/p><\/blockquote>\n<blockquote cite=\"https:\/\/twitter.com\/jckarter\/status\/738039645842198528\"><p>Only keep the types you need. Type hoarding is unhealthy and may require professional help.<\/p><\/blockquote>\n\n<p>Update (2016-06-02): <a href=\"http:\/\/elm4ward.github.io\/swift\/generics\/type\/erasure\/2016\/04\/21\/erase-em-all.html\">Elmar Kretzer<\/a> posted an example of a type-erasing struct.<\/p>\n\n<p>Update (2018-03-09): See also: <a href=\"https:\/\/realm.io\/news\/altconf-hector-matos-type-erasure-magic\/\">Hector Matos<\/a> and <a href=\"https:\/\/www.mikeash.com\/pyblog\/friday-qa-2017-12-08-type-erasure-in-swift.html\">Mike Ash<\/a> (<a href=\"https:\/\/news.ycombinator.com\/item?id=15931875\">Hacker News<\/a>).<\/p>","protected":false},"excerpt":{"rendered":"<p>Rob Napier: Once upon a time, when Swift was young, there were a couple of types called SequenceOf and GeneratorOf, and they could type erase stuff. &ldquo;Type erase?&rdquo; you may ask. &ldquo;I thought we loved types.&rdquo; We do. Don&rsquo;t worry. Our types aren&rsquo;t going anywhere. But sometimes we want them to be a little less&#8230;precise. [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"2019-01-22T20:45:36Z","apple_news_api_id":"98b31c47-54ac-4bb3-b7ce-b2731d03ecff","apple_news_api_modified_at":"2019-01-22T20:45:37Z","apple_news_api_revision":"AAAAAAAAAAD\/\/\/\/\/\/\/\/\/\/w==","apple_news_api_share_url":"https:\/\/apple.news\/AmLMcR1SsS7O3zrJzHQPs_w","apple_news_coverimage":0,"apple_news_coverimage_caption":"","apple_news_is_hidden":false,"apple_news_is_paid":false,"apple_news_is_preview":false,"apple_news_is_sponsored":false,"apple_news_maturity_rating":"","apple_news_metadata":"\"\"","apple_news_pullquote":"","apple_news_pullquote_position":"","apple_news_slug":"","apple_news_sections":"\"\"","apple_news_suppress_video_url":false,"apple_news_use_image_component":false,"footnotes":""},"categories":[4],"tags":[46,71,816,901],"class_list":["post-14682","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-languagedesign","tag-programming","tag-refactoring","tag-swift-programming-language"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/14682","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/comments?post=14682"}],"version-history":[{"count":4,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/14682\/revisions"}],"predecessor-version":[{"id":20835,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/14682\/revisions\/20835"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=14682"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=14682"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=14682"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}