Talks
Introducing the Crystal Programming Language
Summarized using AI

Introducing the Crystal Programming Language

by Will Leinweber

In the talk "Introducing the Crystal Programming Language", Will Leinweber discusses the similarities and differences between Ruby and Crystal, a statically typed programming language that borrows its syntax and idioms from Ruby. Key points include:

- Crystal's Inspiration: Crystal is designed for developer happiness and mimics Ruby's syntax. However, it is a compiled language without runtime dynamic features, relying on LLVM for optimized machine code generation.

- Performance Advantages: Crystal can significantly outperform Ruby programs in terms of speed and memory efficiency, showcased through benchmarks comparing a Crystal Sinatra clone and Ruby’s Sinatra on Puma.

- Type System: Unlike Ruby, Crystal uses static typing which allows for compile-time type checking and automatic union types, minimizing runtime errors. This systematic approach offers cleaner and more structured code management.

- Method and Property Management: Assigning arguments and utilizing properties is streamlined in Crystal, with methods being able to handle multiple types seamlessly via method overloading.

- Concurrency and I/O Performance: Drawing inspiration from Go, Crystal provides robust capabilities for concurrency using channels and coroutines, alongside optimized I/O operations which improve overall performance.

- Community and Documentation: Leinweber encourages developers to explore the Crystal ecosystem and emphasizes the supportive community behind the language. He shares installation resources and invites further engagement with the evolving language.

Throughout the presentation, humor and anecdotes were used to maintain engagement, including a Norm Macdonald joke and a recount of personal experiences, which helped to illustrate the speaker's connection with technology humorously. The main takeaway is that Crystal presents a promising alternative for Ruby developers looking for performance and a strong type system, while still being user-friendly and familiar to those experienced in Ruby programming.

00:00:13.519 Thank you, everyone. It's a real honor to be back here again. This is such a great conference! If there's anything you want to talk to me about, you can reach me on Twitter. My website is also available for reference. I’m currently working at a company called Situs Data, which provides a Postgres extension that manages sharding. This allows you to have very regular tables. You can specify which tables you want to shard across several machines, enabling you to handle a large volume of data. It's pretty cool! So if you use Postgres and anticipate having a lot of data, come talk to me! If you don't use Postgres, that's okay too.
00:00:59.250 This talk is going to be divided into a couple of different parts. The first part will cover what the Crystal programming language is and why I'm excited about it. Then, in the last part, I'll provide some examples to illustrate how Crystal is similar to and different from Ruby. Last week, the Crystal team released a new feature where you can type 'crystal play' at the command line, which opens a browser window where you can interactively execute code. I thought this was really cool, so I worked on it with the help of one of the members of the Crystal core team.
00:01:10.650 It's not released yet, but in the next version of Crystal, it will function like a workbook. You will be able to have sample code snippets that accompany your library. So, I adjusted my talk to utilize that feature instead. The good news is that I think it’s going to be more engaging to see the code actually run. However, it does involve a lot of code, which can get dull. I also struggled to find a way to include pictures, so instead of visuals, I decided to share one of my favorite Norm Macdonald jokes to lighten the mood.
00:01:36.600 The joke goes like this: A frog walks into a bank and asks the teller for a loan. The teller is skeptical, saying, "You're a frog!" The frog responds, "I get that a lot, but can you help me?" The teller tells him that the loan manager is Patricia Whack. The frog waits until Patricia opens her door and invites him into her office. She then states, "This is quite irregular; we usually only give loans to humans." The frog insists that he needs a loan, so Patricia collects some information from him. She asks for his name, and the frog says, "My name is Kermit Jagger, my father was Mick Jagger, and my mother is a frog." Patricia, confused, realizes he is not Kermit the Frog. As they continue, the frog explains he simply needs a larger lily pad for his family. Patricia asks for collateral, and he offers her a small carving of an elephant. She takes it to the loan manager, who looks at it and says, "Oh, I see! It's a knick-knack, Patty Whack, give the frog a loan — his old man's a rolling stone!"
00:04:21.670 Now, completely shifting gears, let's talk about the Crystal programming language. Crystal is a language that is unabashedly Ruby-inspired. The syntax, the idioms, everything is quite similar to Ruby, but it's completely compiled. There is no virtual machine running the code at runtime. Instead, it's built on top of LLVM, which has become a remarkable project in recent years, thanks to the efforts of companies like Apple and Google.
00:04:51.590 LLVM generates incredibly optimized machine code, which is impressive. There aren't many contributors to the entire Crystal project; I have contributed around 80 commits, but I’m one of the more significant contributors. This is possible because the top contributors are incredibly proficient and prolific, especially the main creator. Also, because LLVM handles all the optimizations, we can achieve highly efficient programs.
00:05:11.270 Crystal acts more like a front-end to LLVM. I believe that in the next ten years, languages will evolve significantly. The past decade, dynamic languages like Ruby have seen phenomenal growth, but as computers become faster and more powerful, one would expect to see dynamic languages achieve greater performance. Instead, it seems that the compile time in compiled languages is decreasing, which leads me to think that languages built on LLVM will dominate in the coming years.
00:05:36.300 Crystal has several key differences from Ruby. For instance, it uses static method dispatch, meaning it knows everything about the program at compile time. However, you still maintain a lot of the nice features found in Ruby, like the ability to create programmatic getters and setters and macros. Crystal is statically typed, and even though I'm not a language expert, it has a fantastic type system that offers a seamless experience. You rarely have to specify types; the language figures it all out for you.
00:06:03.900 Automatic unions of types are part of the language too, which I'll demonstrate through examples. Moreover, linking against C libraries is straightforward, making it easy to have a robust ecosystem. Crystal also excels in performance, and while micro-benchmarking should be approached with caution, it's worth noting that a Crystal program can outperform a corresponding Ruby program significantly.
00:06:23.760 For example, when running a Crystal program, which is a Sinatra clone, we see it operates an order of magnitude faster, with less latency and lower memory consumption, compared to regular Sinatra running on Puma. While micro-benchmarks can vary greatly, they showcase the incredible potential of Crystal.
00:06:35.820 The language has been evolving over the past few years, achieving self-hosted status early on. This means that the compiler, standard library, and everything else is written in Crystal itself, making it easy to contribute to the project. For comparison, Rubinius is mostly written in Ruby, whereas everything in Crystal is Crystal.
00:06:50.080 Now, I’m going to show you some code examples. I had to compile a custom version since it’s not quite released yet, but I hope it works as expected. When you run the custom version, a browser interface opens where you can interact. All the code samples are available, but you can't use them until the next release, which I believe is coming very soon.
00:07:11.369 To follow the theme of my talk, I’ve included a couple of carpentry jokes as well. Here’s one: I never really wanted to be remembered as stealing from my job as a road worker, but when I got home, all the signs were there! Now let’s look at the similarities between Ruby and Crystal. Of course, ranges are the same in both languages. For example, if you want to do a 'puts', you can put 'puts with inspect' to turn it into an array. You can also chain methods, use blocks, lambdas, and closures — all functionalities that work identically in both.
00:07:32.520 The foundation of object-oriented programming remains consistent as well. In Crystal, classes are open, which means that any last definition of a class will override previous ones, quite similar to Ruby. Instance variables act in the same manner, promoting flexibility in code design. The standard library is also written in Crystal, and programmers can modify parts of it without incurring any performance penalties. For instance, if I want to reopen a string and add my own size method, I can do it as if I were working with Ruby.
00:07:56.610 Equally important are modules and mix-ins. The inclusion of common elements is handled similarly with 'include' and 'extend' keywords. Notably, idioms around naming conventions, such as question marks for boolean methods, as well as the optional parentheses for calls, remain intuitive and consistent.
00:08:23.170 This creates familiarity for Ruby developers transitioning to Crystal, as they can apply their existing knowledge and experiences to solve problems effectively in this new language. Learning syntax or properties of a new language isn’t terribly difficult, but to truly be proficient and confident can take years of practice.
00:08:35.600 That said, it's worth noting that the spec framework is included in the standard library, offering an interesting twist. Speaking of twists, consider this humorous anecdote: construction workers have to be careful — when they raise the roof, they could end up in an unexpected situation!
00:08:47.660 Now, you might be wondering whether Crystal is fundamentally the same as Ruby. What are the differences? One notable difference lies in syntax when assigning arguments to instance variables, to reduce boilerplate code. In Crystal, you can place the '@' sign right next to the name, which simplifies the process.
00:09:01.500 Additionally, instead of using 'attr_accessor', Crystal uses 'property'. While this may seem like a small difference, Crystal allows various ways to gather type information about classes, leading to streamlined implementations. For instance, we can explore class attributes using built-in inspection tools.
00:09:19.530 My favorite feature in Crystal, which is a subtle one that brings added value, is the ability to use the 'to_proc' method, which is represented by a period instead of a dot, making it easier to chain methods together. This affords more elegant and powerful functionality than is typically possible in Ruby.
00:09:36.110 The principal distinction, however, lies within the type system. For example, if we define a method that takes parameters and handles different types of inputs, we can see how the method distinguishes between them. For instance, the return type changes depending on the input type due to the compile-time type system in Crystal.
00:09:59.790 If we pass an integer, the type is an Int32, and if we pass a string, it returns a string. What’s happening behind the scenes is the creation of multiple method copies based on the argument types, which facilitates structured handling of various input cases.
00:10:17.700 Crystal also supports Union types for methods that might return different outcomes. In this case, a method could return an Int32 when the input is high enough but return a string if the input is low enough. This means you can track the running type at any time, ensuring robust compatibility and validation.
00:10:37.300 Despite this efficiency, situations may arise where handling union types causes issues. When methods downstream require compatibility with all union type members, it might lead to compile-time errors if incompatible methods are invoked. This is a true distinction that's clear in Crystal's type system.
00:10:56.930 For example, if we try to add a string and an integer, it results in a compile-time error because there's no defined method that recognizes plus for both types. Thus, this compile system prevents pitfalls commonly encountered in dynamically typed languages.
00:11:08.160 When we encounter these issues, we can write conditional checks to ensure we only evaluate specific code if the relevant parameters are present. If we are certain about types, we could pursue explicit type casting, but we have to be cautious since any oversight could bring runtime errors.
00:11:23.630 What persists through this is that type inference allows capabilities without substantial type annotations throughout the codebase. The language compiles quickly and you're not bogged down by typing constraints unless you choose to specify them.
00:11:41.120 This is exemplified with method overloading — the definition can accept varied argument types, allowing for clean method management. Whenever writing methods that handle similar logic, specifying types ensures the right execution at runtime.
00:12:06.130 Another interesting feature is leveraging interfaces. If an abstract class method isn't implemented where it's required, an immediate compilation error guarantees that you address the shortcoming. Crystal’s compile-time guarantees prompt structured programming patterns.
00:12:19.230 When dealing with arrays and containers, defining type specificity can sometimes impose constraints. For instance, if you attempt to reverse the placement of elements in an array, the error can emerge due to mismatched types. Crystal alleviates this with tuple support, which maintains strict conformity to expected type orders.
00:12:36.290 Tuples present a firm way to enforce structure. If we misplace items in positional definitions, the system throws an error, ensuring appropriate handling and strong typings throughout the code.
00:12:55.750 Conversely, instantiating empty arrays can necessitate explicit specifications — a constraint not typical for dynamically typed languages. Users of Crystal must specify the type while declaring arrays to match the rigorous nature of the compiler.
00:13:09.230 Reflecting on my experience with Crystal, I quickly embraced the seamless integration of operations such as linking against C code. Building a Postgres driver was a straightforward experience, illustrating how direct operations can be executed with minimal boilerplate compared to languages like Ruby.
00:13:20.095 When linking against systems like LibPQ, the coded requirements were succinct, enabling direct connections to running Postgres instances, accompanied by ease in executing queries. This efficiency was among the first things that left a strong impression on me regarding Crystal.
00:13:33.450 Exploring various facets of performance profiling reveals that numerous existing Linux tools function seamlessly with Crystal applications. Developers can leverage tools they might already be familiar with, eliminating the burden of additional instrumentation processes.
00:13:44.590 Working with standard profiling tools provides clarity into program execution down to the assembly level. In projects where performance is pivotal, the ability to monitor where time is spent helps optimize critical areas effectively.
00:14:01.920 With the construction jokes, I was initially worried about messing those up, but I feel like I’m nailing it! Let’s shift into some unique characteristics. Structs in Crystal serve distinct purposes as they exist akin to classes, but allocate on the stack, conferring a specific advantage in efficiency while keeping immutability in mind.
00:14:14.245 I/O operations are optimized thoroughly in this language. All of the string interpolations and buffer manipulations weave through efficient abstraction, ultimately delivering impactful performance. Crystal’s approach capitalizes on ideas popularized by Go, bringing built-in formatters for code consistency throughout projects.
00:14:32.580 On the topic of concurrency, the model draws inspiration from Go as well, utilizing channels and coroutines effectively, though it remains crucial to note that parallelism isn't fully realized just yet. The Crystal community is persistent in evolving the language, and I encourage anyone interested to try it out.
00:14:54.480 For those eager to explore, visit crystal-lang.org/docs for installation instructions applicable across various platforms. Reflecting on my journey, I grew up in a small town in Illinois where everyone placed immense hopes on one individual, Justin. He was expected to achieve greatness but ultimately carved his own path in an unexpected way.
00:15:11.530 During a visit to Niagara Falls, I serendipitously found him feeding dolphins at an aquatic park. I asked him about his journey, and he humorously remarked about capturing his passion for serving a youthful purpose in a manner entirely different from what was anticipated. Thank you!
Explore all talks recorded at Ruby on Ales 2016
+2