Yeah, good morning everyone, how I come to my talk about Crystal, language for humans and
computers, glad some people were able to grow out of bed this morning, it's early, it's
a lot.
I'm going to talk a bit about Crystal, especially about it and what's currently on on with
it.
Yeah, this is my information, if you want to reach me, you can follow the slides, just
check out the QR code or to the URL, and if you want to play a long bit with Crystal, you
can find a URL there to install it or the online playground where you can just, yeah,
try it out in the browser.
So yeah, my name is Johannes, when I was at university, I had some compiler tech courses
and I thought, okay, it's nice to be where, what's going on there when you build software,
but I mean, I won't need that, there are plenty of languages already there, and smart
people who build them, so let them do that, yet here I am presenting a relatively recent programming
language, so yeah, sometimes scopes change, I was really amazed when I first encountered
the language Ruby because it is a really fun language, it's a joy to work with it, and
a couple years later I discovered Crystal, which is very similar to Ruby, but the different
and it expands Ruby in a way that I find very attractive, that makes a lot of sense.
At the time, Crystal was still very young, even now it's not an old language, but at the
time lots of basic stuff was missing and I started contributing, simple, additions, back
fixes, then bigger features, eventually it became a coaching member and now of the pleasure
of working on Crystal full-time, at Manus Tech the place where Crystal was born and which continues
to a trip of the project, and somehow ended up as head of the project, so yeah, let's talk a bit
about how Crystal came to be, so Manus is software agency from Argentina, international team and
we build software for clients with different technologies, one of those technologies is Ruby,
we love that a lot, especially Ruby and Rails, and Ruby is really great, there are some things where
I could think maybe doing a different way would also be nice, for example Ruby doesn't have
really type safety, performance can be an issue, distribution of your programs because you basically
need a Ruby runtime to run them, concurrency can be a bit of an adventure, so it's always like a
program language is a set of features and compromises you can't have like everything in one in
swift maybe tries but this always can do stuff either that way or that way not both, but a couple
of guys at Manus a couple years ago thought what if we could evolve Ruby to compile it statically,
so they started something and it's a hello Crystal, Crystal wasn't experiment just to see
what could a static Ruby look like, the compiler was originally with an in Ruby,
then grew into a language and an ecosystem and became like its own language,
if you want to characterize what Crystal is I mean you can have some former description like
it's a general purpose programming language, it's object oriented, garbage collected, I don't know
that but I think it's simple formula is just lots of goodies from Ruby because Ruby got
less of things really good, plus adding static typing with type interference we have
we compile the native machine code so it's super fast and has a strong intuitive concurrency
models so you can write concurrent applications really well with it, so basically we take the best
from Ruby at a bit more and again the big line of programming, Ruby is very dynamic so you can
do lots of stuff you can even alter the program at one time so at the end it has something different
than it did in the beginning whatever you can do lots of stuff and Ruby is super flexible
with compiling which static typing you don't get that much flexibility because lots of things
need to be defined ahead of time so Crystal moves a bit into the static direction but without
losing too much of the dynamic feel that that Ruby has and that makes it really good for lots of
applications I mean it's a strong purpose and I've seen from operating systems to 3D games
and command ion applications servers you can do basically almost anything with it
to expand a bit on what this how this looks like so if we have this code method add that
calls like a plus operator and it's two parameters and this perfectly fine Ruby code
it's also crystal code but if you think crystal is steadily typed so where are the types
there are no types here still it works because the compiler is able to figure out what the types are
in what place so the first call is with two integer arguments and the compiler is okay then we have
this add method it's insensiated with two integer arguments so we need to figure out
what happens next the addition operator between integers and the other call insensiates the method
again but with different arguments this time their strings it's a bit like like function templates
and C++ for example there's not one method but multiple ones and the compiler is able to
infer all that typing information that it needs so basically explicit typing is actually
rarely necessary we can do that I'll show that later but you still get all the benefits of static
typing so this compiles down to very very simple and efficient machine code if we do something that
doesn't work we get an error like you can't add a number to a string the compiler tells you that
there I have no method to call there and this happens in a dynamic language like Ruby as well but only
if you actually execute that code because the types are only known at runtime so if you never reach
that code you will never know that there's an error there but with static typing and the type
inference on crystal you know that as soon as you compile the program that this one work and you
need to write it in a different way to make sure the compiler is happy so that gives you a lot of
piece of mind like code that can't work can't be compiled yeah if we want to add
type annotations we can do that and it's often is useful because yeah it clearly defines the
invariance that the method expects it helps for better error messages and and especially for
public API methods like it's super good to have documented what the method expects as inputs or
transfers outputs so types are often good but you don't need them especially for small like help
methods you can just leave them out and the compiler will do it's thing
yeah similar simple this is another very simple example of a program that reads the message
from the standard input then transfer all the characters in upper case and writes that
to the standard output if we want to run that the compiler will compile that the compiler says
no that's not going to work um and in need to know that the gets method which reads the string
from standard in it returns either a string or nil a nil indicates that the input was closed so
this is maybe an error state whatever you want to do whatever you want to say about it but
it can be a string or it cannot be a string and if you want to call the up case method which
expects the string then that is a string or not maybe a string or maybe something else
so the compiler won't be happy about it and you need to explicitly handle the case that is
this is a string or not a string so here I'm adding a simple condition that asks whether
method is a string that condition is applied at runtime and the code inside the if expression is
only run if the expression is true so inside the branch the message variable is
restricted to the string variant of of its type so we could add an else branch in that else branch
it would be nil of course with nil you can't probably do much but think about more complex types
then this gets a lot more interesting so what's behind is union types and of the concept is
then called flow typing which respects variables according to what's possible at the current location
in the code another very powerful aspect of Christmas meetup programming so why we can modify code
at runtime we can do that at compile time so this is basically code that writes other code
looks a bit like a template and yeah basically that is a template that evaluates to other code
we see here we define a gather macro which expands then to a method that yeah access access
or to instance variable and also defines instance variable itself this just saves a lot of boiler
played code this example is actually taken from the standard library of crystal of course a lot
simplify to fit into this slide here so the real things is much more complex and there are other
similar tools for defining setters and both together setters and gather so there's lots of stuff you
can do that which makes the code really concise and crystal has a lot of batteries included so for
example HTTP server library is part part of the standard library and this is a simple example of how
you can run with just what comes with crystal a simple HTTP server of course you can do
much more than just a print handle crystal response but this works really well it's fully concurrent
so this program can easily handle tens of thousands of requests no problem
the nice thing about crystal is really it's concurrency which works with fibers
that are like this code here there's the spawn methods spawns in your fiber executes the
block in that fiber and it's an individual string of execution so especially like a thread
but much much more lightweight so the operating system is not involved it's all handled by the
crystal runtime and it's an integral part of the runtime so all code is implicitly async
there are no color functions no callbacks as soon as we reach some call that would block because
it waits for IO or whatever the runtime automatically switches to a different fiber and it comes
back whenever the original one is ready to execute so now let's take a look into the crystal ball
like some clouds here what's currently going on what we can expect in the future
our main focus right now is multithreading says that concurrency is great multithreading is
not exactly there yet crystal has had multithreading support for actually a very long time
but it was a bit like simple approach which just took the single thread is getting in order and
moved it to different threads long each other but there was no connection between them so fiber
was assigned to one thread fixed and it would always run there even if another is getting it would
have slots available the fiber can't move so we have introduced recently the concept of execution
context which allow a more powerful multithreading runtime this is currently in a brief view probably
will be enabled in the next release we'll see about that but it will but it but default it will
still be all single threaded just because multithreading has some safety issues which like the entire
code base needs to be prepared for and that's another part it's set safety crystal the language
itself was designed from the start with thread safety in mind so that's not a problem but parts of
like the code base is because crystal has so long been mostly single threaded code bases are not
necessarily prepared for multithreading so there's some some work have there even inside the
standard library mostly related to system interactions like environment variables which is super hard
to do thread safe and of course some some container structures yeah they need to be thread safe
or things may have explode so this what what we're currently working on another topic is I owe
you're in the Linux event selector also in a very final phase we've been working for
on it for a while but it might come as a preview in the next release yeah and finally a big
piece of work is Windows support which also crystal has had for a long time pretty good it's
working really well except for few tiny things which are still need resolving but we're working on that
and I hope it gets resolved soon so then we can say Windows is super fully supported which
basically already is but we won't say that until really everything is in the clear if you want to learn
about crystal we have language reference with also a small tutorial that should get you started
accessism track crystal is really good yeah that's it thank you for listening thanks for being here
at this early hour and I'm happy to take any questions
okay your question yeah the question is how you can pass functions arguments functions are
yeah that's called prox so they're captured into basically a function argument function pointer
and context pointer and these together you can pass around and then they're called
yeah basically what you saw in the the fiber example that do end block that gets captured
into a prox which is essentially a function and then passed around to the the fiber where it
executes yeah compatible with crystal with rabbit so if you take rabbit code and try to compile
this crystal in was the chance I did well so the question is compatibility with Ruby if you can
take Ruby code and execute as crystal with very simple programs that could work but yeah
I mean crystal needs some some type annotations here and there especially for instance
variables that need to be typed because the compiler would have a hard time figuring out
what the data types are so in many some additional pointers there to try to Ruby program into
crystal also some other things have changed I'm going to send a library mostly aligns
what are spaced on Ruby ideas but some things we just changed because so okay can do better
or modern at least and we're not tied into that that Ruby compatibility but what you can
also do is interact between Ruby and crystal so for example there is a
a library called things called crystal Ruby but I'm not sure I have to look that up
which essentially lets you compile crystal code and expose that in Ruby so you can call crystal
from Ruby inside the same process essentially yeah and how do I pay any I don't know
from developers or whatever some programs that could add type annotations for Ruby code I don't
know yeah it's not the best work for this um so the question is about converters standardized
workflows to convert from Ruby to crystal um not that I'm aware of um it usually is more complex
work that probably hard to automate in that way I think that that's where this probably doesn't
exist and I think some of the because of the way crystal works you usually need some different
approaches or it's better to not use the the Ruby way and some things because you can do much
much more efficient for example with some crystal idions yeah okay so yeah okay meet me outside if you have
further questions