Talks

The Power of Crystal: A language for humans and computers

The Power of Crystal: A language for humans and computers

by Johannes Müller

In this presentation, Johannes Müller discusses the programming language Crystal, emphasizing its compatibility with Ruby and its potential benefits for developers. Crystal combines a syntax reminiscent of Ruby with features such as static typing and native code compilation, making it both performant and user-friendly for Ruby developers.

Key points include:
- Introduction to Crystal: Crystal is designed to enhance developer happiness today, akin to Ruby, offering a clean syntax and object-oriented model that Rubyists can easily adapt to.
- Statically Typed and Native Compilation: Unlike Ruby, Crystal compiles to machine code, enhancing runtime efficiency and making it suitable for performance-critical applications.
- Contributions and Community: Johannes shares his journey from Ruby enthusiast to contributing to the Crystal core team, highlighting how community collaboration has fostered Crystal's evolution.
- Dynamic vs. Static Features: While Ruby is known for its dynamic features, Crystal embraces static typing combined with type inference, leading to cleaner code and easier error detection during compile time.
- Comparative Examples: Müller presents examples that illustrate how code written in Ruby can often be executed in Crystal with minimal changes, reinforcing the shared syntactical aspects between the two languages. An HTTP server example showcases Crystal's potential for handling high-concurrency scenarios effectively.
- Development Insights for Rubyists: The talk imparts learnings on improving Ruby development, focusing on type awareness and structured data usage to ensure code robustness when transitioning to Crystal.
- Interoperability between Crystal and Ruby: Finally, Müller discusses how libraries like Crystal Ruby facilitate interaction between the two languages, enabling Ruby applications to harness Crystal's performance capabilities.

In conclusion, Müller encourages Ruby developers to consider adding Crystal to their toolkit as it can significantly enhance performance without compromising the elegance they appreciate in Ruby. The synergy between Crystal and Ruby presents an opportunity for developers to create increasingly efficient and robust applications. Thanks to its built-in capabilities and ongoing optimization, Crystal is an exciting addition to any Rubyist's skillset.

00:00:06.759 Hello everyone. I'm going to talk to you about the power of Crystal, which is a programming language that's intended for both humans and computers.
00:00:13.360 I’ll give a short introduction to what Crystal is, how it works, how it relates to Ruby, and how you can use both together to leverage the combined power of the two.
00:00:25.240 At the end, I'll share some learnings for Ruby developers. Even if you leave this talk and decide you never want to work with Crystal, you can still gain insights that will help you improve your Ruby development.
00:00:37.760 If you want to follow the slides, you can use this QR code. They'll be available later as well. At the bottom of the presentation, I have some links for installing Crystal or trying it out on an online playground.
00:00:50.800 This playground is essentially a full Crystal compiler that lets you run Crystal code directly in your web browser. So I'll leave this slide on for a moment if you want to copy something.
00:01:12.240 My name is Johannes Müller. When I first learned Ruby, it was the first time I really fell in love with a programming language. Ruby is great, and it was fun to work with. Later, I came into contact with Crystal and once again found a programming language that I loved.
00:01:28.439 Crystal builds upon Ruby and adds some extra features that I find incredibly attractive. When I first encountered Crystal, it was very young, and even though it still is, there were many things missing in the standard library. I started contributing to it and eventually joined the core team.
00:01:48.799 Currently, I work on Crystal full-time as the principal engineer at Manas, the company where Crystal was born. Manas is a software agency that develops software for international clients.
00:02:02.119 The team is international as well—I'm based in Germany, for example, while my colleagues are in Argentina, France, and the US. We use various technologies depending on our clients' needs and projects, but we particularly love Ruby, especially Ruby on Rails.
00:02:30.319 Ruby has fantastic properties, such as a user-friendly syntax, versatility, and high productivity. You can accomplish a lot with minimal effort, and its simplicity and intuitive nature are just a few of its strengths.
00:02:56.640 The greatness of Ruby stems from the creator's vision. A few years ago, a developer in Japan thought about what a truly great programming language would look like, and he realized this vision in Ruby.
00:03:11.039 Many people agreed with this vision. At Manas, there's a developer in Argentina named Ari Bensik who wondered what would happen if a really good programming language could be statically compiled. This brainstorming led to the creation of Crystal.
00:03:50.280 Initially, Ari experimented with Ruby syntax to make it statically compiled. He presented this to his colleagues, sparking further interest, which eventually evolved into a language, an ecosystem, and a community now beneficial to many.
00:04:01.680 In this way, Matz became the grandfather of Ruby, instilling the principle of creating good programming languages. Every programming language, including Ruby, has its downsides.
00:04:20.080 For instance, type checking in Ruby offers options like RBS, but these are added features rather than core functionalities, leading to some challenges in effective utilization.
00:04:34.720 Additionally, Ruby's performance has improved significantly with Ruby 3 and JIT compilation, but it still falls short compared to natively compiled optimized code for specific CPU architectures.
00:05:03.680 Also, Ruby requires a language runtime and various dependencies, making software distribution challenging. Concurrency in Ruby can be a cumbersome adventure, especially if anyone has attempted to create concurrent software without leveraging tools like Web Server Frontends.
00:05:39.279 Programming languages are always a compromise; they come with features and non-features. While you may attempt to include all features, this often doesn't work due to conflicts.
00:05:56.960 Ruby is a dynamic language with immense power but lacks some optimizations due to this. Crystal, on the other hand, maintains most good aspects of Ruby while shifting the feature set towards being more static.
00:06:24.560 While this loses some dynamic nature, it still feels dynamic. Crystal balances static typing with type inference, eliminating the need for excessive type annotations in most cases.
00:06:51.000 The result is clean code that's easy to read. Crystal compiles to highly efficient machine code and has a strong concurrency model, presenting a fresh approach compared to Ruby.
00:07:23.680 Crystal can be seen as a different dialect of Ruby, sharing familiar syntaxes but creating a more distinct language overall.
00:07:58.120 Many parts of the structure are almost identical. As a Ruby developer, you can leverage your existing Ruby knowledge when transitioning to Crystal.
00:08:30.320 Let’s look at some examples. Here’s a simple program that outputs a hello world message along with the language being executed.
00:08:48.640 This program works in both Crystal and Ruby, loaded with a bit of a trick to demonstrate that both languages share a common superset.
00:09:06.840 For instance, when executed in Ruby, it outputs 'Hello Ruby,' and in Crystal, it outputs 'Hello Crystal.' Another example is an HTTP server implementation.
00:09:26.760 This server comes with a crystal-centered library that is feature-rich and provides several useful tools out of the box.
00:09:47.360 This server is simple yet super efficient, capable of handling tens of thousands of requests per second seamlessly.
00:10:06.160 Let’s discuss static typing. Here’s a function that accepts two parameters and uses the plus operator on them.
00:10:34.600 The first call adds two numbers, while the second call concatenates two strings. Despite Crystal being statically typed, the compiler checks all expressions at compile time.
00:10:54.880 The type varies depending on how you call the method. The compiler can deduce the return type based on the parameters used during the method call.
00:11:14.800 If you attempt to add a number to a string, neither Crystal nor Ruby supports this operation, and the compiler promptly warns you.
00:11:48.480 Static typing in Crystal enhances error detection, as the compiler identifies potential issues before execution. This leads to greater assurance in program soundness.
00:12:12.840 In this way, static typing reduces common errors, such as method calls on unexpected types due to dynamic language behavior.
00:12:47.280 For example, an array in Crystal is more than just a single type; it can be initialized to hold specific types. The compiler understands that elements within the array must conform to its defined type.
00:13:12.680 In developing with Crystal, it's necessary to provide type information explicitly to clarify the intended usage.
00:13:36.720 While explicit types may not always be necessary, they act as documentation defining method interfaces, which aids in understanding the code.
00:14:01.680 Next, let's explore what compilation means. When you build a program in Crystal, you can use the 'crystal build' command, producing an executable file.
00:14:26.480 This file, while requiring an additional step, significantly enhances runtime efficiency. The resulting executable is dynamically linked to the current system libraries.
00:14:52.520 Dynamically linked programs may work across different machines, with preconditions around available libraries or dependencies like regular expressions.
00:15:21.280 Alternatively, statically linking an executable means that all required libraries are embedded, offering greater portability but at a larger file size.
00:15:46.960 Static linking affords the benefit of deploying programs without needing to manage dependencies, making server deployment easier.
00:16:12.320 Crystal employs LLVM, a compiler framework that produces highly efficient code. This optimization process ensures phenomenal runtime performance.
00:16:41.440 The compilation process requires all the code to be known at compile time, contrasting Ruby's dynamic nature where you can modify the program at runtime.
00:17:06.480 Crystal provides alternatives to dynamic programming through features like macros, which generate code at compile time, thus optimizing execution.
00:17:39.600 Macros serve as code generators that operate at compile time, offering functionality similar to template processing in languages like Ruby.
00:18:09.320 Additionally, Crystal supports hooks that activate during inheritance, mirroring some operations in Ruby, albeit using different mechanisms.
00:18:39.840 Crystal and Ruby share many similarities across APIs but differ in specifics, adjusting features like meta-programming for performance.
00:19:12.000 For the sake of simplicity, Crystal avoids offering multiple names for identical methods, which can lead to confusion among programmers.
00:19:40.440 As such, Crystal may provide only one naming convention—for example, 'size' instead of 'length.' This approach eases learning for newcomers.
00:20:01.240 Transitioning from Ruby to Crystal is manageable, and embedding the two languages together is facilitated by libraries like `Crystal Ruby`.
00:20:31.920 This gem allows Ruby applications to utilize Crystal code, compiling it into a dynamically linked library that can be accessed via FFI.
00:20:54.960 You can also embed a Ruby interpreter in a Crystal program, allowing type mappings between the two languages, offering flexibility in operations.
00:21:23.320 Additionally, performance-critical Ruby workloads can be optimized by implementing Crystal backends, like background job processing with libraries such as Sidekiq.
00:21:46.520 Now, let's summarize some learnings for Rubyists. Crystal prompts you to be more mindful of types in your code.
00:22:06.480 For instance, if a method returns either a string or nil, and another method accepts only a string, the Crystal compiler will highlight potential issues.
00:22:43.920 You should store the method return value in a local variable to ensure it remains stable throughout usage.
00:23:02.640 This approach enhances efficiency, preventing multiple calls and reinforcing code stability.
00:23:24.640 Ruby's tendency towards semi-structured hashes can be problematic in Crystal due to its static typing. The compiler favors explicit, structured types, making code cleaner.
00:23:49.440 For example, utilizing defined classes instead of generic hashes provides clear expectations and usage.
00:23:55.440 Structured types are more efficient to document and maintain than changing hashes, preventing confusion in code readability.
00:24:29.520 For learning resources, there are excellent materials available for Rubyists. Some concise guides and translation tables for Ruby gems to Crystal shards are particularly useful.
00:25:03.600 The Exorcism track is a great platform for deeper learning in Crystal, albeit potentially a bit lower-level for Rubyists.
00:25:41.440 In conclusion, I showed you how Crystal can enhance your toolkit and improve your Ruby projects. Using Crystal might be a good option if you need more performance.
00:26:02.560 Crystal and Ruby work harmoniously together, providing significant benefits to developers.
00:26:26.960 Thank you for listening. I also want to thank our sponsors, like 84codes, who are instrumental in the development of the language.
00:26:49.440 They’re currently assisting with improving multi-threading, alongside ongoing performance optimization in Crystal. We’ve been using it productively for some time now, and we're excited to enhance its capabilities.