RubyConf Mini 2022

Crystal for Rubyists

Crystal is a Ruby-like compiled language that was originally built using Ruby. Its syntax is remarkably similar to Ruby's, which generally makes it straightforward for a Ruby programmer to start using Crystal. There are some notable, and interesting differences between the languages, however. In this workshop, let's learn some Crystal while we learn a little about the similarities and the differences between the two languages.

RubyConf Mini 2022

00:00:16.440 my name is Kirk Haynes my day job is as a developer relations engineer for
00:00:22.320 parity Technologies but I've been doing Ruby for
00:00:27.599 a long time more than 20 years and today we're going
00:00:33.840 to talk a little bit about Crystal and specifically Crystal for
00:00:39.420 rubius what that means is what does crystal look like what is it
00:00:45.140 and how can you leverage your existing Ruby knowledge in order to make you
00:00:50.399 productive more quickly with Crystal and this the first part of this will be kind
00:00:56.219 of like a talk because I kind of want to go over you know like an overview of a bunch of things but
00:01:03.019 it isn't going to be like a talk in the sense that I'm going to hold your questions till the end if you have
00:01:08.340 anything to ask you want to you know talk about anything that you see up on the screen or I think anything that I
00:01:13.380 say interrupt me and let's talk about it and let's just sort of see where this
00:01:18.659 goes um the whole slide deck as well as some
00:01:24.720 code that was used in some of the slides some code examples and a few little
00:01:32.220 I guess you call them exercises are all on GitHub and you can access it through
00:01:38.460 that QR code if that QR code is too little
00:01:43.740 for your camera to read it you know you can grab it from here and that's the URL to go to so if you want to grab it and
00:01:50.460 pull it down to your your laptop to you know follow along on your laptop directly you're welcome to do so
00:01:58.439 um I'll give you just a few seconds there to to grab that and then we'll move on so
00:02:06.000 while we're waiting let me ask this who in here knows what crystal is
00:02:13.140 quite a few of you cool now who in here is actually written the line of Crystal before
00:02:18.720 okay cool it's sometimes yeah yeah it's actually
00:02:25.200 kind of surprising to me how much um how much Ruby code will simply compile with the crystal compiler
00:02:31.379 because the syntax is so similar and there are a
00:02:36.480 lot of things that are quite similar um all right so if you need me to go back to that QR
00:02:41.760 code let me know but otherwise I'm going to roll forwards and let's just talk about a little bit about y Crystal you know we're all here
00:02:48.720 because we like Ruby and I know some of us like
00:02:54.120 you know Keith here you know we've been around a long time we've been using Ruby a long time and there are a
00:03:01.620 lot of benefits to Ruby and you know you can go and you can make a pretty exhaustive list to them this is just a
00:03:06.959 few quick little ones that I think a lot of people agree on you know the blocks the user-friendly syntax the fact that
00:03:13.019 Ruby is a very versatile language you can use it for a lot of different things and it's got some interesting sprinkles
00:03:20.159 a functional programming in it that make it just just enable that usability and that
00:03:26.040 versatility the dynamic typing is one of the things that honestly
00:03:31.319 um really drew me to it initially and I think is one of the things that a lot of
00:03:37.739 people look at as as a benefit the fact that most of the time you don't really have to worry about what the type of
00:03:45.420 your thing is you let Ruby figure it out and you let Ruby tell you if you made a mistake
00:03:51.480 um and Ruby has a really strong set of tools built around it and a
00:03:58.080 really strong testing ecosystem there's a lot of stuff to help you as a developer structure your projects and
00:04:04.200 make your projects easier to work with so
00:04:10.140 there are some drawbacks to Ruby and I know we can argue about some of these drawbacks but generally you know if
00:04:17.579 you're trying to distribute a ruby program a ruby binary it's really difficult to do there are some projects
00:04:24.360 that have existed actually for a very long time to try to tackle this problem and there isn't any one of them that has
00:04:33.120 ever really taken off and dominated this space because it's really a pretty difficult problem to solve because
00:04:38.699 there's so many dependencies wrapped up in a piece of Ruby Ruby code of any
00:04:44.280 significance now you can write something and say m Ruby M Ruby is a ruby-like
00:04:49.740 language itself it's not really Ruby because there's some some significant differences but it's ruby-like and it
00:04:55.979 will compile to be an executable but you can't go take your rails app and turn it into an M Ruby executable
00:05:02.840 now Ruby's performance has always been a topic of discussion and with Ruby 3
00:05:10.020 um that that has been a significant focus and it has gotten a lot faster but
00:05:15.300 nobody writes Ruby because Ruby is going to to be a Lightning Fast 3D rendering
00:05:21.000 engine that's not why we use it um it's it's performance is fairly
00:05:26.039 mediocre concurrency with Ruby is also kind of interesting because
00:05:32.580 there's a lot of different ways to do concurrency with Ruby and that's part of the the tricks with it you've got fibers
00:05:39.479 you've got threads you've got Rafters you've got evented systems and that
00:05:45.000 makes concurrency handling kind of um an adventure sometimes and then
00:05:51.000 the static type checking in Ruby it was added in Ruby 3
00:05:56.780 actually arguably a little bit before that because of the sorbet project but Ruby 3 also has something called RBS so
00:06:04.740 if you want to have static type checking on on your software so that you can
00:06:09.780 really be more certain that you aren't making type
00:06:14.820 related errors you can use it but it is a bolt-on and it has some limitations
00:06:20.160 it's not really when when you're writing code it's it's
00:06:25.259 not fluid to use RBS now these are some of the drawbacks
00:06:30.539 and Crystal has some answers to some of these things um it is syntactically extremely similar
00:06:35.880 to Ruby you know if you look at this code that first little snippet it's the
00:06:41.520 same crystal or Ruby and the next two Snippets are almost the same
00:06:48.000 the one on top is Ruby and the one on the bottom is Crystal the only difference between the two is
00:06:55.080 that in Crystal if you're declaring an array you have to tell it what it's
00:07:00.180 going to store so you have a little bit of typing information in there yeah it's kind of little on this screen I
00:07:06.539 I had thought maybe the screen was going to be bigger but you can see that bottom line
00:07:12.419 there where it says array there's an amp32 in there to tell it what the type of the array is but that's the only
00:07:18.539 difference um
00:07:24.060 yeah so actually I just minimized it completely out of view um
00:07:30.660 where'd it go um all right
00:07:35.940 yeah I minimized my my view of it there we go um
00:07:42.060 I don't think
00:07:49.259 yeah I'm not sure why it's not showing me the normal full screen controls right
00:07:54.300 now when I'm plugged in but um I guess we'll just we'll just roll with
00:08:00.960 it here um so Crystal is a compiled language it
00:08:07.919 compiles your your code down to an executable and it's built on top of llvm um anybody here use rust
00:08:15.599 okay so so you know you know how that works um rust also compiles down to llvm
00:08:21.780 um so it and Crystal share that common layer underneath
00:08:28.139 and this is just a a little snippet just showing you that that if you build build
00:08:34.320 something with Crystal it is in fact a elf executable on my system yeah
00:08:42.060 well let's try it no
00:08:48.600 laughs
00:09:10.980 nope anyway the the binaries tend to also be
00:09:16.680 very fast to execute um in the the repo that that you can get
00:09:22.560 from that QR code there's a fib bench directory that has four implementations
00:09:28.440 of a simple Fibonacci calculator that just recursively calculates Fibonacci numbers and
00:09:35.100 um on my laptop these are the timings for those so you can see that rust is a little bit faster but
00:09:42.420 um yeah crystal out runs everything else by by a substantial margin and this this
00:09:48.240 was simply calculating the 42nd Fibonacci number because if I go bigger than that on my laptop Ruby's really
00:09:54.959 really slow and if if I go smaller you know everything happens too fast so that
00:10:02.040 that's the reason for that number um so Crystal has some answers to some
00:10:07.080 of these these things while still remaining a versatile productive
00:10:12.380 language with with a lot of the same syntax as Ruby
00:10:17.820 so if you don't have Crystal installed on your system and you want to install it it's really easy to do that and you
00:10:25.500 know for like once we're done with kind of the me Talking part of this and we're to the you guys playing part of this you
00:10:32.160 might want to install it if you want to play with it and ask me questions but if you go to crystalllang.org install it's
00:10:39.959 got guided installation steps for any operating system you might be using out there
00:10:50.339 if you need a second to grab that URL I can wait here a second but it's just Crystal lang.org install
00:10:57.839 and if you want to just play on your browser without installing anything you can go to
00:11:03.380 play.crystalling.org and you'll have a a in browser console where you can type
00:11:08.519 code and you can run it and see what happens it's a full uncrippled Crystal running
00:11:14.519 you know running there and letting you see what happens so it's really nice to play with little code Snippets and
00:11:20.100 things like that so I'm going to go through really quickly
00:11:25.980 what the differences are between Ruby and Crystal at a very high level and
00:11:31.320 again if you have questions about anything that I say interrupt me this is you know this is a conversation if you
00:11:37.860 want it to be a conversation and the first thing I want to say is that while Crystal looks a lot like Ruby and in
00:11:44.820 fact there is a lot of Ruby code that you can just throw the crystal compiler at and it'll build it and it'll run it
00:11:50.220 Crystal isn't Ruby there's some significant differences um it's it's a
00:11:57.540 statically type checked compiled language that doesn't have a lot of the dynamic qualities that Ruby has so there
00:12:04.680 is no eval there is no send it's a possible to get a lot of the same
00:12:11.760 capabilities using a different mechanism but those things don't exist in in
00:12:17.579 Crystal um and so you got to keep that in mind that
00:12:22.920 it's not just a funny Ruby it is actually a different language it's just one that leverages your Ruby quite
00:12:28.380 extensively and I also want to mention here just because it's a historically interesting thing the reason why Crystal
00:12:35.220 looks so much like Ruby is that the the people that originally built it they
00:12:40.860 built it using Ruby the first Crystal compilers were built with Ruby and the
00:12:47.880 original goal was basically to take Ruby and see if they could make a compiled
00:12:52.980 language that looked like Ruby and felt like Ruby but was compiled and was fast
00:13:01.200 so that is that is the first difference Ruby's interpreted crystal is compiled
00:13:06.839 however there is an interpreter for Crystal right now it's considered experimental
00:13:12.300 um there's some things that don't work on it but um you can actually run um a large subset of your Crystal code
00:13:20.279 AS interpreted code just like you would Ruby
00:13:26.160 crystal is dynamically typed arubia is dynamically type checked what that means
00:13:31.320 is that the Ruby interpreter is checking the types of of your your data objects
00:13:36.920 at runtime and if you get something wrong you're not going to know it until you run your code and Ruby figures out
00:13:43.860 oh there's a mismatch here and throws an error crystal is statically type checked which means that when the compiler
00:13:51.180 builds the software it goes and it checks before it ever builds the executable to make sure that all of the
00:13:58.380 types make sense and match the way they're supposed to and like I mentioned before Ruby does have static type
00:14:03.779 checking with RBS or sorbet but it is not directly integrated into the
00:14:09.060 language it's kind of a bolt-on so it's a little bit different
00:14:14.160 so here's a quick example what happens if you do this in Ruby
00:14:21.360 yeah yeah so Keith Keith said it's an error if you run it in Ruby and again
00:14:29.279 unfortunately this might be a little hard to read um but Ruby gives you a type error
00:14:34.680 because you Ruby doesn't know how to add a string to a number
00:14:42.360 if you do the same thing in Crystal it's also going to throw an error but it will throw it at compile time instead of at
00:14:48.360 runtime and it's going to give you an explanation of what's wrong and what's
00:14:53.760 wrong is that it has an unexpected argument to the number
00:14:59.760 it expected it to be one of those types and it wasn't that type it was a string and then it goes and it tells you you
00:15:05.940 know what all of the things are that it could be
00:15:11.579 now Crystal does have type inference which means that in a lot of cases it can figure out the types of things so
00:15:17.579 you don't have to specify those types you know back in that early example where you had the array with the the
00:15:24.420 type specified in the array um if if in Crystal code you went and
00:15:29.459 you just used the the syntax to specify a static array
00:15:35.399 um with strings in it or whatever Crystal's going to see that it's going
00:15:40.920 to know okay you mean an array of strings and you won't have to specifically tell it that you have an array of strings that you're storing
00:15:46.440 strings into it's only when it's ambiguous and you can't figure it out that you have to tell it what your types
00:15:52.740 are and so in this example there's nothing in there
00:15:58.500 anywhere that's telling Crystal what a is or what B is whether they're numbers or whether
00:16:03.839 they're strings and this will work exactly the same in Crystal as it does in Ruby
00:16:16.860 just like that no difference same code both languages
00:16:24.300 now in Crystal because it was inspired by Ruby and Ruby informed a lot of the design
00:16:31.740 choices a lot of the method names are identical so a lot of your code will work identically all of this code here
00:16:38.220 will work exactly the same in either language and you run this and you'll get the same out almost the same output
00:16:44.399 there is a difference in how scan in the the what is returned by scan as far as
00:16:51.899 how regular expression matching is there's a slightly different data type that's returned but all this code will
00:16:57.120 execute exactly the same but this will not
00:17:04.500 um in Ruby you do time.now
00:17:09.720 Crystal doesn't have a Time dot now it has a timed out local or time.utc
00:17:15.559 depending upon whether you want the time now in local time or the time now in UTC
00:17:20.819 time but it doesn't have a Time dot now and that one when I was very first you
00:17:26.579 know but first working with Crystal and I was porting some of my code I could not figure out why it didn't work
00:17:32.520 because time.now this why isn't time.now we're not working
00:17:38.160 and it took me longer than I will admit um before I realized that it didn't work
00:17:43.980 because it wasn't implemented and I didn't have the right method um and so you you will run into some
00:17:50.520 places where those things are just different um inject is another one you know inject on
00:17:57.780 on an array in order to to Loop over an array and execute a block on it and gather up a result it's called reduce in
00:18:05.039 Crystal a lot of these name changes by the way are inspired by go where there are name changes in a lot of
00:18:12.120 cases it was because the authors thought that another language typically golang had
00:18:18.960 named it in a way that made more sense and so rather than carrying on with the Ruby influence
00:18:26.220 they chose something that was clear or made more sense to them and then
00:18:32.059 sticking with our Fibonacci theme that piece of code down below
00:18:38.580 there is two really really really terse ways of very efficiently calculating
00:18:45.360 Fibonacci numbers and the one in comments is Ruby and you can calculate
00:18:50.820 more or less any Fibonacci number that you want with that and it will be very fast you want the thousandth Fibonacci
00:18:56.460 number you know that little bit of Ruby will give it to you um and it'll be very very fast
00:19:02.580 um slightly different in Crystal because in Ruby Ruby will cast between
00:19:09.660 um your your regular integer types and a big int if
00:19:14.880 you overflow that integer so when your number gets too big Ruby will say oh it's too big time to use bigint and it
00:19:21.539 will transparently cast that for you Crystal doesn't do any of that automatic
00:19:26.700 casting and so in order to implement this in a nice tighter swaying Crystal
00:19:34.340 we just use big int right from the beginning and avoid that issue of casting so you can
00:19:41.580 see the code's almost the same but just that little bit of typing difference in there
00:20:00.140 oh so so yeah so yeah so that's that's basically what I'm
00:20:06.600 doing um so if if you look
00:20:12.120 so in Crystal we have whoops in Crystal you have to tell it
00:20:17.400 for a hash or an array where oh you I'm on the wrong window again having two windows all right so
00:20:25.760 this part here we're saying we've got a hash and the key is 32-bit integers and
00:20:33.840 the values are big ends and then what we're doing is we're just casting
00:20:41.400 just the very first value that's going to go into there as a big end because when the math happens then in the next
00:20:47.940 part because one value is a bigint just like in Ruby if you're doing integer math
00:20:55.280 you know you don't have to you don't have to specify your types all
00:21:01.380 the way through you know it will if you have an integer and a float it will say okay I guess the whole thing needs to be
00:21:06.720 afloat well because we have a big int and regular ins it's going to say okay the whole thing needs to be a big end
00:21:13.200 and so it converts it all to Big end so it can stay nice and terse and
00:21:19.140 concise but you do need that little bit of extra typing information in there in Crystal that you don't need in Ruby
00:21:32.460 um it will it depends upon the math operators they use for all of the math
00:21:38.820 operators there's there's two variations one of them will throw an error and the other one will wrap
00:21:45.360 so you know if you're doing multiplication or addition or something and maybe you have a use case for just
00:21:50.880 wrapping it back around there's an operator that will do that
00:22:02.400 now concurrency I mentioned it earlier and concurrency is one of those things that's quite a bit different
00:22:08.580 um Ruby has fibers threads reactors and Via gem
00:22:14.340 libraries you have event-based concurrency and um so when you're trying to do something
00:22:20.340 that is concurrent in Ruby it can be quite a bit of work
00:22:26.700 so this is a fiber-based Fibonacci calculator it sets up a fiber and then every time
00:22:35.760 you resume that fiber it calculates the next value of the Fibonacci sequence and
00:22:42.539 you can see that yeah go ahead
00:22:48.720 there isn't any it's just an example yeah yeah yeah there's absolutely no benefit to this yeah it is simply an
00:22:55.320 example of um a fiber that's out there separate from your main program and
00:23:02.280 um so what we're doing here is that every time we allow that fiber to execute
00:23:07.620 it'll calculate the next number and then return it but what we have to do to do that is we
00:23:14.280 have to do a lot of manual herding of that fiber we have to declare it we have
00:23:19.919 to yield to it we have to resume it and if you're doing anything that's really complicated all of that fiber herding
00:23:27.480 can can get really involved you know there's a lot of little details you have
00:23:33.240 to keep track of if you're trying to write fiber code and do it all yourself
00:23:39.900 yeah yeah and I didn't do a ractor example mostly
00:23:45.720 because I ran out of time to pull one together but nobody's really using reactors yet anyway because there's
00:23:52.320 still some Growing Pains there and this is the same thing in Ruby
00:23:59.940 written with threads and so you can see that it's similar there's some things
00:24:06.120 that are a little bit different but um written with threads what we're doing is we're feeding that value into a cue
00:24:13.320 and then we're popping the values off of that Q
00:24:22.200 yeah if you're using jruby it'd be multiple CPUs um in regular MRI Ruby it's still going
00:24:29.340 to be one CPU typically because of the the the global global lock that is on on
00:24:36.780 those in order to prevent conflicts between shared data um
00:24:42.299 now when we do it in Crystal it's a little bit different Crystal looks if if any of you have ever
00:24:48.960 used go with um with goes
00:24:54.120 um go routines and channels Crystal basically has that model of concurrency
00:25:00.720 and so what happens here with with Crystal is we're spawning a separate
00:25:07.559 um a separate execution unit and you don't really have
00:25:12.600 to worry about whether that's a fiber or that's a thread that's kind of a background implementation detail
00:25:18.620 we're spawning an external unit that is responsible responsible for calculating
00:25:24.900 the Fibonacci numbers and then we're communicating to it through a channel and you can think of as a channel as as
00:25:31.080 a a one-directional pipe so you you can
00:25:37.140 feed data in one end and you can pull it out the other end and this is how
00:25:42.240 all concurrency Works in Crystal um so you have coordinated sequential
00:25:48.000 processes that that are talking to each other through these channels
00:25:55.140 um it doesn't have a lot of the the same
00:26:00.840 um with with Ruby you have to make these choices or am I going to use threads am I going to use reactors am I going to
00:26:06.779 use fibers am I going to use some combination I'm going to use fibers with threads um and you have to do a lot of things
00:26:13.740 very manually to handle all of that with Crystal um
00:26:19.380 hides a lot of those details if you turn on multi-threading because right now multi-threading is is an option with
00:26:26.039 Crystal that you can turn on or not when you compile your program if you turn on multi-threading it will have one or more
00:26:33.840 threads with fibers running distributed through those threads but you don't have
00:26:39.539 to worry about hurting any of that you don't have to worry about managing any of that it manages it all for you so all
00:26:44.820 you have to do is send your communication to your processes get your communication back from your processes
00:26:49.980 and let it worry about handling all of that
00:26:56.340 now some other just little differences um this is yeah Ruby libraries are gems
00:27:04.919 Crystal libraries or shards and just like you know with Ruby you have a gem command and Crystal you have a Shard
00:27:10.799 command um the actual low level management of
00:27:15.840 those is a little bit different because shards uses a yaml file to describe
00:27:20.940 everything in it since um because crystal is not a dynamic
00:27:29.340 interpreted language you can't describe your your library in code within that so
00:27:38.400 it's described in yaml and it parses the yaml to get the information out um
00:27:46.080 and just like Ruby has bundler um
00:27:52.200 Crystal has tooling that is inherent in the language to allow you to do a lot of
00:27:58.320 the same things that you do with bundler and with shards
00:28:03.539 and somehow I got that slide in there twice
00:28:08.580 um so this is a quick example when it comes
00:28:14.340 up there we go
00:28:21.740 this is a quick example of something you're probably familiar with this is how it would look if you wanted to
00:28:26.820 create a new project with bundler you do bundle Gem and then you can give it some
00:28:32.460 some command line options to tell it what kind of test Suite you want to use and how you want to do your CI and
00:28:38.580 whatever and it'll go create your stubs for you and Crystal provides the same
00:28:44.100 basic Tooling in a slightly different different shape you know the crystal command itself has this functionality so
00:28:52.080 it's not in a separate tool so you can just do crystal init and you get much the same thing
00:29:00.120 um just in a different tool
00:29:06.539 testing is one of the things that I think in Ruby is a real strength there's there's a strong testing culture in Ruby
00:29:14.100 yeah go for it both both yes so so there's there's two
00:29:22.380 where it says app there if you change that to lib it will change very slightly what it generates to be a
00:29:29.820 library versus an you know something that's meant to be executed separately
00:29:36.419 yeah so so Ruby has you know strong testing history and the two main you
00:29:42.000 know testing libraries are are spec and mini tests and Crystal essentially has the same thing
00:29:48.360 um its testing library is simply called spec and it's built in to to Crystal
00:29:54.240 um and it is extremely similar to our spec um
00:29:59.580 slight differences but extremely similar when you look at a crystal spec if you're familiar with our spec you can
00:30:05.700 read it and likewise there is a mini test that actually was implemented more or less as
00:30:12.899 a direct Port of Ruby's mini test um and so if you like test unit style
00:30:19.020 tests that's available to you as well
00:30:24.779 and so this is just an example actually it's an example pulled out of of
00:30:29.940 a real library of what the specs might look like in Crystal you
00:30:36.779 know it's got the same described the whole it syntax
00:30:42.000 you know event.name dot should equal test event
00:30:47.760 um so it's very very similar to our spec slight differences EQ versus equal eql
00:30:55.020 um some things like that but more or less if you can read our spec you can read
00:31:00.419 read Crystal tests
00:31:05.580 and then yeah kind of wrap up back to the beginning Crystal isn't Ruby but its
00:31:10.980 syntax is close enough that you can use your Ruby knowledge to bootstrap yourself into Crystal really effectively
00:31:20.220 so this is the part where I'm done just talking and the part where maybe we work
00:31:25.679 on something you know we we you know pair programmer we talk through something or whatever it is you guys
00:31:31.860 might find valuable um one of the things that I found really
00:31:37.679 valuable when I first started learning Crystal was just going and taking pieces of Ruby code where I knew the
00:31:43.860 functionality I knew how it worked and rewriting it in Crystal because sometimes it's it's extremely trivial
00:31:51.240 but you can see the little differences and then every once in a while you run into something that is significantly
00:31:57.179 different and you know so then then it sort of breaks your brain and so you
00:32:03.299 know I had I guess two two concepts in mind here and one was we can just you
00:32:09.659 know go to exorcism and take some of the Ruby tasks that are in exorcism how many of you are familiar with exorcism
00:32:16.919 maybe I should explain exorcism first I I made an assumption that seems to be an erroneous assumption
00:32:23.820 um exorcism is a website that is intended to teach programming and tended
00:32:31.559 to teach programming languages and it does it by providing um
00:32:38.220 for any given language and they have dozens and dozens and dozens of them they have programming tasks little tiny
00:32:45.240 challenges that each teach individual Concepts and you can go right in your
00:32:50.700 web browser and you can you can code and you can work on those challenges and you can run your tests and when they pass
00:32:56.520 then you get to move on to the next exercise and so it's a really cool way to learn a language and they have both a
00:33:03.299 ruby track and a crystal track and honestly tracks for just about any language you can think of and a lot that
00:33:08.820 you've never ever heard of so if you've never looked at exorcism before it's a
00:33:14.340 really cool thing to take a look at and you know even without I was just looking at why
00:33:21.779 the the URL is blocked by something down there but um even without
00:33:28.260 um doing anything with Crystal I would say exorcism is worth your time to go take a look at if you're interested in
00:33:33.779 in working on your Ruby skills or or your rust skills or any other language
00:33:41.760 and then the other thing that that I have is um
00:33:46.980 a little it's actually in the repo there is a ruby program that was implemented
00:33:52.260 as a as a dice roller for like a role-playing game and I implemented it in Ruby and there's
00:33:58.019 a stub in the repo of a crystal implementation but it's not completed
00:34:04.140 and so that the challenge would be to take the Ruby version and make it work in Crystal and there is
00:34:11.099 if you want to cheat a finished version also in the repo but if you don't want
00:34:16.379 to cheat um it's it's an interesting exercise and taking a working piece of Ruby that
00:34:24.179 isn't just two or three lines and converting it into a piece of working
00:34:29.460 Crystal and I'm completely open to what people might be interested in if you
00:34:35.580 just want to ask me questions or you want to work on something um this is your turn to shine
00:34:42.599 um yeah
00:34:50.159 what's something okay so so I'm going to repeat your question because the microphone yeah so so he asked what is
00:34:58.200 something that I found that Crystal isn't great at where I would go to Ruby first
00:35:04.200 um and that's an interesting question I think that
00:35:12.180 I think that for most um
00:35:17.400 most significant projects most projects that are intended to have some longevity
00:35:22.980 um crystal is comparable to Ruby I mean you know
00:35:29.040 there's reasons for one or the other you know if if you really like the rails
00:35:34.440 ecosystem and you're building a website you know it's hard to go wrong with rails you know but
00:35:39.780 um there are also very productive options in Crystal I think that probably
00:35:45.599 the place where there might be a difference is if I have something where
00:35:50.940 I really really really need that Dynamic code evaluation
00:35:56.280 um you know like I said there are ways around it that I haven't gone into in
00:36:01.920 this because you know there'd be dragons there um you know if you're familiar with with rust rust has macros Crystal has macros
00:36:09.300 too so you can write you know Crystal has a macro language which is a crystal-like language that exists only
00:36:15.660 to write code so so it's it's code that writes code and so you know doing that you can do
00:36:22.920 all sorts of of dynamic looking things but without going there
00:36:28.920 um anything where you really need that Dynamic code execution or anything that
00:36:33.960 maybe is just a quick you don't care if
00:36:39.000 if it's might have typing errors that that you're not going to run into anyway because it's not going to be in
00:36:45.300 production forever it's some quick little thing you're going to bang out you're going to get a task done and you're done
00:36:51.839 um you know all that kind of stuff I think Ruby is definitely better for
00:36:56.880 um for the other stuff you know I think it's a much harder
00:37:02.040 thing to decide that one is better than the other because they're pretty comparable
00:37:09.780 yeah so what are things that in the real world that are powered by Crystal
00:37:16.680 um so that's a good question that it's it's
00:37:21.960 something that is growing um there's
00:37:28.800 yeah what's so a lot of it is is fairly similar to
00:37:36.060 Ruby in a lot of ways I mean there's a lot of web development that that happens with Crystal
00:37:41.160 um there's some very productive web development Frameworks for Crystal um there's also I think the biggest
00:37:48.839 project that I'm personally aware of is something called Place OS it's a
00:37:56.240 infrastructure management system so you have some giant building with a whole bunch of complex mechanical systems and
00:38:02.339 rooms to reserve and all kinds of stuff like that with a hospital or or an office building
00:38:08.579 with with offices and desks and you know that are being reserved and stuff like that place OS is is a system that
00:38:16.740 manages all of that and some very very big companies like Cisco use it and and
00:38:21.900 large hospitals use it and things like that and then it's all written in Crystal
00:38:26.940 um but it has it has a lot of overlap with
00:38:32.460 with Ruby in where it is currently being used um I know of a company in Las Vegas that
00:38:39.660 is a a small twitch competitor um that uses it for all of their
00:38:46.020 all of their infrastructure um and I know that there are people that are using it for
00:38:52.740 um gaming development because this is another thing that I didn't go over because
00:38:58.079 too much complexity and too much talk talk but
00:39:03.540 Crystal has a really really really nice facility for interfacing with C libraries Ruby is pretty good at that
00:39:10.680 but crystal is is just stupid stupidly easy you know basically
00:39:17.099 it you can just link to a C library and use it almost like almost like Crystal code
00:39:23.339 um so it's it's really nice for interfacing with with Graphics libraries and things
00:39:30.839 like that and I know some people are doing that
00:39:43.260 um so so it's not really that Crystal has plans to deviate from Ruby it's just that
00:39:49.560 um as crystal is innovating on their Syntax for like things like pattern matching
00:39:54.720 um there's ongoing discussions in in the the core development community on
00:40:00.180 Crystal and Crystal is actually a very very open development environment anybody who wants to get
00:40:07.440 involved in actually working on the core of Crystal can it's really open and accepting in
00:40:14.400 that way but there are ongoing discussions about language features whether they're from
00:40:21.119 from Ruby or from other languages like go um or or Elixir or or wherever
00:40:27.140 that might be good ones to implementing Crystal and some of those things will be
00:40:32.760 followed and some won't pattern matching is an example because pattern matching is something that has
00:40:38.820 been discussed recently yeah please yeah
00:40:52.260 so the question is whether in Crystal you can reopen a class like in Ruby and add a method and you absolutely can it's
00:40:58.020 it's exactly like Ruby in that respect so if you wanted to make a ruby compatibility later layer that implemented that stuff you can do that
00:41:05.099 yeah and actually crystal is implemented in Crystal entirely so
00:41:11.099 um you know basically down at the low level it's reopening itself all over the
00:41:16.320 place to add add things
00:41:21.660 Yankee oh
00:41:27.839 I guess it's um so so there was a central person but
00:41:37.680 um it's more now of a um a community effort um and I can't pronounce his last name
00:41:45.300 his first name is Ari um but he's from Argentina and he was a
00:41:51.480 longtime Ruby guy he's still in the in the Ruby Community but um there's a a
00:41:56.760 consulting company in Argentina Manis Tech that provides a lot of the monetary
00:42:05.099 support for Crystal they have um some developers who are on staff
00:42:10.680 specifically to work on crystal because they use crystal with a lot of their clients but it is very much a sort of a
00:42:18.119 decentralized development environment it's just shepherded by mana's Tech right now
00:42:30.300 we'll be running out of questions okay cool I mean if if you want to hang
00:42:37.680 out we've got the room until two um so you know if you want to hang out
00:42:43.140 and ask me more questions or you want to work on on some code or whatever
00:42:49.500 um I'll be here otherwise you know I'm not going to keep you all prisoner you're you're you're welcome to to go go
00:42:57.300 mingle and and do your thing thank you all for coming
00:43:09.839 so how robustly has the the go Lang model of the current
00:43:17.579 um pretty robustly I mean it it um it's in
00:43:22.680 pretty pretty heavy use um you know and and
00:43:28.800 speaking from my own experience um it's it's really easy to use it
00:43:36.119 um it's it is it is a little different I mean there's
00:43:41.700 certain certain thought processes that take a little bit of getting used to when you're talking about passing messages around and receiving them like
00:43:47.940 that um but it's pretty solid the thing that isn't
00:43:53.400 quite there yet is um just in general the language is the
00:43:58.800 multi-threading support because um there's certain well you know you get into to you know
00:44:06.540 resource sharing issues and there's a lot of the standard library that still
00:44:11.760 shares data um and so isn't it self-thread safe and so when you turn on multi-threading
00:44:18.720 um there's there's some risks which is why it isn't enabled by default
00:44:25.079 um but as long as you pay attention to those things that also
00:44:31.920 was working pretty flawlessly now golang
00:44:46.260 yeah no I mean I'm I'm with you there I I
00:44:52.140 golang is one of those languages that I've used it before and I understand okay you know the the fact that you've
00:45:00.060 got a standard Library that's statically linked so you can just share your binary
00:45:05.760 anywhere that's pretty useful but it's it's just kind of a ugly no fun language
00:45:12.900 skills to me like genetic programming yeah
00:45:24.839 yeah I thought about that because the source
00:45:29.940 but still behind you yeah
00:45:37.020 writing something
00:45:52.079 yep that's production and I need to
00:46:03.780 yeah so um I've got a couple
00:46:09.359 couple thoughts there um and I'm not sure I'm not sure if this
00:46:14.640 this exactly applies to what you're talking about but there is a um a
00:46:21.060 library and now that I'm up here on stage I'm blanking on its exact name it starts
00:46:27.780 with an A um that lets you run
00:46:33.359 lets you embed Ruby in Crystal essentially um so that you can you can run both
00:46:41.880 on pass data back and forth between them but it sounds like you're saying you've
00:46:46.920 got one body of code
00:47:00.060 uh-huh
00:47:24.920 I mean you can you know Crystal will will compile something even if it's
00:47:31.319 called dot RB yeah yeah yeah that that's actually in some in some of the you know
00:47:37.920 examples that that you didn't see that's exactly what I did is I had one file called dot RB and I just compile it you
00:47:44.520 know yeah you so you can actually physically use the same file as long as it'll compile
00:47:54.960 yep yeah you can just require blah blah.rb and it should work
00:48:09.960 and does crystal generate a single binary yeah it generates a single binary um
00:48:16.319 So like um okay let's just go
00:48:24.119 well actually let's do this so if we do
00:48:31.020 um if you want to see if you want to see
00:48:37.140 all of the steps you can do it PST and then Dash release builds a slightly
00:48:42.359 optimized version um
00:48:48.060 now the the compiling is a little bit slower than say golang because at the
00:48:55.079 llvm level it's applying quite a few optimizations and so most of the time
00:49:00.660 taken is waiting for that final step um
00:49:09.540 but then if we do a yes so
00:49:17.579 oh I edited it and then messed that up but that's okay
00:49:22.740 um it's still built
00:49:30.060 oh it didn't build okay but um I have I've got the rest version there so you
00:49:35.400 can see that the rest version is about three megabytes the crystal version is
00:49:40.560 987 kilobytes it's just a single executable um
00:49:58.800 so basically the same thing just yeah
00:50:07.200 and there is that that is actually strippable um so if you really wanted a very small file size you can
00:50:19.200 you can knock it down quite a bit um let's find out
00:50:25.140 um
00:50:33.660 so it actually strips down slightly smaller yeah
00:50:42.180 and that that is I guess one of the um I guess one of the negatives to Crystal is
00:50:47.640 that if you have if you have a very very large piece of software um when you compile it
00:50:54.720 especially if you're running on a laptop that's not plugged in you know it can it can take a little bit
00:51:01.920 of time but most you know most of the time you aren't going to be compiling it in
00:51:07.619 release mode and if you compile it not in release mode it's a lot faster
00:51:13.020 the thing that it doesn't do is it doesn't do partial partial compilation
00:51:18.420 so it doesn't it isn't very good at reusing things that had already compiled because you
00:51:24.660 can reopen classes and you can change them and stuff like that and so it's a really hard problem for it to know what
00:51:31.200 it can actually reuse so it ends up just rebuilding everything most of the time
00:51:38.579 yeah yeah if if it doesn't yeah if it does cache them so like you know I
00:51:44.940 just I just built that and if I built it again um
00:51:51.540 it was always small enough that there wasn't a lot of difference but it was faster um because it does cash in but if I go
00:51:57.000 change anything it's going to rebuild everything
00:52:03.240 yeah so
00:52:09.300 so so the primary use case is debugging because um
00:52:15.119 you know you know whoops you know if you're writing Ruby code and you're you're hacking on something sometimes the easiest way to debug it is just to
00:52:21.900 drop into a price session or use IRB um and so with
00:52:28.619 with the the interpreted mode you have essentially it's essentially pry
00:52:33.900 basically they duplicated pry here um and so you have a price session and
00:52:40.559 you can use it exactly the same way pretty much but you can also use it just
00:52:46.260 to directly run your stuff so you can do um
00:52:52.020 and actually the Fibonacci calculator is a terrible one because it'll be really slow on my unplugged in computer but um
00:53:01.020 you can go ahead and run it oh that was the execute that was the binary
00:53:06.900 yeah there yeah so this is a terrible example right now because The Interpreter is not as fast
00:53:14.940 as Ruby um yeah it's brand new it's completely
00:53:20.579 unoptimized so it is not as fast as Ruby and so on something like this it's it's pretty slow
00:53:26.339 but it's really useful for debugging and things like that yeah
00:53:34.319 um yeah it has some limitations because because it is so new um if you go and you go to the crystal Lang
00:53:41.040 install thing and you just install from from an apt um you know or something like that it's
00:53:47.579 not going to be enabled by default um because it's still considered experimental so you've got to go to the sources and build it but um
00:53:55.800 building it is incredibly easy basically it's just a you run make and it builds
00:54:01.740 um and so you can you can go if you want The Interpreter you go to the sources
00:54:07.559 and um let's make interpreter equals one
00:54:13.559 and that'll build it with The Interpreter enabled um however there are some there's some
00:54:19.680 bugs basically I mean that's what the limitations are there's just some bugs and so there's some some things where
00:54:25.079 you start doing especially when you start doing the more esoteric stuff there's some places some
00:54:30.300 edge cases where it just breaks but because crystal is implemented in Crystal essentially what The Interpreter
00:54:36.119 is doing is it's reusing all of those implementations that already exist that were already written in Crystal and
00:54:42.300 aren't just compiled it's just reusing them in an interpreted fashion
00:54:58.440 so yeah if you guys have any other questions anybody has any other questions at any point
00:55:04.680 um I I'm here and I'm happy to talk about it I love Ruby but I also really love
00:55:11.339 Crystal thank you