Paul Martensen

Rust for Rubyists (and Rubyists for Rust)!

Ruby Unconf 2019

00:00:14.260 Hello everyone! Today, I want to talk to you about a different programming language than Ruby, which I think is really nice and that I really like.
00:00:19.340 I basically spend all my free time with it. The language I want to discuss is Rust. Who has heard of Rust before? I guess a lot of people here have, which is great!
00:00:32.629 Rust is a town in Bonn, Germany, with a population of 4,100 people and an elevation of 169 meters. But don’t worry, that’s not what I came here to talk about!
00:00:45.739 I actually came to Rust after looking for a language that could handle the 20% of programming tasks that Ruby isn’t well-suited for. I was comfortable with Ruby for web programming and scripting, which comprises about 80% of what I do. However, the remaining 20% involves embedded programming and game development, which Ruby struggles with.
00:01:07.789 I was searching for a modern alternative to C. In university, I learned C, but I hit several walls and eventually stopped learning it. I wanted to see if anyone had made progress in creating a nicer, C-like language.
00:01:15.170 Let me now discuss the selling points of Rust because I want to advocate for it. To be honest, I’m not here to provide a completely neutral perspective. First of all, Rust offers excellent performance, which is critical.
00:01:35.509 Most Ruby programs can face slowdowns. Moreover, Rust provides memory safety without requiring a garbage collector. This makes it suitable for areas like microcontrollers or game development where you can’t afford to pause the program for garbage collection.
00:01:55.910 It's also nice not to have to manage memory manually as you do in C or C++, which can be quite scary. I have nightmares about manual memory management. Rust has zero-cost abstractions, which allow you to write high-level code without worrying about sacrificing performance.
00:02:12.110 It compiles down to efficient assembly code that you don't have to read. Plus, Rust has an adorable mascot, which is a nice change from Ruby's inanimate rock.
00:02:27.370 Rust was originally designed by Mozilla, the creators of Firefox, to replace C and C++ in their codebase due to challenges they faced with parallelizing certain components, like CSS rendering. After encountering significant difficulties twice, they decided to create a new programming language.
00:02:45.720 Rust has been under development for about 10 or 11 years, but it has only really gained traction in the last two to three years primarily through Mozilla. As a result, there's already Rust code running in production in Firefox, so it's on many machines today.
00:03:04.940 Now, to provide a neutral perspective requires me to be fully honest: Rust is not a language you can just dive into and master in ten minutes. You cannot pick it up and write a Python script casually. However, if you already know C++ or Haskell, Rust can be easier to grasp.
00:03:24.990 For someone with a strong C++ background, the concepts in Rust are primarily best practices. Let me briefly introduce you to Rust's syntax!
00:03:39.050 The basic 'Hello, World!' program is fairly simple. The function signature returns nothing, meaning it does not have a return type, and it uses a print line macro, which is an interesting feature of Rust.
00:03:55.600 Now let’s discuss some fundamental differences between Ruby and Rust. First, Rust is statically typed, but it does include a lot of type inference, meaning you don’t have to specify types explicitly, which is great because, let’s face it, I’m lazy.
00:04:10.840 In Rust, you must think about stack versus heap memory. In Ruby, everything exists on the heap, and we often forget about the stack. With Rust, however, you do have to consider what operates on the heap and what operates on the stack for performance reasons.
00:04:29.230 In Rust, all variables are immutable by default. While you can make them mutable if needed—like freezing strings in Ruby—Rust emphasizes immutability, but you can change them if necessary. It's not like Haskell where everything must be immutable.
00:04:46.120 Another point is that Rust has limited metaprogramming. While macros exist, they operate differently from traditional meta programming methods. Rust expands them at compile time, not at runtime.
00:05:01.430 Moreover, there’s a clear visual separation between data and behavior. You can perform object-oriented programming, but you do not have to, and the trend seems to be moving away from it.
00:05:15.830 The core concept in Rust is ownership, and I won’t be able to cover everything about it right now, but it's crucial. Ownership is a concept that started as an academic idea and is now mainstream with Rust.
00:05:33.290 It allows Rust to manage memory without needing manual management or garbage collection. Ownership means each value has exactly one variable that owns it. If that variable goes out of scope, the memory is then freed at that address.
00:05:51.160 This means that in practice, you inherently make decisions about memory allocation and deallocation. For example, if I have a variable 'x' assigned to the string 'cake,' when I try to eat the cake, it gets consumed, and I can't access 'x' anymore. The compiler alerts me if I try to have my cake and eat it too.
00:06:15.460 However, you can borrow the cake. In the second example, if I borrow the cake and return it, I can still have my cake afterward without any issues. The 'eat' function takes ownership for its scope but gives it back after execution.
00:06:35.500 One of the main advantages of Rust's approach is that it allows for a memory-safe environment without garbage collection. This means that you can have your mutable and immutable state without worrying about memory deallocation.
00:06:51.460 However, working with Rust forces you to think differently. For instance, while global mutable states are possible, they are discouraged.
00:07:01.150 In more complex data structures, like graphs, things become less trivial. If you have a struct where a vector owns its elements, you'll encounter compilation issues when you try to use elements after they have been owned by the vector.
00:07:10.700 While graph structures can be implemented in Rust, they can be tricky for beginners due to these ownership issues.
00:07:27.180 Immutability by default in Rust means that change is not straightforward; if I try to change a variable initialized to a specific value, the compiler will throw an error unless I explicitly make it mutable.
00:07:47.480 However, this immutability, coupled with ownership and borrowing, leads to clear and readable function signatures. You can generally infer a lot about a function just by looking at its signature.
00:08:07.310 For instance, if I have a function that consumes a cake, it takes ownership, which is indicated in its type signature. Another function might consume the cake but also return a new one which means the original is now unavailable.
00:08:20.080 Using borrowing, I can take a reference to a cake without altering it, ensuring you can continue to use it afterward. This type of careful memory management is vital for concurrency.
00:08:43.960 In Rust, you can have multiple read-only references at a time, but only a single mutable reference. This prevents data races in concurrent programming, which is an essential feature.
00:09:01.990 For instance, if I have a function that consumes a value and frees it, the compiler inserts memory management where it knows that value cannot be accessed thereafter. However, the borrow checker requires a shift in thinking; keeping track of access and modifications to the data is crucial.
00:09:21.180 When creating more complex data structures, such as graphs, the rules of ownership and borrowing can get complicated, especially if you intend to use nodes or mutable states.
00:09:40.820 The concept of immutability and ownership in Rust encourages clearer and more manageable code, promoting safe concurrency. The added challenges of using references and managing states can lead to even more readable function outcomes.
00:09:56.890 Here’s a simple example: if I have a number that I want to multiply, I can handle errors through patterns that Rust offers by returning a result type, allowing the function to fail gracefully if needed.
00:10:12.400 Error handling in Rust is vastly different from exceptions found in languages like Ruby. You work directly with result types that express success or error, which helps with handling predictable failures.
00:10:28.070 This error handling pattern allows chaining operations while seamlessly managing failures. Essentially, each function returns a status indicating if another operation can continue.
00:10:43.800 Being able to manage states across multiple threads with ownership guarantees means you can share data safely without experiencing traditional pitfalls like use-after-free or double-free memory errors.
00:10:59.680 This code example demonstrates a simple thread-safe increment using a mutex. It allows synchronization between threads while tracking state without any conflicts, ensuring safe concurrent access.
00:11:14.080 Additionally, notable Rubyists such as Yehuda Katz and Sean Griffin are currently working in the Rust community. Katz contributed to Bundler and Ember.js and is involved in the development of Rust's package manager, Cargo.
00:11:30.800 Sean Griffin is known for his work with Active Record and has developed Diesel, a popular library for interacting with SQL databases in Rust, which provides a similar ease to Ruby developers.
00:11:48.500 There are some interesting libraries in the Rust ecosystem that aim to integrate with Ruby, including Rayon for data parallelization and Serde for serialization/deserialization of data structures.
00:12:06.100 Another promising tool is Bindgen, which generates Rust bindings from C header files to facilitate embedding C or C++ applications with Rust’s reliability.
00:12:23.600 Helix is also noteworthy, allowing Ruby developers to write extensions in Rust, which integrates Ruby classes with Rust methods seamlessly through a foreign function interface.
00:12:37.460 I want to address the rising interest in WASM (Web Assembly). Rust can compile natively to Web Assembly, making it a viable choice for web front-end development, even enabling integration with frameworks like React.
00:12:55.710 Some companies that currently use Rust include Firefox, Dropbox, and Cloudflare. Rust’s reliability and performance make it a solid choice for resource-critical applications.
00:13:11.750 Crunching some more names, Parity is an Ethereum client written in Rust. Companies like Facebook are also exploring Rust for various applications.
00:13:28.700 So, to wrap up, while my company is still using Ruby and Ruby developers, I see great potential in introducing Rust to our team.
00:13:44.260 If you’re interested in trying Rust, check out the newly updated Rust website! I whipped this all together just last night, so if there’s anything I didn’t cover, please feel free to ask!
00:14:01.560 Thank you!
00:14:43.390 If I can use my own experience as an example, I haven’t developed in C for about five or six years. I’ve basically forgotten everything about it, but I found the functional aspects of Rust intriguing enough to push through some initial challenges.
00:15:18.330 I believe it is absolutely graspable for Ruby developers. The Ruby core team is focusing on performance now, similar to how Rust is emphasizing usability and documentation.
00:15:37.730 The Rust community realizes the importance of having well-documented codebases with examples, which has significantly improved in recent years.
00:15:52.770 Overall, Rust's ease of tooling and supportive community makes it a pleasant language to learn. You can get help and find answers on platforms like Reddit, where others are eager to assist you with your questions.
00:16:08.770 Feel free to reach out with any queries or thoughts!