-
Notifications
You must be signed in to change notification settings - Fork 0
/
feed.rss
310 lines (274 loc) · 44 KB
/
feed.rss
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>ChuyNadaMas's Personal Blog</title><description>Some note for my personal purposes</description><link>https://chuynadamas.github.io/chuynadamas/</link><language>en</language><lastBuildDate>Sun, 17 Oct 2021 19:06:08 -0500</lastBuildDate><pubDate>Sun, 17 Oct 2021 19:06:08 -0500</pubDate><ttl>250</ttl><atom:link href="https://chuynadamas.github.io/chuynadamas/feed.rss" rel="self" type="application/rss+xml"/><item><guid isPermaLink="true">https://chuynadamas.github.io/chuynadamas/posts/type-erasures</guid><title>Type erasures in Swift 🤔</title><description>Type Erasures in Swift ✏️</description><link>https://chuynadamas.github.io/chuynadamas/posts/type-erasures</link><pubDate>Sun, 3 Oct 2021 21:39:00 -0500</pubDate><content:encoded><![CDATA[<h1>Type erasures in Swift 🤔</h1><h2></h2><a class="disclaimer" href="https://www.donnywals.com/understanding-type-erasure-in-swift/">
This is a rewrite of the post from Donny Wals, if you are reading this pleae see the original content at Donny Wals I'm not making any money of this blog is only my personal studies purposes.
</a><h2>Some background</h2><p>With protocols and generics, you can express ideas that are complex and flexible. But sometimes you are coding along happily and the Swift compiler starts yelling at you. You've hit one of those scenarios where your code is so flexible and dynamic that Swift isn't having it.</p><br/><p>If you want to write a function that returns an object that conforms to a protocol that has an associated type? Not going to happen unless you use an <code>opaque result type</code>!</p><br/><p>But what if you don't want to return the exact same concrete type from your function all time? Unfurtunately, <code>opaque results types</code> won't help you there.</p><p>When the Swift compiler keeps yelling at you and you have no idea how to make it stop. it might be time to apply some type erasure.</p><p>There are multiple scenarios where type erasure makes sense.</p><br/><h2>Using type erasure to hide implementation details</h2><p>The most straightforward way to think of type erasure is to consider it a way to hide an objects "real" type. Some xamples that come to mind ommediately are Combine's <code>AnyCancellable</code> and <code>AnyPublisher</code>.</p><br/><p><code>AnyPublisher</code> in Combine is generic over an <code>Output</code> and <code>Failure</code>. All you really need to know about <code>AnyPusbliser</code> is that conforms to the <code>Pusbliser</code> protocol and wraps another publisher. Combine comes with tons of built-in publishers like <code>Publisher.Map</code>, <code>Publisher.FlatMap</code>, <code>Future</code>, <code>Publisher.Filter</code>, and many more.</p><br/><p>Often when you're working with combine, you will write functions that set up a chain of publishers. You usually don't want to expose the publishers you used to callers of your function. In essence, all you want to expose is that you're creating a publisher that emits values of a certain type <code>Output</code> or fails with a specific error <code>Failirue</code>. So instead of writing this:</p><pre><code><span class="keyword">func</span> fetchData() -> <span class="type">URLSession</span>.<span class="type">DataTaskPublisher</span><(data: <span class="type">Data</span>, response: <span class="type">URLResponse</span>), <span class="type">URLError</span>> {
<span class="keyword">return</span> <span class="type">URLSession</span>.<span class="property">shared</span>.<span class="call">dataTaskPublisher</span>(for: someURL)
}
</code></pre><br/><p>You will usually want to write this:</p><br/><pre><code><span class="keyword">func</span> fetchData() -> <span class="type">AnyPublisher</span><(data: <span class="type">Data</span>, response: <span class="type">URLResponse</span>), <span class="type">URLError</span>> {
<span class="keyword">return</span> <span class="type">URLSession</span>.<span class="property">shared</span>.<span class="call">dataTaskPublisher</span>(for: someURL)
.<span class="call">eraseToAnyPublisher</span>()
}
</code></pre><br/><p>By appliying type erasure to the publisher created in <code>fetchData</code> we are now free to change its implementation as needed, and callers of <code>fetchData</code> don't need to care about the exact publisher that's used under the hood.</p><br/><p>When you thinkg about how you can refactor this code, you might be tempted to try and use a protocol instead of an <code>AnyPublisher</code>. And you'd be right to wonder why we wouldn't.</p><br/><p>Since <code>Publisher</code> has an <code>Output</code> and <code>Failure</code> that we want to be able to use, using <code>some Publisher</code> wouldn't work. We wouldn't be able to return <code>Publisher</code> due its associated type constraints, so returning <code>some Publisher</code> would allow the code to compile but it would be pretty useless:</p><br/><pre><code><span class="keyword">func</span> fetchData() -> <span class="keyword">some</span> <span class="type">Publisher</span> {
<span class="keyword">return</span> <span class="type">URLSession</span>.<span class="property">shared</span>.<span class="call">dataTaskPublisher</span>(for: someURL)
}
<span class="call">fetchData</span>().<span class="call">sink</span>(receiveCompletion: { completion <span class="keyword">in</span>
<span class="call">print</span>(completion)
}, receiveValue: { output <span class="keyword">in</span>
<span class="call">print</span>(output.<span class="property">data</span>) <span class="comment">// Value of type '(some Publisher).Output' has no member 'data'</span>
})
</code></pre><br/><p>Because <code>some Publisher</code> hides the true type of the generic used by <code>Publisher</code>, there is no way to do anything useful with the <code>output</code> or <code>completion</code> in this example. An <code>AnyPublisher</code> hides the underlying type just like <code>some Publisher</code> does, exept you can still define what the <code>Output</code> and <code>Failure</code> types are for the publisher by writing <code>AnyPublisher<Output,Failure></code></p><br/><p>If you use <code>Combine</code>, you will encounter <code>AnyCancellable</code> when you subscribe to a publisher useing one of Combine's built-in subscription methods.</p><br/><p>Without going too much detail, Combine has a protocol called <code>Cancellable</code>. This protocol requires that conforming objects implement a <code>cancel</code> method that can be called to cancel a subscription to a publisher's output. Combine provides three objects that conform to <code>Cancellable:</code></p><br/><ul class="ul-normal">
<li class="li-normal"><code>AnyCancellable</code></li>
<li class="li-normal"><code>Suscribers.Assign</code></li>
<li class="li-normal"><code>Subscribers.Sink</code></li>
</ul><br/><p>The <code>Assign</code> and <code>Sink</code> subscribrers match up with two of <code>Publishers</code>'s methods:</p><br/><ul class="ul-normal">
<li class="li-normal"><code>assign(to:on:)</code></li>
<li class="li-normal"><code>sink(receiveCompletion:receiveValue)</code></li>
</ul><br/><p>These two methods both return <code>AnyCancellable</code> instances rather than <code>Subscribers.Assign</code> and <code>Subscribers.Sink</code>. Apple could have chosen to make both of these methods return <code>Cancellable</code> instead of <code>AnyCancellable</code>.</p><br/><p>But they didn't</p><br/><p>The reason Apple applies type erasure in this example is that thery don't want users of <code>assign(to:on:)</code> and <code>sink(receiveCompletion:receiveValue)</code> to know which type is returned exactly. It simply doen't matter. All you need to know is that it's an <code>AnyCancellable</code>. Not just that it's <code>Cancellable</code>, but that it coul be any <code>Cancellable</code>.</p><br/><p>Because <code>AnyCancellable</code> erases the type of the original <code>Cancellable</code> by wrapping it, you don't know if the <code>AnyCancellable</code> wraps a <code>Subscriber.Sink</code> or some other kind of internal, private <code>Cancellable</code> that we're not supposed to know about.</p><br/><p>If you have a need to hide implementation details in your code, or if you run into a case where you want to return an object that conforms to a protocol that has an associated type that you need to access without returning the actual type of object you wanted to return, type erasure just might be what you're looking for.</p><br/><h2>Applying type erasure in your codebase</h2><p>Too apply type erasure to an object, you need to define a wrapper. Let's look at an example:</p><pre><code><span class="keyword">protocol</span> DataStore {
<span class="keyword">associatedtype</span> StoredType
<span class="keyword">func</span> store(<span class="keyword">_</span> object: <span class="type">StoredType</span>, forKey: <span class="type">String</span>)
<span class="keyword">func</span> fetchObject(forKey key: <span class="type">String</span>) -> <span class="type">StoredType</span>?
}
<span class="keyword">class</span> AnyDataStore<StoredType>: <span class="type">DataStore</span> {
<span class="keyword">private let</span> storeObject: (<span class="type">StoredType</span>, <span class="type">String</span>) -> <span class="type">Void</span>
<span class="keyword">private let</span> fetchObject: (<span class="type">String</span>) -> <span class="type">StoredType</span>?
<span class="keyword">init</span><Store: <span class="type">DataStore</span>>(wrappedStore: <span class="type">Store</span>) <span class="keyword">where</span> <span class="type">Store</span>.<span class="type">StoredType</span> == <span class="type">StoredType</span> {
<span class="keyword">self</span>.<span class="property">storeObject</span> = wrappedStore.<span class="property">store</span>
<span class="keyword">self</span>.<span class="property">fetchObject</span> = wrappedStore.<span class="property">fetchObject</span>
}
<span class="keyword">func</span> store(<span class="keyword">_</span> object: <span class="type">StoredType</span>, forKey key: <span class="type">String</span>) {
<span class="call">storeObject</span>(object, key)
}
<span class="keyword">func</span> fetchObject(forKey key: <span class="type">String</span>) -> <span class="type">StoredType</span>? {
<span class="keyword">return</span> <span class="call">fetchObject</span>(key)
}
}
</code></pre><br/><p>This example defines a <code>DataStore</code> protocol and a type erasing wrapper called <code>AnyDataStore</code>. The purpose of the <code>AnyDataStore</code> is to provide an abstraction that hides the underlying data store entirely. Much like <code>Combine</code> <code>AnyPublisher</code>. The <code>AnyDataStore</code> object makes extensive use of generics,</p><br/><p>The <code>AnyDataStore</code> itself is generic over <code>StoredType</code>. This is the type of object that the undelying <code>DataStore</code> stores. The initializer for <code>AnyDataStore</code> is generic over <code>Store</code> where <code>Store</code> conforms to <code>DataStore</code> and the objects that are stored in the <code>Store</code> must match the objects stored by the <code>AnyDataStore</code>. Due to the way this wrapper is set up that should always be the case but Swift requires us to be explicit.</p><br/><p>We want forward any calls on <code>AnyDataStore</code> to the wrapped store. but we can't hold in tothe wrapped store since that would require making <code>AnyDataStore</code> generic over the underlying datastore. Instead, we capture references to the method we need in the <code>storeObject</code> and <code>fetchObject</code> propeerties and forward any calls to <code>store(_:forKey:)</code> and <code>fetchObject(forKey:)</code> to their respective stores references.</p><br/><pre><code><span class="keyword">class</span> InMemoryImageStore: <span class="type">DataStore</span> {
<span class="keyword">var</span> images = [<span class="type">String</span>: <span class="type">UIImage</span>]()
<span class="keyword">func</span> store(<span class="keyword">_</span> object: <span class="type">UIImage</span>, forKey key: <span class="type">String</span>) {
images[key] = object
}
<span class="keyword">func</span> fetchObject(forKey key: <span class="type">String</span>) -> <span class="type">UIImage</span>? {
<span class="keyword">return</span> images[key]
}
}
<span class="keyword">struct</span> FileManagerImageStore: <span class="type">DataStore</span> {
<span class="keyword">typealias</span> StoredType = <span class="type">UIImage</span>
<span class="keyword">func</span> store(<span class="keyword">_</span> object: <span class="type">UIImage</span>, forKey key: <span class="type">String</span>) {
<span class="comment">// write image to file system</span>
}
<span class="keyword">func</span> fetchObject(forKey key: <span class="type">String</span>) -> <span class="type">UIImage</span>? {
<span class="keyword">return nil</span> <span class="comment">// grab image from file system</span>
}
}
<span class="keyword">class</span> StorageManager {
<span class="keyword">func</span> preferredImageStore() -> <span class="type">AnyDataStore</span><<span class="type">UIImage</span>> {
<span class="keyword">if</span> <span class="type">Bool</span>.<span class="call">random</span>() {
<span class="keyword">let</span> fileManagerStore = <span class="type">FileManagerImageStore</span>()
<span class="keyword">return</span> <span class="type">AnyDataStore</span>(wrappedStore: fileManagerStore)
} <span class="keyword">else</span> {
<span class="keyword">let</span> memoryStore = <span class="type">InMemoryImageStore</span>()
<span class="keyword">return</span> <span class="type">AnyDataStore</span>(wrappedStore: memoryStore)
}
}
}
</code></pre><br/><p>In the code snippet above There is two different data stores and <code>StoreManager</code> that is responsible for providing a preffered storage solution. Since the <code>StorageManager</code> decides which storage we want to use it returns an <code>AnyDataStore</code> that's generic over <code>UIImage</code> object.</p><br/><p>The example of AnyDataStore is very similar to the <code>AnyPublisher</code> scenario that is described in the previous section. It's pretty complex but it's good to know this exists and how it (possibly) looks under the hood.</p><br/><p>In the previous section, is mentioned <code>AnyCancellable</code>. An object like that is much simpler to recreate because it doesn't involve any generics or associated types. Let's try to create something similar except this version will be called <code>AnyPersistable:</code></p><br/><pre><code><span class="keyword">protocol</span> Persistable {
<span class="keyword">func</span> persist()
}
<span class="keyword">class</span> AnyPersistable: <span class="type">Persistable</span> {
<span class="keyword">private let</span> wrapped: <span class="type">Persistable</span>
<span class="keyword">init</span>(wrapped: <span class="type">Persistable</span>) {
<span class="keyword">self</span>.<span class="property">wrapped</span> = wrapped
}
<span class="keyword">func</span> persist() {
wrapped.<span class="call">persist</span>()
}
}
</code></pre><br/><p>An abstraction like the one I showed could be useful if you're dealing with a whole bunch of objects that need to be persisted but you want to hide what these objects really are. Since there are no complicated generics involved in this example it's okay to hold on to the <code>Persistable</code> object that's wrapped by <code>AnyPersistable</code>.</p>]]></content:encoded></item><item><guid isPermaLink="true">https://chuynadamas.github.io/chuynadamas/posts/opaque-returns</guid><title>Opaque return types in swift 🤪</title><description>Explanation about the opaque return types in swift 🐦</description><link>https://chuynadamas.github.io/chuynadamas/posts/opaque-returns</link><pubDate>Sat, 25 Sep 2021 03:13:00 -0500</pubDate><content:encoded><![CDATA[<h1>Opaque return types in swift 🤪</h1><a class="disclaimer" href="https://www.donnywals.com/understanding-opaque-return-types-in-swift-5-1/">
This is a rewrite of the post from Donny Wals, if you are reading this pleae see the original content at Donny Wals I'm not making any money of this blog is only my personal studies purposes.
</a><h2>Some background</h2><p>If you have spent some time with SwiftUI, you may have noticed that views in SwiftUI have a property called <code>body</code> of type <code>some View</code>. If want to go deeper please see the following <a href="https://github.com/apple/swift-evolution/blob/master/proposals/0244-opaque-result-types.md">SE-0244</a></p><h2><code>Some</code> keyboard</h2><p>In Swift, we can use protocols to define interfaces or contracts for our objects. When something conforms to a protocol, we know that it can do certain things, or has certain properties. This means that you can writr code like this:</p><pre><code><span class="keyword">protocol</span> ListItemDisplayable {
<span class="keyword">var</span> name: <span class="type">String</span> { <span class="keyword">get</span> }
}
<span class="keyword">struct</span> Shoe: <span class="type">ListItemDisplayable</span> {
<span class="keyword">let</span> name: <span class="type">String</span>
}
<span class="keyword">var</span> listItem: <span class="type">ListItemDisplayable</span> = <span class="type">Shoe</span>(name: <span class="string">"a shoe"</span>)
</code></pre><br/><p>When using this <code>listItem</code> property, only the properties exposed by <code>ListItemDisplayable</code> are exposed to us. This is especially useful when you want to have an array of items that are <code>ListItemDisplayable</code> where concrete types can be more than just <code>Shoe</code></p><br/><pre><code><span class="keyword">struct</span> Shoe: <span class="type">ListItemDisplayable</span> {
<span class="keyword">let</span> name: <span class="type">String</span>
}
<span class="keyword">struct</span> Shorts: <span class="type">ListItemDisplayable</span> {
<span class="keyword">let</span> name: <span class="type">String</span>
}
<span class="keyword">var</span> mixedList: [<span class="type">ListItemDisplayable</span>] = [<span class="type">Shoe</span>(name: <span class="string">"a shoe"</span>),
<span class="type">Shorts</span>(name: <span class="string">"a pair of shorts"</span>)]
</code></pre><br/><p>The compiler treats our <code>Shoe</code> and <code>Shorts</code> objects as <code>ListItemDisplayable</code>, so users of this list won't know whether they're dealing with shoes, shorts, jeans or anything else. All they know is that whatever is in the array can be displayed in a list because ir conforms to <code>ListDisplayable</code>.</p><br/><h2>Opaque result types for protocols with associated types</h2><p>The flexible shown in the previous section is really cool, but we can push our code further:</p><br/><pre><code><span class="keyword">protocol</span> ListDataSource {
<span class="keyword">associatedtype</span> ListItem: <span class="type">ListItemDisplayable</span>
<span class="keyword">var</span> items: [<span class="type">ListItem</span>] { <span class="keyword">get</span> }
<span class="keyword">var</span> numberOfItems: <span class="type">Int</span> { <span class="keyword">get</span> }
<span class="keyword">func</span> itemAt(<span class="keyword">_</span> index: <span class="type">Int</span>) -> <span class="type">ListItem</span>
}
</code></pre><br/><p>The above defines a <code>ListDataSource</code> that holds some list of an item that conforms to <code>ListItemDisplayable</code>. We can use objects that conform to this protocol as data source objects for table views, or collection views which is preatty neat.</p><br/><p>We can define a view model generator object that will, depending on what kind of items we pass it, generate a <code>ListDataSource:</code></p><br/><pre><code><span class="keyword">struct</span> ShoesDataSource: <span class="type">ListDataSource</span> {
<span class="keyword">let</span> items: [<span class="type">Shoe</span>]
<span class="keyword">var</span> numberOfItems: <span class="type">Int</span> { items.<span class="property">count</span> }
<span class="keyword">func</span> itemAt(<span class="keyword">_</span> index: <span class="type">Int</span>) -> <span class="type">Shoe</span> {
<span class="keyword">return</span> items[index]
}
}
<span class="keyword">struct</span> ViewModelGenerator {
<span class="keyword">func</span> listProvider(for items: [<span class="type">Shoe</span>]) -> <span class="type">ListDataSource</span> {
<span class="keyword">return</span> <span class="type">ShoesDataSource</span>(items: items)
}
}
</code></pre><br/><p>However, this code doesn't compile because <code>ListDataSource</code> is a protocol with associated type constraints. We could fix this by specifiying <code>ShoesDataSource</code> as the return type instead of <code>ListDataSource</code>, but this would expose an implementation detail that we wanto to hide from users of the <code>ViewModelGenerator</code>.</p><br/><p>Callers of <code>listProvider(for:)</code> only really need to know is that we're going to return a <code>ListDataSource</code> from this method. We can rewrite the generators as follos make our code compile:</p><br/><pre><code><span class="keyword">struct</span> ViewModelGenerator {
<span class="keyword">func</span> listProvider(for items: [<span class="type">Shoe</span>]) -> <span class="keyword">some</span> <span class="type">ListDataSource</span> {
<span class="keyword">return</span> <span class="type">ShoesDataSource</span>(items: items)
}
}
</code></pre><br/><p>By using the <code>some</code> keyword, the compiler can enforce a couple of things while hiding them from the caller of <code>listProvides(for:)</code>:</p><br/><ul><li>We return something that conforms to <code>ListDataSource</code></li><li>The returned object's associated type matches any requirements that are set by <code>ListDataSource</code></li><li>We always return the same type from <code>listProvider(for:)</code> <br/> <br/></li></ul><p>Especially this last point is interesting. In Swift, we rely on the compiler to do a lot of compile-time type checks to help us write safe and consistent code. And in turn, the compiler uses all of this information about types to optimize our code to ensure it runs as fast as possible. Protocols are often a problem for the compiler because they imply a certain dynamism that makes it hard for the compiler to make certain optimizations at compile time which means that we’ll take a <em>(very small)</em> performance hit at runtime because the runtime will need to do some type checking to make sure that what’s happening is valid.</p><br/><p>Because the Swift compiler can enforce the things listed above, it can make the same optimizations that it can when we would use concrete types, yet we have the power of hiding the concrete type from the caller of a function or property that returns an opaque type.</p><br/><h2>Opaque result types and Self requirements</h2><p>Because the compiler can enforce type constraints compile time, we can do other interesting things. For example, we can compare items that are returned as opaque types while we cannot do the same with protocols. Let’s look at a simple example:</p><br/><pre><code><span class="keyword">protocol</span> ListItemDisplayable: <span class="type">Equatable</span> {
<span class="keyword">var</span> name: <span class="type">String</span> { <span class="keyword">get</span> }
}
<span class="keyword">func</span> createAnItem() -> <span class="type">ListItemDisplayable</span> {
<span class="keyword">return</span> <span class="type">Shoe</span>(name: <span class="string">"a comparable shoe:</span> \(<span class="type">UUID</span>().<span class="property">uuidString</span>)<span class="string">"</span>)
}
</code></pre><br/><p>The above doesn’t compile because <code>Equatable</code> has a <code>Self</code> requirement. It wants to compare two instances of <code>Self</code> where both instances are of the same type. This means that we can’t use <code>ListItemDisplayable</code> as a regular return type, because a protocol on its own has no type information. We need the <code>some</code> keyword here so the compiler will figure out and enforce a type for <code>ListItemDisplayable</code> when we call <code>createAnItem():</code></p><br/><pre><code><span class="keyword">func</span> createAnItem() -> <span class="keyword">some</span> <span class="type">ListItemDisplayable</span> {
<span class="keyword">return</span> <span class="type">Shoe</span>(name: <span class="string">"a comparable shoe:</span> \(<span class="type">UUID</span>().<span class="property">uuidString</span>)<span class="string">"</span>)
}
</code></pre><br/><p>The compiler can now determine that we’ll always return <code>Shoe</code> from this function, which means that it knows what <code>Self</code> for the item that’s returned by <code>createAnItem()</code>, which means that the item can be considered <code>Equatable</code>. This means that the following code can now be used to create two items and compare them:</p><br/><pre><code><span class="keyword">let</span> left = <span class="call">createAnItem</span>()
<span class="keyword">let</span> right = <span class="call">createAnItem</span>()
<span class="call">print</span>(left == right)
</code></pre><br/><p>What’s really cool here is that both <code>left</code> and <code>right</code> hide all of their type information. If you call <code>createAnItem()</code>, all you know is that you get a <code>list</code> item back. And that you can compare that list item to other list items returned by the same function.</p><br/><h2>Opaque return types as reverse generics</h2><p>The Swift documentation on opaque result types sometimes refers to them as reverse generics which is a pretty good description. Before opaque result types, the only way to use protocols with associated types as a return type would have been to place the protocol on a generic constraint for that method. The downside here is that the caller of the method gets to decide the type that’s returned by a function rather than letting the function itself decide:</p><br/><pre><code><span class="keyword">protocol</span> ListDataSource {
<span class="keyword">associatedtype</span> ListItem: <span class="type">ListItemDisplayable</span>
<span class="keyword">var</span> items: [<span class="type">ListItem</span>] { <span class="keyword">get</span> }ƒ
<span class="keyword">var</span> numberOfItems: <span class="type">Int</span> { <span class="keyword">get</span> }
<span class="keyword">func</span> itemAt(<span class="keyword">_</span> index: <span class="type">Int</span>) -> <span class="type">ListItem</span>
<span class="keyword">init</span>(items: [<span class="type">ListItem</span>])
}
<span class="keyword">func</span> createViewModel<T: <span class="type">ListDataSource</span>>(for list: [<span class="type">T</span>.<span class="type">ListItem</span>]) -> <span class="type">T</span> {
<span class="keyword">return</span> <span class="type">T</span>.<span class="keyword">init</span>(items: list)
}
<span class="keyword">func</span> createOpaqueViewModel<T: <span class="type">ListItemDisplayable</span>>(for list: [<span class="type">T</span>]) -> <span class="keyword">some</span> <span class="type">ListDataSource</span> {
<span class="keyword">return</span> <span class="type">GenericViewModel</span><<span class="type">T</span>>(items: list)
}
<span class="keyword">let</span> shoes: <span class="type">GenericViewModel</span><<span class="type">Shoe</span>> = <span class="call">createViewModel</span>(for: shoeList)
<span class="keyword">let</span> opaqueShoes = <span class="call">createOpaqueViewModel</span>(for: shoeList)
</code></pre><br/><p>Both methods in the preceding code return the exact same <code>GenericViewModel</code> in this example. The main difference here is that in the first case, the caller decides that it wants to have a <code>GenericViewModel<Shoe></code> for its list of shoes, and it will get a concrete type back of type <code>GenericViewModel<Shoe></code>. In the opaque example, the caller only decides that it wants some <code>ListDataSource</code> that holds its list of <code>ListItemDisplayable</code> items. This means that the implementation of <code>createOpaqueViewModel</code> can now decide what it wants to do. In this case, we chose to return a generic view model. We could also have chosen to return a different kind of view model instead, all that matters is that we always return the same type and that it conforms to <code>ListDataSource</code>.</p><h2>Using opaque return types in your projects</h2><p>While I was studying opaque return types and trying to come up with examples for this post, I noticed that it’s not really easy to come up with reasons to use opaque return types in common projects. In SwiftUI they serve a key role, which might make you believe that opaque return types are going to be commonplace in a lot of projects at some point.</p><br/><p>Personally, I don’t think this will be the case. Opaque return types are a solution to a very specific problem in a domain that most of us don’t work on. If you’re building frameworks or highly reusable code that should work across many projects and codebases, opaque result types will interest you. You’ll likely want to write flexible code based on protocols with associated types where you, as the builder of the framework, have full control of the concrete types that are returned without exposing any generics to your callers.</p><br/><p>Another consideration for opaque return types might be their runtime performance. As discussed earlier, protocols sometimes force the compiler to defer certain checks and lookups until runtime which comes with a performance penalty. Opaque return types can help the compiler make compile-time optimizations which is really cool, but I’m confident that it won’t matter much for most applications. Unless you’re writing code that really has to be optimized to its core, I don’t think the runtime performance penalty is significant enough to throw opaque result types at your codebase. Unless, of course, it makes a lot of sense to you. Or if you’re certain that in your case the performance benefits are worth it.</p><br/><p>What I’m really trying to say here is that protocols as return types aren’t suddenly horrible for performance. In fact, they sometimes are the only way to achieve the level of flexibility you need. For example, if you need to return more than one concrete type from your function, depending on certain parameters. You can’t do that with opaque return types.</p><br/><p>This brings me to quite possibly the least interesting yet easiest way to start using opaque return types in your code. If you have places in your code where you’ve specified a protocol as return type, but you know that you’re only returning one kind of concrete type from that function, it might make sense to use an opaque return type instead.</p><h2>In summary</h2><p>You learned that opaque return types can act as a return type if you want to return an object that conforms to a protocol with associated type constraints. This works because the compiler performs several checks at compile time to figure out what the real types of a protocol’s associated types are. You also saw that opaque return types help resolve so-called Self requirements for similar reasons. Next, you saw how opaque result types act as reverse generics in certain cases, which allows the implementer of a method to determine a return type that conforms to a protocol rather than letting the caller of the method decide.</p><br/><blockquote><p>With great power comes great responsibility -- Uncle Ben 🕸</p></blockquote>]]></content:encoded></item><item><guid isPermaLink="true">https://chuynadamas.github.io/chuynadamas/posts/oh-my-zh-git</guid><title>Oh my zsh git plugin cheatsheet</title><description>A Cheatsheet for some git commands in ohmyzsh 👾</description><link>https://chuynadamas.github.io/chuynadamas/posts/oh-my-zh-git</link><pubDate>Tue, 7 Sep 2021 21:31:00 -0500</pubDate><content:encoded><![CDATA[<h1>Oh my zsh git plugin cheatsheet</h1><p>If you are using <code>oh-my-zsh</code> you can take advantage of some plugins like the <code>git</code> one, for this I'll list the most common commands that I use almost everyday.</p><h2>Some useful commands in the <a href="https://github.com/ohmyzsh/ohmyzsh/tree/master/plugins/git">git plugin</a></h2><table class="lzz-table">
<tr class="lzz-tr">
<th class="lzz-th">Alias</th>
<th class="lzz-th">Command</th>
<th class="lzz-th">Notes</th>
</tr>
<tr class="lzz-tr">
<td class="lzz-td">gb</td>
<td class="lzz-td"><code><span class="keyword">git</span> <span class="dotAccess">branch</span></code></td>
<td class="lzz-td">List all local branches</td>
</tr>
<tr class="lzz-tr">
<td class="lzz-td">gba</td>
<td class="lzz-td"><code><span class="keyword">git</span> <span class="dotAccess">branch -a</span></code></td>
<td class="lzz-td">List all local and remote branches</td>
</tr>
<tr class="lzz-tr">
<td class="lzz-td">gcam</td>
<td class="lzz-td"><code><span class="keyword">git</span> <span class="dotAccess">commit -am</span></code></td>
<td class="lzz-td">Add all files to stage and commit</td>
</tr>
<tr class="lzz-tr">
<td class="lzz-td">gcmsg</td>
<td class="lzz-td"><code><span class="keyword">git</span> <span class="dotAccess">commit -m</span></code></td>
<td class="lzz-td">Git commit message</td>
</tr>
<tr class="lzz-tr">
<td class="lzz-td">gco</td>
<td class="lzz-td"><code><span class="keyword">git</span> <span class="dotAccess">checkout</span></code></td>
<td class="lzz-td">Checkout spceified changes</td>
</tr>
<tr class="lzz-tr">
<td class="lzz-td">gco -</td>
<td class="lzz-td"><code><span class="keyword">git</span> <span class="dotAccess">checkout</span></code></td>
<td class="lzz-td">Change branch to the previous one</td>
</tr>
<tr class="lzz-tr">
<td class="lzz-td">gd</td>
<td class="lzz-td"><code><span class="keyword">git</span> <span class="dotAccess">diff</span></code></td>
<td class="lzz-td">Show differences in staging files/td>
</tr>
<tr class="lzz-tr">
<td class="lzz-td">gfa</td>
<td class="lzz-td"><code><span class="keyword">git</span> <span class="dotAccess">fetch --all --prune</span></code></td>
<td class="lzz-td">Fetch all remote branches, delete branch if upstream is gone</td>
</tr>
<tr class="lzz-tr">
<td class="lzz-td">gl</td>
<td class="lzz-td"><code><span class="keyword">git</span> <span class="dotAccess">pull</span></code></td>
<td class="lzz-td">Pull from remote</td>
</tr>
<tr class="lzz-tr">
<td class="lzz-td">gp</td>
<td class="lzz-td"><code><span class="keyword">git</span> <span class="dotAccess">pull</span></code></td>
<td class="lzz-td">Push to remote</td>
</tr>
<tr class="lzz-tr">
<td class="lzz-td">gpsup</td>
<td class="lzz-td"><code><span class="keyword">git</span> <span class="dotAccess">push --set-upstream origin[currentbranch]</span></code></td>
<td class="lzz-td">Set upstream branch</td>
</tr>
<tr class="lzz-tr">
<td class="lzz-td">gst</td>
<td class="lzz-td"><code><span class="keyword">git</span> <span class="dotAccess">status</span></code></td>
<td class="lzz-td">Local files to commit</td>
</tr>
</table><br/><p>There are plenty of them, but also you can create new ones open your <code>.zshrc</code> file and adding all the alieases that you want in the following format</p><br/><pre><code>alias [name]=<span class="string">"[command]"</span>
</code></pre><br/><p>Let see an example with some of my personal aliases</p><br/><pre><code>alias glog=<span class="string">"git log --graph --full-history --all --color --pretty=format:'%x1b[31m%h%x09%x1b[32m%d%x1b[0m%x20%s'"</span>
alias glog1=<span class="string">"git log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset)%C(bold yellow)%d%C(reset)%n''"</span>
alias gpullall=<span class="string">"git pull --all"</span>
alias gconflict=<span class="string">"git diff --diff-filter=U"</span>
alias gconflict=<span class="string">"git diff --name-only --diff-filter=U"</span>
</code></pre><br/><br/><p>Once you add all the alias that you need, you have to reload the source of your terminal with <code>source ~/.zshrc</code> and then you are ready to go! 🐱 && 🐙</p><br/><blockquote><p>Space: the final frontier. These are the voyages of the starship Enterprise.Its five-year mission: to explore strange new worlds; to seek out new lifeand new civilizations; to boldly go where no man has gone before. -- <cite>Captain James T. Kirk</cite></p></blockquote>]]></content:encoded></item><item><guid isPermaLink="true">https://chuynadamas.github.io/chuynadamas/posts/subscript-dictionary</guid><title>Subscript a Dictonary in Swift</title><description>How to subscript a dictionary in Swift ☄️</description><link>https://chuynadamas.github.io/chuynadamas/posts/subscript-dictionary</link><pubDate>Mon, 6 Sep 2021 21:39:00 -0500</pubDate><content:encoded><![CDATA[<h1>Subscript a Dictonary in Swift</h1><h2>The power of subscription in swift</h2><p>The dictionary are a super helpful tool given by foundation in swift, but we can make it even powerful with the powe of subscript, let see the example with the current user here in the site.</p><br/><p>I'll crete a new dictionary with to handle the color of my labels, something like this:</p><pre><code><span class="keyword">private struct</span> Utils {
<span class="keyword">static let</span> tagVariants = [
<span class="string">"Article"</span> : <span class="string">"variant-a"</span>,
<span class="string">"Assembly"</span> : <span class="string">"variant-b"
"Swift"</span>: <span class="string">"variant-c"</span>
]
}
</code></pre><br/><p>This is a pretty simple dictionary but every time we wan't to use any variant for the color in the css we have to call something like the following <code>Utils.tagVariants[safeKey: tag.string]</code> this is <code>O(1)</code> but the result will be an optinal string <code>String?</code> becuase could be the scenario with the dictionary fails triying to find our value.</p><br/><p>In that se have to unwrap every time we use in our code, to be sure the key already has a value</p><pre><code><span class="keyword">if let</span> actualValue = <span class="type">Utils</span>.<span class="property">tagVariants</span>[<span class="string">"Article"</span>] {
<span class="comment">//Do the rest...</span>
}
</code></pre><br/><p>This is a good practice but if you are a little bit lazy like me we can make a safe access for the subscription, something like this</p><br/><pre><code><span class="keyword">import</span> Foundation
<span class="keyword">extension</span> <span class="type">Dictionary</span> <span class="keyword">where</span> <span class="type">Key</span> == <span class="type">String</span>, <span class="type">Value</span> == <span class="type">String</span> {
<span class="keyword">subscript</span>(safeKey key: <span class="type">Key</span>) -> <span class="type">Value</span> {
<span class="keyword">get</span> {
<span class="keyword">return self</span>[key] ?? <span class="string">""</span>
}
}
}
</code></pre><br/><p>With that every time we use our new function <code>[safeKey]</code> we are ensure that the result will be a value, and if the tag doesn't have any style we need to be sure that we have an associated type in our current dictionary.</p><br/><p>As an example now we can use the following way to acces our variants!</p><pre><code><span class="type">Utils</span>.<span class="property">tagVariants</span>[safeKey: tag.<span class="property">string</span>]
</code></pre><br/><p>Just directly without using any <code>guard</code> of <code>if let</code> logic. This is faster, but also cames with a great responsability because you have to be sure <br>that all the values that you'll use have to be in your ditionary in other case you won't have a crash... Yes, sometimes crash are good, they can help us to find some holes in our code.</p><br/><p>With great power comes great responsibility -- Uncle Ben 🕸</p>]]></content:encoded></item><item><guid isPermaLink="true">https://chuynadamas.github.io/chuynadamas/posts/hello-sillicon</guid><title>Hello Sillicon</title><description>How to do a hello world in assambler for M1 Mac 💻</description><link>https://chuynadamas.github.io/chuynadamas/posts/hello-sillicon</link><pubDate>Sat, 28 Aug 2021 21:39:00 -0500</pubDate><content:encoded><![CDATA[<h1>Hello Sillicon</h1><h2>How the computer works</h2><p>In this is post I'll talk about how to compiler assambler code to create a <code></code><code>Hello World</code><code></code> in M1, this code is following the course of the <a href="https://www.amazon.com/Programming-64-Bit-ARM-Assembly-Language/dp/1484258800/ref=sr_1_1?crid=34ED002YD0Y9Z&dchild=1&keywords=programming+with+64-bit+arm+assembly+language&qid=1610126434">Programming with 64-Bit ARM Assembly Language</a></p><p>Below is the code that you can find the book</p><br/><pre><code><span class="comment">//
// Assembler program to print "Hello World!"
// to stdout.
//
// X0-X2 - parameters to linux function services
// X16 - linux function number
//</span>
.<span class="property">global</span> _start <span class="comment">// Provide program starting address to linker</span>
.<span class="property">align</span> <span class="number">2</span>
<span class="comment">// Setup the parameters to print hello world
// and then call Linux to do it.</span>
_start: mov <span class="type">X0</span>, #1 <span class="comment">// 1 = StdOut</span>
adr <span class="type">X1</span>, helloworld <span class="comment">// string to print</span>
mov <span class="type">X2</span>, #13 <span class="comment">// length of our string</span>
mov <span class="type">X16</span>, #4 <span class="comment">// MacOS write system call</span>
svc <span class="number">0</span> <span class="comment">// Call linux to output the string
// Setup the parameters to exit the program
// and then call Linux to do it.</span>
mov <span class="type">X0</span>, #0 <span class="comment">// Use 0 return code</span>
mov <span class="type">X16</span>, #1 <span class="comment">// Service command code 1 terminates this program</span>
svc <span class="number">0</span> <span class="comment">// Call MacOS to terminate the program</span>
helloworld: .<span class="dotAccess">ascii</span> <span class="string">"Hello Sillicon!\n"</span>
</code></pre><br/><p>Also we need to create a make file in order to compile our code</p><br/><pre><code><span class="type">HelloWorld</span>: <span class="type">HelloWorld</span>.<span class="property">o</span>
ld -macosx_version_min <span class="number">11.0.0</span> -o <span class="type">HelloWorld HelloWorld</span>.<span class="property">o</span> -lSystem -syslibroot
`xcrun -sdk macosx --show-sdk-path` -e _start -arch arm64
<span class="type">HelloWorld</span>.<span class="property">o</span>: <span class="type">HelloWorld</span>.<span class="property">s</span>
<span class="keyword">as</span> -o <span class="type">HelloWorld</span>.<span class="property">o</span> <span class="type">HelloWorld</span>.<span class="property">s</span>
</code></pre><br/><p>Also please take in note that we need to install Xcode 12 at least with the compiler tools. Once we did that just open the folder in the terminal and run the following code</p><br/><pre><code>$ make -<span class="type">B</span>
</code></pre><br/><p>the <code>-B</code> is just to force the compiler to recompile even if the code doesn't change, so you can skip it if you want. Then, if you run the executable you have to see the following</p><br/><pre><code>$ ./<span class="type">HelloWorld
Hello Sillicon</span>!
$
</code></pre><br/><p>And that's it this is our first program in assambler with M1 chip! 🚀</p>]]></content:encoded></item></channel></rss>