WEBVTT 00:00.000 --> 00:10.200 Yeah, good morning everyone, how I come to my talk about Crystal, language for humans and 00:10.200 --> 00:16.240 computers, glad some people were able to grow out of bed this morning, it's early, it's 00:16.240 --> 00:17.240 a lot. 00:17.240 --> 00:24.400 I'm going to talk a bit about Crystal, especially about it and what's currently on on with 00:24.400 --> 00:25.400 it. 00:25.400 --> 00:32.880 Yeah, this is my information, if you want to reach me, you can follow the slides, just 00:32.880 --> 00:39.200 check out the QR code or to the URL, and if you want to play a long bit with Crystal, you 00:39.200 --> 00:46.560 can find a URL there to install it or the online playground where you can just, yeah, 00:46.560 --> 00:51.880 try it out in the browser. 00:51.880 --> 00:58.840 So yeah, my name is Johannes, when I was at university, I had some compiler tech courses 00:58.840 --> 01:04.960 and I thought, okay, it's nice to be where, what's going on there when you build software, 01:04.960 --> 01:10.760 but I mean, I won't need that, there are plenty of languages already there, and smart 01:10.760 --> 01:17.320 people who build them, so let them do that, yet here I am presenting a relatively recent programming 01:17.320 --> 01:31.320 language, so yeah, sometimes scopes change, I was really amazed when I first encountered 01:31.320 --> 01:41.760 the language Ruby because it is a really fun language, it's a joy to work with it, and 01:41.760 --> 01:47.280 a couple years later I discovered Crystal, which is very similar to Ruby, but the different 01:48.240 --> 01:53.520 and it expands Ruby in a way that I find very attractive, that makes a lot of sense. 01:53.520 --> 02:01.760 At the time, Crystal was still very young, even now it's not an old language, but at the 02:01.760 --> 02:08.720 time lots of basic stuff was missing and I started contributing, simple, additions, back 02:08.720 --> 02:14.160 fixes, then bigger features, eventually it became a coaching member and now of the pleasure 02:14.240 --> 02:20.960 of working on Crystal full-time, at Manus Tech the place where Crystal was born and which continues 02:20.960 --> 02:30.960 to a trip of the project, and somehow ended up as head of the project, so yeah, let's talk a bit 02:30.960 --> 02:37.040 about how Crystal came to be, so Manus is software agency from Argentina, international team and 02:37.040 --> 02:43.520 we build software for clients with different technologies, one of those technologies is Ruby, 02:43.600 --> 02:50.160 we love that a lot, especially Ruby and Rails, and Ruby is really great, there are some things where 02:50.160 --> 02:58.080 I could think maybe doing a different way would also be nice, for example Ruby doesn't have 02:58.080 --> 03:05.920 really type safety, performance can be an issue, distribution of your programs because you basically 03:05.920 --> 03:13.280 need a Ruby runtime to run them, concurrency can be a bit of an adventure, so it's always like a 03:13.280 --> 03:19.200 program language is a set of features and compromises you can't have like everything in one in 03:19.200 --> 03:26.400 swift maybe tries but this always can do stuff either that way or that way not both, but a couple 03:26.400 --> 03:32.640 of guys at Manus a couple years ago thought what if we could evolve Ruby to compile it statically, 03:33.280 --> 03:43.760 so they started something and it's a hello Crystal, Crystal wasn't experiment just to see 03:43.760 --> 03:52.080 what could a static Ruby look like, the compiler was originally with an in Ruby, 03:53.360 --> 03:59.200 then grew into a language and an ecosystem and became like its own language, 04:00.160 --> 04:06.080 if you want to characterize what Crystal is I mean you can have some former description like 04:06.080 --> 04:12.320 it's a general purpose programming language, it's object oriented, garbage collected, I don't know 04:12.320 --> 04:18.720 that but I think it's simple formula is just lots of goodies from Ruby because Ruby got 04:18.720 --> 04:24.640 less of things really good, plus adding static typing with type interference we have 04:25.120 --> 04:32.080 we compile the native machine code so it's super fast and has a strong intuitive concurrency 04:32.080 --> 04:38.960 models so you can write concurrent applications really well with it, so basically we take the best 04:38.960 --> 04:48.080 from Ruby at a bit more and again the big line of programming, Ruby is very dynamic so you can 04:48.080 --> 04:53.120 do lots of stuff you can even alter the program at one time so at the end it has something different 04:53.120 --> 04:57.600 than it did in the beginning whatever you can do lots of stuff and Ruby is super flexible 04:58.800 --> 05:05.040 with compiling which static typing you don't get that much flexibility because lots of things 05:05.040 --> 05:12.640 need to be defined ahead of time so Crystal moves a bit into the static direction but without 05:12.640 --> 05:21.920 losing too much of the dynamic feel that that Ruby has and that makes it really good for lots of 05:22.000 --> 05:28.480 applications I mean it's a strong purpose and I've seen from operating systems to 3D games 05:28.480 --> 05:35.040 and command ion applications servers you can do basically almost anything with it 05:36.640 --> 05:45.520 to expand a bit on what this how this looks like so if we have this code method add that 05:45.520 --> 05:52.160 calls like a plus operator and it's two parameters and this perfectly fine Ruby code 05:52.960 --> 05:57.200 it's also crystal code but if you think crystal is steadily typed so where are the types 05:58.160 --> 06:04.560 there are no types here still it works because the compiler is able to figure out what the types are 06:04.560 --> 06:13.360 in what place so the first call is with two integer arguments and the compiler is okay then we have 06:13.440 --> 06:17.920 this add method it's insensiated with two integer arguments so we need to figure out 06:18.480 --> 06:24.880 what happens next the addition operator between integers and the other call insensiates the method 06:24.880 --> 06:31.600 again but with different arguments this time their strings it's a bit like like function templates 06:32.560 --> 06:39.040 and C++ for example there's not one method but multiple ones and the compiler is able to 06:39.040 --> 06:49.120 infer all that typing information that it needs so basically explicit typing is actually 06:49.120 --> 06:56.560 rarely necessary we can do that I'll show that later but you still get all the benefits of static 06:56.560 --> 07:05.520 typing so this compiles down to very very simple and efficient machine code if we do something that 07:05.600 --> 07:13.280 doesn't work we get an error like you can't add a number to a string the compiler tells you that 07:13.280 --> 07:19.120 there I have no method to call there and this happens in a dynamic language like Ruby as well but only 07:19.120 --> 07:26.000 if you actually execute that code because the types are only known at runtime so if you never reach 07:26.000 --> 07:30.560 that code you will never know that there's an error there but with static typing and the type 07:30.640 --> 07:35.520 inference on crystal you know that as soon as you compile the program that this one work and you 07:35.520 --> 07:41.120 need to write it in a different way to make sure the compiler is happy so that gives you a lot of 07:41.120 --> 07:48.400 piece of mind like code that can't work can't be compiled yeah if we want to add 07:49.360 --> 07:55.920 type annotations we can do that and it's often is useful because yeah it clearly defines the 07:56.000 --> 08:04.000 invariance that the method expects it helps for better error messages and and especially for 08:04.000 --> 08:09.680 public API methods like it's super good to have documented what the method expects as inputs or 08:10.240 --> 08:15.840 transfers outputs so types are often good but you don't need them especially for small like help 08:16.880 --> 08:21.200 methods you can just leave them out and the compiler will do it's thing 08:21.360 --> 08:31.760 yeah similar simple this is another very simple example of a program that reads the message 08:31.760 --> 08:37.040 from the standard input then transfer all the characters in upper case and writes that 08:38.640 --> 08:46.800 to the standard output if we want to run that the compiler will compile that the compiler says 08:46.960 --> 08:54.000 no that's not going to work um and in need to know that the gets method which reads the string 08:54.000 --> 09:00.560 from standard in it returns either a string or nil a nil indicates that the input was closed so 09:00.560 --> 09:06.240 this is maybe an error state whatever you want to do whatever you want to say about it but 09:07.200 --> 09:12.080 it can be a string or it cannot be a string and if you want to call the up case method which 09:12.960 --> 09:17.760 expects the string then that is a string or not maybe a string or maybe something else 09:18.800 --> 09:23.360 so the compiler won't be happy about it and you need to explicitly handle the case that is 09:24.800 --> 09:31.600 this is a string or not a string so here I'm adding a simple condition that asks whether 09:31.600 --> 09:40.400 method is a string that condition is applied at runtime and the code inside the if expression is 09:40.480 --> 09:46.480 only run if the expression is true so inside the branch the message variable is 09:48.560 --> 09:56.160 restricted to the string variant of of its type so we could add an else branch in that else branch 09:56.160 --> 10:03.520 it would be nil of course with nil you can't probably do much but think about more complex types 10:04.000 --> 10:11.120 then this gets a lot more interesting so what's behind is union types and of the concept is 10:11.120 --> 10:18.240 then called flow typing which respects variables according to what's possible at the current location 10:18.240 --> 10:29.840 in the code another very powerful aspect of Christmas meetup programming so why we can modify code 10:30.480 --> 10:36.880 at runtime we can do that at compile time so this is basically code that writes other code 10:36.880 --> 10:46.320 looks a bit like a template and yeah basically that is a template that evaluates to other code 10:47.360 --> 10:57.840 we see here we define a gather macro which expands then to a method that yeah access access 10:57.840 --> 11:06.640 or to instance variable and also defines instance variable itself this just saves a lot of boiler 11:06.640 --> 11:11.840 played code this example is actually taken from the standard library of crystal of course a lot 11:11.840 --> 11:19.120 simplify to fit into this slide here so the real things is much more complex and there are other 11:19.120 --> 11:25.520 similar tools for defining setters and both together setters and gather so there's lots of stuff you 11:25.520 --> 11:34.400 can do that which makes the code really concise and crystal has a lot of batteries included so for 11:34.400 --> 11:41.520 example HTTP server library is part part of the standard library and this is a simple example of how 11:41.520 --> 11:46.560 you can run with just what comes with crystal a simple HTTP server of course you can do 11:47.520 --> 11:56.400 much more than just a print handle crystal response but this works really well it's fully concurrent 11:56.400 --> 12:02.240 so this program can easily handle tens of thousands of requests no problem 12:04.880 --> 12:09.600 the nice thing about crystal is really it's concurrency which works with fibers 12:10.000 --> 12:17.040 that are like this code here there's the spawn methods spawns in your fiber executes the 12:17.040 --> 12:28.000 block in that fiber and it's an individual string of execution so especially like a thread 12:28.000 --> 12:33.520 but much much more lightweight so the operating system is not involved it's all handled by the 12:33.600 --> 12:44.240 crystal runtime and it's an integral part of the runtime so all code is implicitly async 12:44.960 --> 12:52.560 there are no color functions no callbacks as soon as we reach some call that would block because 12:52.560 --> 12:59.360 it waits for IO or whatever the runtime automatically switches to a different fiber and it comes 12:59.360 --> 13:10.160 back whenever the original one is ready to execute so now let's take a look into the crystal ball 13:10.160 --> 13:14.720 like some clouds here what's currently going on what we can expect in the future 13:17.040 --> 13:22.800 our main focus right now is multithreading says that concurrency is great multithreading is 13:23.520 --> 13:30.080 not exactly there yet crystal has had multithreading support for actually a very long time 13:30.080 --> 13:36.080 but it was a bit like simple approach which just took the single thread is getting in order and 13:36.080 --> 13:42.720 moved it to different threads long each other but there was no connection between them so fiber 13:42.720 --> 13:48.560 was assigned to one thread fixed and it would always run there even if another is getting it would 13:48.560 --> 13:55.200 have slots available the fiber can't move so we have introduced recently the concept of execution 13:55.200 --> 14:02.240 context which allow a more powerful multithreading runtime this is currently in a brief view probably 14:02.240 --> 14:09.680 will be enabled in the next release we'll see about that but it will but it but default it will 14:09.680 --> 14:16.320 still be all single threaded just because multithreading has some safety issues which like the entire 14:16.320 --> 14:25.040 code base needs to be prepared for and that's another part it's set safety crystal the language 14:25.040 --> 14:32.480 itself was designed from the start with thread safety in mind so that's not a problem but parts of 14:32.480 --> 14:39.200 like the code base is because crystal has so long been mostly single threaded code bases are not 14:39.200 --> 14:44.400 necessarily prepared for multithreading so there's some some work have there even inside the 14:44.400 --> 14:53.120 standard library mostly related to system interactions like environment variables which is super hard 14:55.280 --> 15:02.880 to do thread safe and of course some some container structures yeah they need to be thread safe 15:02.880 --> 15:10.560 or things may have explode so this what what we're currently working on another topic is I owe 15:10.560 --> 15:21.520 you're in the Linux event selector also in a very final phase we've been working for 15:21.520 --> 15:29.520 on it for a while but it might come as a preview in the next release yeah and finally a big 15:30.400 --> 15:36.400 piece of work is Windows support which also crystal has had for a long time pretty good it's 15:36.400 --> 15:43.120 working really well except for few tiny things which are still need resolving but we're working on that 15:43.120 --> 15:49.840 and I hope it gets resolved soon so then we can say Windows is super fully supported which 15:49.840 --> 15:57.600 basically already is but we won't say that until really everything is in the clear if you want to learn 15:57.600 --> 16:04.240 about crystal we have language reference with also a small tutorial that should get you started 16:04.560 --> 16:12.320 accessism track crystal is really good yeah that's it thank you for listening thanks for being here 16:12.320 --> 16:18.400 at this early hour and I'm happy to take any questions 16:18.400 --> 16:39.120 okay your question yeah the question is how you can pass functions arguments functions are 16:39.120 --> 16:47.360 yeah that's called prox so they're captured into basically a function argument function pointer 16:47.360 --> 16:53.680 and context pointer and these together you can pass around and then they're called 16:55.680 --> 17:02.880 yeah basically what you saw in the the fiber example that do end block that gets captured 17:02.880 --> 17:08.640 into a prox which is essentially a function and then passed around to the the fiber where it 17:08.640 --> 17:16.800 executes yeah compatible with crystal with rabbit so if you take rabbit code and try to compile 17:16.800 --> 17:23.920 this crystal in was the chance I did well so the question is compatibility with Ruby if you can 17:23.920 --> 17:32.800 take Ruby code and execute as crystal with very simple programs that could work but yeah 17:32.800 --> 17:42.240 I mean crystal needs some some type annotations here and there especially for instance 17:42.240 --> 17:46.960 variables that need to be typed because the compiler would have a hard time figuring out 17:46.960 --> 17:55.520 what the data types are so in many some additional pointers there to try to Ruby program into 17:55.520 --> 18:02.080 crystal also some other things have changed I'm going to send a library mostly aligns 18:02.080 --> 18:07.600 what are spaced on Ruby ideas but some things we just changed because so okay can do better 18:08.960 --> 18:14.800 or modern at least and we're not tied into that that Ruby compatibility but what you can 18:14.800 --> 18:21.120 also do is interact between Ruby and crystal so for example there is a 18:21.120 --> 18:29.840 a library called things called crystal Ruby but I'm not sure I have to look that up 18:31.360 --> 18:37.520 which essentially lets you compile crystal code and expose that in Ruby so you can call crystal 18:37.520 --> 18:44.560 from Ruby inside the same process essentially yeah and how do I pay any I don't know 18:44.560 --> 18:51.120 from developers or whatever some programs that could add type annotations for Ruby code I don't 18:51.120 --> 18:56.560 know yeah it's not the best work for this um so the question is about converters standardized 18:56.560 --> 19:05.120 workflows to convert from Ruby to crystal um not that I'm aware of um it usually is more complex 19:05.120 --> 19:10.960 work that probably hard to automate in that way I think that that's where this probably doesn't 19:11.040 --> 19:18.320 exist and I think some of the because of the way crystal works you usually need some different 19:18.320 --> 19:24.720 approaches or it's better to not use the the Ruby way and some things because you can do much 19:24.720 --> 19:36.720 much more efficient for example with some crystal idions yeah okay so yeah okay meet me outside if you have 19:36.720 --> 19:38.720 further questions