 I'm Jae Yoon, I'm Jae Yoon, today I'm going to talk about, well my talks in a revolve around, Swift literals, so it's Swift literally, sorry. So what is literal? So this will be really basic but you guys will be coding Swift forever. So this is literal, right, just type 42 to X code or playgrounds, it's literal. What kind of literal is it? It's actually an integer literal, alright. The reason why I say it's an integer literal is because there are other types of literals, float literal, string literal, boolean literal. And of course our famous Neo-Letro, which a lot of people don't realize it's only added in Swift 1.1 onwards. I was there from day one, like from Swift 1.1 and they were having problems with Neo being nested into an optional, like say if you do int, question mark, question mark, if you assign a Neo, it becomes a song as an SOM. So it's a valid Neo value, which doesn't make sense. And the only way it could overcome it was to actually invent Neo-Letro. A little bit of demo. Close it from here like that. Close it? Even if you need to close this window, you can close one there. Yeah, obviously. No, not happening. I think I need to move it across there, you know what I mean? Yeah, it's not mirroring. It's fine. I think it's just a normal mirroring, right? Yeah, I cannot. As you can see, it says 42, right? But that's the only type of literal. Can type literals in hex two? That's one. Oh, it's 42, too. Ox, as well. If this is really boring, I promise you there's a payoff error. Oh, it's 42 in octaves. Yeah, it's 42, too. Anyway, so these are all integer literals, but different ways of representing them. Some interesting things about literals. A literals is a source code representation of your type, right? So your value is actually represented in text, hard-coded into your source code. Now, to wrap your heap around that, say I have a float value, right? 42.0. And I get 42. So I ask you, so what's the precision of this? So if I cast it to a float, it'll be a single-body precision, right? Extend it. So what do you think this will be? So it's actually cast, because it's cast into a single-body precision. I wonder if I change it into a double. It gets extended. So what is the precision of the vitro? It's actually infinite. As long as your text file or your source code can store these values, it has that precision. It just gets truncated when it's cast into a barrel. Now, that's a very interesting thing to say, right? Because when you assign it, a compiler actually then tries to infer its type. So even if you don't put anything here, this is what a suit compiler might be called. Which means this type is actually different from this type. This is a swift type, but this is a literal type. And that's why your float literal has infinite precision, right? Now, if you're a good engineer, you would have swapped a mistake here already. This will give a compiler error. Now, what does that mean? It's because all these literals give enough information for the swift compiler to find out what type to cast it into. But for Neil, it needs two types of information. He needs to know what kind of optional it is. He knows it's an optional because he can't be new. But what type of optional it is, right? So if you give it another information here, like, oh, it's an int optional, this will work. Full optional, string optional, boolean optional. This reinforces the idea that this type is not the same as what you see here. This is compiler infer. Those are the only scalar literal types, but there are complex literal types like an error, literal. And it's somewhat like the new literal in the sense that it's not enough information, but it can infer it from whatever you type of. So here, the compiler is inferred. There's not only an error, but it's also an int error. And likewise, this is a dictionary literal, the compiler inferred that it's a dictionary that's deep with a string, and the value is boolean. So if you really think about it, all the other literals you see, the literal alone was enough, sort of enough to give the information. But here, you need two types of information, and here you need three types of information. That's it. There's nothing else to talk about Swift literals, literally. But if we're talking about it in another language, I'm done. It's time for me to sit down, but a Swift is amazing, right? So here's the rest of the talk. So today, my talk is about literal converter books. So not literals, a Swift literal converter. So what are Swift literal converter books? Back to this slide, as you can see, we now know that a literal type is different from a Swift type, right? We can coax it. So here, when we say, ah, it's a book, it'll cast it in a book, it's a double, and it'll cast it in a double. Not that it really matters here because, you know, a future literal doesn't have precision. But does this work? Can you assign 42 to a string? And does this work? Can you assign a float to an inch? Let's find out. Ah, you need to like... Josh, you've got the mirror. Is that pasta? Yeah, yeah, yeah. Okay, I'll do that. You can take it from your side. You can actually take it from your side. You can actually take it from your side. Okay, tapping around. Yeah, we can. So we asked ourselves just now, right? Can we do this? Obviously, you know. But can we do this? No. Can I do that? Can you do this? You can. Why? The answer is something called an integer literal converter book. And an integer literal converter book is actually a protocol. The int type conforms to this protocol. And all this protocol has is just an integerizer. And take note that the integerizer takes an integer here. But you can apply it to anything if you think about it. Anything that takes a protocol can take an integer literal if you apply it. This protocol int conforms to int integer literal converter book. Now this. We know that word, right? And that's because float conforms to integer literal converter books. And double also conforms to integer literal converter books. Alright, let's find out. Playground demo again. So this is for people who don't really dive into code that often. So let's do this. This is how I find out everything anyway. Jump. Alright, so this is the actual standard library. So I like a bit, right? Int itself is not conformed to integer literal. This thing called the sign number type conforms to it. But int then inherits this protocol. Alright, so that's because the reason why it's done I guess is because there are many types of ints. There are unsigned ints there are ints. Then there's int 8, int 16, int 32, int 34. And they all separately conform to integer literal convertible elsewhere. And then they all get absorbed under the int type. But the double is more straightforward. You can see the next engineer in the float here. And you can see struct int. There's nowhere here and anywhere else. The int guy conforms to float literal converter books. And just by not performing, you cannot assign a float literal to an integer. That's it. That's all that is behind it. There's no magic. I mean, this is magic. But that's the only magic. What actually happens is when you conform to a protocol, the compiler is a guy that goes around checking, ah, hey, there's a literal here. I wonder if I can find out what the type is. It actually looks at everything in your code. And in the standard library, for types to cooks, whatever literal you assign int to. I mean, you can't find it. And as we know, those are the reasons. Why? All these checks are non-linear compilations. So you can argue that they are actually special case protocols. Why do I call them special case? Because these are the only type of literal convertibles that you can have. You can never write your own literal convertible. This is hard-wired into the compiler. So every time a compiler sees an array, it's going to look for array, literal convertibles for booleans, for dictionaries, let's get this one, for floats, integers. Every time it sees this, it'll hand for everything that compiles to this and see if it can assign. And if it can't, it will just break it. All right. These three are interesting. These string literal convertibles, and I'll explain why later. Actually, just to tell you briefly, string literal convertibles conform to, it's like a super protocol of this guy and it's a super protocol of this guy. I'll explain why later. Now, this is quite interesting and this is very different from other languages because you would think something like literals are hard-coded into the compiler on the language. But it's not because CribLatnus vision for Swift is to have a very small core language, very small set of features that they implement in a compiler with a really large standard library implementing the rest of the features. And we find something that's usually, and I believe probably still in every language out there, that's fundamentally hard-coded. It's actually implemented in protocols using Swift. That's how deep down you can go just by looking at a standard library and find out why things are behaving a certain way. So are they useful then if you can't make your own literal convertibles? They are useful because you can apply those protocols. You just can't make your own. So how are they useful? What if I told you that hard-coding always means you're using literal convertibles? Think about it. Every time you write a hard-coded value, it actually goes through a literal convertible somewhere. So you can probably infer what this guy does. You think, oh, hard-coding is bad, right? Good engineers don't hard-code. They make everything dynamic. But I'm telling you, good engineers do hard-code. In fact, good Swift engineers religiously hard-code nil where they belong. Because Swift is a safety type language. This doesn't work. We're trying to do this. We tell this to remind ourselves this guy can be nil. And here we are hard-coding a value already. If you put this in a class and you don't do this, the compiler puts it in for you anyway. So who conforms to nil literal convertible? The optional guidance. So this is just in text sugar for what gets transformed into this guy. If you look into the SDK, you can see very clearly nil literal convertible just needs this initializer. And then you can do something like this sort of assignment. It's not as widely used as you think. The only other types that conform to nil literal convertible are actually pointer types. So unsaved pointer, unsaved muleable pointer. When nil actually does make sense in those contexts. So it's not like, oh we have nil now, let's abuse it everywhere now. It's only optional pointers. That's the only place you can do something like this. The other really common one that we know and love is the every literal convertible. And Swift 1.2 introduced something called set. And you're like, ah, sweet. I can assign them like, you know, I can use the same text. Do you guys know what actually happens when you do that? I'm sure you do, but... Let's just pretend we don't. So here we initialize a to carry. Now using the same literal, you now initialize a set. If you notice, one is missing, because it's a set. It's like, oh, why is that happening? Just because a set is set and things cannot be repeated, they are unique, right? The interesting thing is, it's actually using every to initialize set. So you can think of it as same text you get, right? There's no hard coded set in the truth. So, you know, the language God said, ah, things are fine. If there are some unique stuff, we'll just pull it out anyway. This is such a nice syntax. We don't invent another natural code. And here we are. And the reason why we can do this, using this somewhat idiomatic way of initializing sets is because they decide to, you know, implement this protocol on the set type. Okay, but... So, right? Well, that means if you have any collection types that you write yourself, and you think, hey, actually, you know, it'll be really sweet if I can initialize it with an array. I'm saying you cannot. So here we have a very contrite queue from what it is. It's very straightforward, right? Create a scrub. It's backed by an array. I recommend it. It's actually very inefficient. This is just for adagogy purposes. I push a value into the queue. It depends. I popped it. It takes out the first. So it's a queue, right? It's first in, first out. Which counts the array animals. How do you use it? So the only way to... How do you use this line? So say I create an initializer. It just takes an array, right? We've done these heaps of times. We create our own collection types. We write any function, and this is how we construct our collection. And because we made it generic, we can take screens, and take whatever we want, as long as they're all the same type. This is kind of verbose, right? I mean, the queue is pretty straightforward. If I tell you, oh, this is a queue, you can immediately imagine, ah, this is the first guy, this is the second guy. I can imagine this is a queue. So all we have to do is just implement this protocol, and then queue conform, and you can immediately do something like this. And the compiler knows how to refer type as well. So this is really... All in this is actually just syntax-sugar. You're saving this amount of characters. But when the mental model of a literal really fits the type that you're trying to make, it makes a lot of sense to do it like that. Anything hard. That's interesting. That's if I make my own type though. Can I extend existing types? Can I... Can I write NSURL and just assign a string to it and create an NSURL? And if you go online, you'll find this article by our Matt Thompson at NSHipster. And he'll show you some of these. If you make NSURL conform to string, you can do something like this. You can immediately extract holes out. And you would get this back. Wow, that's insane. All you have to do is just extend. When you start digging into the article, it's like, hang on, this doesn't really look like a string literal convertible that I know. It's because it's been deprecated. All right. These APIs are all deprecated in Swift 1.1. Two years ago, it was 2.2 region. They stopped, I'll explain why. All right, so this was Swift 1.0. Any type that implements these two functions can take strings and initialize itself or something. From Swift 1.1 onwards, we turn it from that to this. I think, oh, why can't I do that though? Why can't I just extend NSURL with my init? And if you know enough about Swift, you actually can't do that. You can't extend any class, even your own class, with initializers, because it's... They want to guarantee that any initializer that you implement will be used by a subclass, and when you extend, you break those guarantees. They're coming back to that? There you go. So it's still exciting. So it's very unfortunate that we can't extend existing classes because we can't write initializers in extensions. So is this too useful? Let's try to make it useful. So everyone has done this. I can't extend it, but I can subclass it and then conform on to it. Does this work? Yes, it does. This example, you implement these three functions and you can do something like this. And it behaves the way we expect, because it's a subclass of NSURL, we can extract figures like that. But we can't do .close or .skill because this is a string. Is it useful? Is that useful? I don't know. How about this guy? Well, I've done this heaps of times. My designer comes along and said, no, I don't want bright red. A little bit of green and a little bit more of blue. It's like, okay, we write something like this. It's really long, right? You think about it. What is this, right? This is a string. But what is it a string of? It's a string of Hexa decimal characters. It's a 24-bit integer encoded string. Why are we encoding integers in strings? Why can't integers be integers? Sometimes we put hash here. Hash means number. It's a number. We are using strings. We can make this into a string literal comfortable. What about making it into an integer literal comfortable? So we can do something like this. We can say, all right, let's take a value and we do some bit shifting and we hard-code the fact that these two numbers are always red. These two numbers are green and these two are blue. And we can initialize colors like that. This looks pretty clear to me. Bonus is they don't this one compile. They are because there's r and r is not Hexa decimal digit. Isn't that better than this? So now you get some sort of type checking there as well because you are initializing something that's represented by numbers as from numbers. There are downsides. First, you hard-code the fact that there's always red green blue. What if I want alpha and r? And if it's bigger than a certain number than maybe as an alpha, that's weak. What if I wanted to be a different order? rgb is just one order. There's in video I think there's red blue green as well. Lots of fancy other CMYKs and all that. But here it's locked down to one representation and you always initialize it in rgb. This is another contrived example and this is the next contrived example. This is a very retro-comfortable example. And we think of the moment we think of areas we think about collections actually an annex index path is kind of like a collection. It's a collection of two integers always two. That's pretty easy. So, I've typed this tons of times especially if I'm hard coding static table and this auto-complete always fails. I don't know why. Every time you type photo nothing shows up. That's because it's a UI kit edition and somehow the compiler doesn't like going there. I don't care about editions. So I always have to look this up in the documentation and paste it. But I don't have to if I initialize it that way. And you can access it like you normally do because only the constructor was paid for when you solve that with every neutrals. So if you think about it it's just syntactic sugar for all four times like when you forget or it doesn't map well to your brain or constructors are bubbles and the literal is very very clear and as long as the types match up as you can see here you have to tell your class you have to tell your class what type it is so it unwraps this guy and gives you a verity function so I can't send floats in there because I already type a cast in here and as long as they match up it will work. What if I only gave one value what is the index half with 1 in mean it doesn't mean anything so maybe initialize it with 0 what about those with 3 or 3 makes sense there are index paths actually a lot of people don't know but index paths can go on forever since we are used to section and row so those mean something to yes here's a weird one it's weird because it's missing a word electro it's also weird in other ways because it's not a literal convertible because it doesn't really have much to do with literal directly it's actually used by the string literal convertible protocol now say I have this enum it's a zodiac and say happy year of the monkey year or whatever I have these prints my set string is my raw value my base representation any guess what does this print no guess why okay so my guess is the monkey modicon right you can tell it's wrong already it prints the name of the enum why it's a string in this protocol and the only class that interments it is string what actually happens when you put an object of a certain type in an interpolated syntax whatever you call it it tries to find out what type it is and obviously zodiac is not here I wrote it so it forms back when it forms back and it will print the enum's name so even if it's it can be any base right it's based in aint, base in whatever as long as it detects its enum it will actually print the name of the enum rather than what's underlying it but I want a raw value of how do I do it so remember I said you can't extend you can't extend initializers right but you can overload them I can overload another initializer it takes a zodiac and I say when you see this guy print a raw value and assign it to myself so the way it works is every time the compiler finds interpolation it will try to find out what it can convert how to convert that into a string and here we are telling it to go back to the string turn it into a raw value what's the raw value? this guy then hits another function that you saw earlier that conforms the string and then it checks out so if you have some fancy types that you put in your interpolation console output or whatever wondering how do I get it to print I don't want to type raw value everywhere you can hijack the string interpolation and override here okay so when you use it all sounds useful maybe not useful but if you think about it all of this is syntaxed so every time you find it's a pain to initialize something using constructors or whatever you just want to initialize it in literal you can always fall back on because that's literally what the standard line reduced to initialize its own types from the troops what does this mean I mean this is interesting in another way it's useful for DSLs and why do we name DSLs now the amount of times you type cgpoint bracket xy and the amount of times you type cgpoint made cgpoint zero if you make a type called point a struct conforms to an area which is literal convertible you can do this and this is what I mean by DSL because it's math we know that if it's a point this makes sense we don't need some structural constructor describing exactly what it is so it really makes sense here in this sense, so as a math DSL this makes sense likewise with a matrix when do I hard code well you do hard code because origin is always zero zero and identity the 2D identity matrix is always one zero zero one so when you write a game you can initialize it that way likewise with programming representations because we think of regex if you've done enough regex you can actually do this or maybe not, you still rely on some help but this contains enough information about the regex you don't have to decorate it with start with and if the stream itself encodes all the information you need in circumstances like this imagine a regex type and then regex to check whether it's a conforming kind of email you can just initialize it that way and it makes sense how it makes sense for URL so the URL stream itself has enough information to tell you what it is a package for instance if you've done enough not so much in Swift but like Ruby, Python even go now this makes sense to you which major, minor, patch version compatible with this is a VSL and even anything I don't know how often you guys play NS character sets I do when I'm checking trying to strip characters and all that initializing NS character sets has to be one of the most most part of the Cocoa API and when I saw this example I'm like why can't we have this it's a bit like seeing this for sets when set first came up it's like ah shit I have to use a constructor to keep typing all these values in then when you you can assign it as an area it's so much cleaner likewise here you don't lose any information writing like this doesn't make me understand it less it clearly is a character set like a set but with characters so what do I mean by why is this important I think this is an interesting phase we are moving into with Swift Swift 3.0 is coming out open source and we are starting to see it on the command line thankfully I lined up this top with this gender so I could make a case for text driven ways of using Swift in this case scripting and this is helping you output so you look at a Swift package manager now and this is all not for me and this is their example on Apple sorry not Apple but more on the Swift and you are creating this package struct I mean with these values and these are enums with these associated values I mean anyone coming from Ruby this is just absolutely insane just to specify packages I don't know maybe with Swift you can condense it to something like this that's a really stark difference the readability of this guy and this guy and it's not hard right this is an area of dependencies it looks like enum so this make this guy conform and you will know how to parse this guy so yes it's leading to things like URL nature version or whatever or maybe like compatible with maximum, minimum requirement or whatever and you can encode it in a string BSL GitHub from Apple it must be version 1.0 or anything compatible with 1.0 right maybe it will work maybe it will not who knows right and I'm not making this up right if you use cartage this is exactly the syntax they use I took this from cartage and enough people know cartage to understand this so it's not like ah you have to invent all this new new conventions to learn increasing the learning curve unless that DSL is a widely known DSL like math everybody learns math before they learn programming so it's actually more painful to learn oh I can't use brackets I have to use point bracket to initialize a point so in this case this is another widely used DSL that makes sense in this context and I would think it actually reduces the learning curve if you use it right um which is crazy right like if you think about it we are the only language that uses something this verbose to initialize packages you look at Ruby Jam no not like that Python, Py, not like that go get this not like this anyway so if it's open source so go ahead and contribute a stream with trope compatibility one um that's all there is to it so questions if we can convince them to answer question on the set yes no actually it doesn't recognize it at the literal level it's actually syntax sugar for so when you do that right it then looks at set and it actually converts into a set constructor so it passes those values into a set constructor and then the set initializes then feeds out the value so the function so it's not the compiler the set itself I think they do it should be hash hash is also yeah so if you so okay let me just jump back to the area for the most I'm not here not here so what happens here right the compiler actually takes apart whatever you wrote up here and puts it here so when you initialize a set like that it actually goes in it elements 1, 2, 3, 4, 1 it's still there is it hashable? no no this guy yeah so I'm I'm 100% sure that set uses hash so it must conform yes and then you get scripted up in here of course after checking hash good question thanks you're done