 OK. Sorry for the delay in starting. I had a hell of a time setting up my laptop died last night. Apologies. I'm here to talk about static and dynamic typing crystal. And is it the best of both worlds if we can have both a mix, Mae'r cwmparau'r beth sydd gennych ddeunam iawn, a dyna'r cystalwyr yn byw i'w ddeunam iawn. Rwy'n gweithio'r ddeunam iawn i'r ddeunam iawn i'r ddeunam iawn. Dydy'r gwasanaeth fydd yn dweud o'r ddweud o ddeunam iawn. Mae'r ddeunam iawn i'r ddeunam iawn i'w ddeunam iawn, o ddweud o gwasanaeth iawn i'w ddeunam iawn, argymwys i'r canol i'r IRC ac yn ymddi'r list. Ond rwy'n rwy'n gweithio'r cyfle o dynami ac yn dynami. Mae'r dynami'r llangwyddiad yn ymddi'r lles o'r dynami. Rydych yn dynami'r llangwyddiad yn ymddi'r llangwyddiad, yn dynami'r llangwyddiad yn dynami, mae'n dynami'r python, rwy'n dynami'r rubi. A'r dynami'r llangwyddiad yn dynami'r jarfos, mae'n rhaid i'r llangwyddiad yn dynami. Yn ymddi'r llangwyddiad yn dynami, ond rhaid i'r llangwyddiad yn dynami, ond rhaid i'r llangwyddiad yn dynami, rwy'n dynami'r llangwyddiad yn dynami. Ond rwy'n gweithio'r hynny, y byd y dystyn хотiau yw gyda'r bydweithydd. Rydyn ni'n gwneud o fynd i dyn nhw ydych chi i fynd i dyn nhw a dyn nhw i freflau'r language.hala hwn yn ddwych y bydwch chi i dyn nhw wedi'u perffaith mae gwneud o feithio ar gyfer blaen Yn Croeddon yn gwneud yn dyn nhw. Roedden y gwnau yn Dyn nhw i dyn nhw i dyn nhw i dyn nhw i dyn nhw i dyn nhw. Byddwch nhw'n mynd i ddaeth bod hynny yn dylwnol yng Ngwyll מף, rydych sinol eraill yn ei ddod am gweithio. Felly mae'n ddigon nhw'n gweithio mewn gwahod y baedd yn y ffordd yn ffordd yn gweithio wath ymateb. Gweithio maen nhw'n olygu'r ddweud yn gweithio at teniol yn cyfnodol hefyd. Nid oell service yn yng Ngwysyffydd, yw CHP, mae ei ddweud ei ddweud am yr hun a nad yna lle ei ddwy yces i ddweud nhw. Mae'r gwahan y mae'r hwn yn ei ddweud nhw. A lot of people like that, a lot of people like that and sort of the repel style, repels are harder to do in statically typed languages. So dynamic code reloading is another thing which is a lot easier in dynamic languages than statically typed languages. Easy to create complex DSLs because often typed systems are a little bit stuck in their ways. They can't be flexible enough to represent complex DSLs or often you get some crazy generic crap to represent your DSL. And sadly a lot of people write in dynamic languages, they have an API and JSON that they emit and it's really not easy to use APIs that have been made in dynamic languages in statically typed languages. Because you have JSON objects for example, it's hard to create types for those JSON objects if you haven't thought about the types beforehand. And in the dynamic languages obviously you don't have to think so much about the types and it can make it harder to do. For statically typed languages you have a promise that it works first try. Obviously that's not catching all errors. There's a lot of logic errors, a lot of other errors, different error types which statically typed languages can't detect. But you can get stricter and stricter type systems which detect more and more of these errors. But for a lot of statically typed languages it's mostly typos and everyone makes a lot of typos. So it does actually detect quite a lot of errors. It's easier to create tooling in static languages because your IDEs, your compiler, all of the different tooling for language can agree on a way to work out the types of every variable. In Java for example it's very easy to work out the type of variable because it's written right next to it almost all the time. That's another form of verbosity where it helps the tools but it doesn't so much help the programmer. So yeah you have a set of rules to work out the types. It's easier to write optimizers for static languages, statically typed languages because you have a little bit of a better idea of if you know exactly which types of variable can be. You can have a much better guarantee and optimizers are limited, code optimizers are limited by the edge cases not by the common case. So if you can remove all the edge cases of your code by having statically typed more guarantees then you can write better optimizers right the more easily. And a human aspect statically typed, static types can help guide you towards cleaner code. They can help you to write cleaner code because you have to think about it a little more. You have to think about how things are structured, what names you're going to give things, a little more than in dynamically typed languages. And of course typed documentation as well. If you've got a big code base especially with newer onboarding and new developers then it's a lot easier for them to navigate around if they know the types of everything. And it helps them to spot patterns and look at the documentation above each type and they can quickly navigate around the code base. So recently in recent years a lot of languages have tried for a static more hybrid approach. We've seen that with typed Llewer which was presented a couple of presentations back. The examples I've got here are Python type annotations. Python has recently introduced type annotations to the language. They are easy to add to existing code bases incrementally. And they're easy to add to existing code bases incrementally. And I haven't used Python so I don't know too much about them. But the type checking is performed by Linter which is external to Python. You're not compiling your Python into non-typed Python. You're checking it with an external program which is unrelated to the Python interpreter. So it doesn't have to be 100% accurate. There are holes in your type annotations. You can always decide not to annotate something if you want to do something fancy. It doesn't have to be 100% accurate and that doesn't mean you have 100% confidence in your type system. You don't have 100% confidence in your types in your code. Obviously it means you can't perform optimisations based on the types because you don't have any guarantee that the types are actually being obeyed when you're running the program because it's done by an external checking tool. Another approach to that is TypeScript and Flow which are essentially typed JavaScript. They're different types of typed JavaScript so they're also easy to add to existing code bases incrementally. You take your JavaScript, you add type annotations, it tells you where you've messed up. And this time type checking is performed by Compiler. So you have the TypeScript compiler, it takes TypeScript code and it emits JavaScript. And this means that you can influence code gen. TypeScript actually doesn't do this. But you can have your types in your typed JavaScript influence the JavaScript code which is generated. And you could perform optimisations based on this. And so TypeScript and Flow are very interesting because they've developed very complex type systems to model JavaScript. They've done a lot of work on pushing the boundaries of how to make a type system describe a dynamically typed idioms very well. So for example, Flow typing, Union types, TypeScript has Intersection types which are very interesting. And all these different innovations which I'm going to cover some of these later when I talk about Crystal finally. Because Crystal has some of these too. But it's very interesting to look into TypeScript as a person who's interested in type systems. And they've done a good job. So yeah, Flow typing, Union types. But it still has a hole. You don't have to type everything because you still have to support the old JavaScript. You still have to support interacting with things that you can't type. There's a lot of code out there which you can't type in TypeScript. You'd have to create a crazy complex type system to do it. So you have the Any type which means just give up. So the TypeScript compiler doesn't do any checking. So you can't be 100% confident in any code which uses any. So this brings me to Crystal which is what I work on. I'm a core developer with the Crystal programming language. It's been around for a couple of years now. Ben, if you've heard of it before, good. That's why you're here. So a bit of history about the language. It started as an attempt to compile something very close to Ruby. It's close to Ruby as they could make it. It was never an attempt so much to have a typed Ruby. It was intended to stick as close to Ruby as it possibly could. It started back in 2011 or 2012. A bunch of guys down in South America, Harry and... They did a very good job in the early days of sticking very close to Ruby making Crystal very accessible to Ruby developers. But Crystal chose to break with Ruby in a couple of key areas which sets it apart from TypeScript and Python type annotations by expanding beyond the language that we were influenced by and creating a programming language which is unique in its own ways. For example, if you have an empty array and you access the first element in Ruby, you will get nil. In Crystal you will get an exception. Obviously, because we're strict about nil in Crystal, if every array access could return nil, depending on the length of the array, then you'd have to check for nil every time you do an array access. This will make your code a lot longer. We decided the only way to solve this is to raise an exception at runtime if you try and access an array element which doesn't exist. In Crystal it just returns t, the type of array. We've removed some of the warts from Ruby as well, like postfix while. I don't think anyone needs a postfix while. It's very confusing. We've added some new things. We've also got flow typing in untypes. It's quite easy to create beautiful DSLs in Crystal. We don't have any holes. Everything is completely typed. There's no escape hatch into not being able to type something. You can trust the pipe system completely because you can't escape from it. We're going to go over a few examples of the type system. We like to think of Crystal as compile time duck typing. You have an example here of a twice function. It's just x plus x. The plus operator is implemented on numbers and strings. If you type twice of one, then you get two. Twice of high, you get high high. This function doesn't note any types, but it's still completely statically typed. This is implicitly a generic function. The same way you have duck typing in Ruby, if it looks like a duck and it cracks like a duck, it probably is a duck, then it works pretty much the same way, but the duck typing is done at compile time. You can be completely certain there's no errors. What is the type of x here? Is it a number or a string or what can it be? Under the hood, what we have is we generate two functions. The example twice function is actually generic. It's implicitly generic. If you give twice an int, it will return an int. If you give it a string, it will return a string. This creates two different functions. Two different functions implementations at the typing time and at the compile time. You have essentially two different functions, but they're represented by the same source code. It's generic. We have complete type safety. If you try and do twice true, you get a nice little error and find method plus for bool, because all our operators are methods too. You can actually get a really nice long error if you want, which gives you even more details of where it noticed that you were passing a bool and it can find where your boolean came from. You get lots of options for nice errors. We have type restrictions. If you type restrict your argument X to int32 or string, this is introducing union types. You can specify a type which can be either an int32 or a string, so a 32-bit integer or a string. This restricts it so that you explicitly say that this function twice can only take integers or strings. You get a slightly nicer type error if you do that, because it doesn't have to go through and find out where you've made the error. It can just say you passed in the wrong type of function right away. A bitter example about unions. You have the gets function. It gets a string from the terminal. It can return the string that you typed in, or if you have an EOF, like you press Ctrl D at the terminal, end of file, it can return nil. If you write this code, hello, what is your name, hello, your name, you get an error because gets can return nil. A way to solve this, get returns string or nil, we have flow typing. If you assign your name to get, you can check whether a name is nil, and the compiler will infer that inside this if branch, name cannot be nil, name cannot be the nil type. Then you run this code again, because you've essentially said to your compiler, if the end of file case happens, and if gets returns nil, then we will do nothing. We will not print any string at all. That will compile, and you save yourself a bug. You have this function Cromulate, another example of flow typing. Here we have a perfectly Cromulant function. If you give it a string, then it will take the third character of the string, or if you type in a number, then it will give you two thirds of that number. It's a bit of a weird function, but it's a weird example. This will actually give you... What I'm trying to demonstrate here, is that the value can take a different type, depending on how you've restricted it. Obviously the indexing for the third value of value will not work if it's in 32. If you restrict value to a string, then obviously you can then do that indexing operation, and if you restrict to an int 32, you can multiply it by two and divide it. At the bottom I've got the different instantiations of the Cromulate function as well. Near the end. Another real example of flow typing this time, this is in the standard library. This is a URI resolve. It resolves one URI versus another one. If you have example.com URI, and then you try and resolve index.html relative to that, you will get the URI example.com. At the start of this function, we need to work out if you've passed in another URI or a string to this function. If it's URI, it will duplicate the URI. Otherwise it will pass the URI from a string that you pass in. This is one function which takes a union type, and then it will, based on that union type, it will do a different thing. This is flow typing because the target variable has a different type of multiple different points in this function. At the top here, it's a URI or string union. Here it's only URI, so you can duplicate. Here it's only a string because you've removed URI from the union. It can only ever be a string here. You can pass that string into URI.pass and get another URI. At the end of this if branch, the target will be a URI, because you've written code to ensure that. We're going to end up with a comparison of crystal versus how we've done, essentially, how crystal does as a dynamic language versus a statically typed language and how it compromises between the two. Types in crystal aren't mentioned more than dynamic languages. You can write crystal code and it looks like Ruby, it feels like Ruby, and you don't have to write types all over the place, like Java or C-sharp. Types change and flow like a dynamic language, the flow typing that I've demonstrated in my examples. You don't have to think about one variable as not one type. It can change throughout the course of a function, and you can write neat code using that and write code which feels a lot more familiar to you as a dynamic language programmer. I haven't covered yield itself, but if you look in documentation, it's a very nice way to allow expressive type safety of cells in crystal, which is something which I think crystal itself very well at. We have nil safety. It's checked. You will never have a nil pointer exception like in Java. You will never have one of those again if you use crystal. You have memory safety as well. There will never be any segfaltis in crystal unless you use unsaved code. Other good things at crystal, it's object-orientated like Ruby. We have CSP concurrency, so if you've used Go, we have a good implementation of essentially the same thing as Go routines and channels. We have fibers and channels, and so crystal is very good at concurrency. Everything's a synchronous IO by default, so it's very good for developing demons, web applications, servers. A lot of people use it for that. We've got a simple tool chain. It's very easy to use tool chain at the command line. It's a very fast generated code because we have all these guarantees about types. We can use that, seed the result into LVM and get essentially code which runs at the same speed as C, but it feels like a dynamic language and it looks like a dynamic language, but you get all the type safety as well. So try it out. It's fun. There's URL, crystal length, finished right on time apparently. Does it time for a question or two? Nothing. I did well then. You. What's the question? The flow typing? Yes. Does it resolve loops? Yes, it does resolve loops. Essentially... Yeah, there's a fixed point. The question was how does crystal deal with how does flow typing interact with loops and essentially there's a fixed point which the crystal compiler can work out. Yes? In the example where you have the array, can you flow the dimensions of the array as part of the data? The question is, with bounds checking for arrays, is it possible to look at the possible range of values that the array index can take and allied the bounds check in that case? And the answer is no, crystal can't. It's just optimisation just yet. But it's something we'll probably look at later. We're focused on getting the language to 1.0, supporting windows, other different types of things before working on optimisations like that. Thank you. We need to switch speakers because they're both also volunteers in this room. It gets complicated now. Thank you. Can you man the camera during the talk and allow this to tiny you? When you're done with the talk, then step to the timer. Make sure it's straight.