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

