Talks

Steal This Talk: The Best Features Ruby Doesn't Have (Yet)

Steal This Talk: The Best Features Ruby Doesn't Have (Yet)

by John Feminella

In the talk "Steal This Talk: The Best Features Ruby Doesn't Have (Yet)" by John Feminella at RubyConf 2017, he explores how Rubyists can enhance their programming experience by learning from other languages known for their engaging features. The main themes include the historical influences on Ruby, future speculations for its evolution, and practical ways to implement novel features presently absent from Ruby.

Key points discussed include:

- Historical Perspective: Feminella emphasizes the importance of understanding Ruby's roots and influences from various languages like Lisp and Smalltalk, highlighting that programming languages are cultural and technological artifacts shaped by their time.
- Future Speculation: He speculates on potential shifts in Ruby by looking at specific characteristics that may enhance its usability and longevity, drawing inspiration from contemporary languages like Elixir and Swift.
- Learning from MUMPS: The talk highlights MUMPS, a language from 1966, as a case study to demonstrate unique features such as its built-in database which could inspire changes in Ruby regarding data handling.
- Error Messaging: Feminella discusses enhancing Ruby's error messages for better guidance, advocating for contextual information similar to that found in other languages like Elm, which provide clearer feedback.
- Exception Handling: He suggests that Ruby could benefit from tripartite exception handling mechanisms found in languages like Lisp to create repairs directly in error management.
- Pattern Matching and Module Shadowing: The discussion includes implementing pattern matching to handle object states more robustly and improving clarity around method overrides with explicit annotations.
- Type Inference: Feminella introduces the concept of gradual typing and type inference as potential features to ease code transitions and enhance Ruby's capabilities.

Feminella concludes his talk by encouraging the Ruby community to adapt and experiment with these concepts to keep Ruby exciting and enjoyable, reinforcing that learning from both predecessors and contemporaries can drive innovation within Ruby. He invites participation via Twitter for follow-up questions and fosters a collaborative atmosphere post-talk.

00:00:10.410 All right, so welcome to "Steal This Talk". Today, I hope to give you some of my thoughts about how we can make Ruby more fun by learning from other languages.
00:00:16.540 These languages have also tried to make fun a priority. A couple of notes before you begin.
00:00:21.820 It is impossible for me to stand up here under the same lighting conditions that make me look really well-lit and naturally glowing.
00:00:28.240 Additionally, this lighting makes it hard for me to see anyone in the audience.
00:00:35.379 So if you have your hand raised or anything like that, I'm absolutely not going to be able to see you.
00:00:41.320 Please feel free, however, to use my Twitter handle to tweet me questions.
00:00:48.670 I will get a buzz on my phone when that happens, and I will respond to the questions that way.
00:00:54.040 Hopefully, this will make for an engaging session as people have questions, and if I don’t get to your questions during the talk,
00:01:05.140 I promise I’ll respond to you on Twitter afterwards.
00:01:10.240 If you hate Twitter or just don't want to use it or don't have a Twitter account, that's 100% fine too.
00:01:16.090 Please feel free to email me, and I'll also respond to your questions in the same way.
00:01:23.200 All right, so just really briefly about me. I work for a wonderful company called Pivotal.
00:01:29.679 Some of my fellow employees are up here in the front two rows.
00:01:35.709 What I do there is work with enterprise companies who face a lot of challenges with how they build, deliver, develop, and design software.
00:01:42.190 Writing software is difficult, and through that process, we get exposed to many different ways that people write software,
00:01:48.369 different languages, and various assumptions about what is and isn't okay to put into software.
00:01:56.259 I think that experience has formed the basis for this talk and exposed me to a lot of different ways of thinking about software and the tools that we use.
00:02:02.259 I'd like to cover basically four themes.
00:02:07.360 One is where do we come from as Rubyists? What are the ancestors of Ruby, and how have those languages influenced not only Ruby but also the broader programming community?
00:02:15.790 Second, given that background, where might we be going in the future? What aspects of Ruby are probably going to be around long-term, and what might we see change?
00:02:23.329 This is all speculation, of course; I know I'm not a dictator regarding the direction of the Ruby programming language.
00:02:33.709 But what could we speculate on, and what are some things we're seeing in other programming languages that might be applicable to Ruby?
00:02:38.810 Also, in the spirit of Ruby's current feature set and goals, what are some ways we could get there?
00:02:46.310 I will show you some reference implementations of these ideas that are certainly not production-ready.
00:02:51.709 There's a GitHub repo for it where I basically modified parts of the Ruby source code to produce these effects or some facsimile of them, at least.
00:02:58.400 Then I'll close with a discussion about how we can do it to hopefully motivate you to try out these kinds of experiments on your own.
00:03:03.439 Let’s start with where we are right now. The best way to understand where Ruby might be in the future is to look at how it got to where it is now.
00:03:09.439 So let’s go back a bit into the history books.
00:03:14.989 There’s a famous quote from George Santayana: "He who does not learn from history is doomed to repeat it." So let’s ensure we learn our history concerning Ruby.
00:03:22.340 We use programming languages for all kinds of reasons.
00:03:27.620 Some people just want to do work, while others are using it for fun or to do science.
00:03:32.780 Some people use Ruby simply because it's enjoyable.
00:03:37.819 Programming languages don’t exist in isolation; they are as much cultural artifacts as they are technological ones.
00:03:43.549 They are products of the time and the assumptions made when they were designed and the challenges their designers faced.
00:03:49.449 Of course, the people who contributed to the language in the first place need to be considered too.
00:03:55.760 The chief advantage of programming languages over other kinds of tools is that they are malleable and mutable—they can change over time.
00:04:02.359 If you mass-produce millions of screwdrivers and then discover they were supposed to be hammers, that's a big problem.
00:04:09.650 In programming, however, if there's a problem, we can change it; we have that power.
00:04:15.409 So the question is: Can we make those properties better for the tools that we have?
00:04:20.449 If so, how? To explore that, I want to look at another programming language that is much older than Ruby but is still around.
00:04:25.909 This language is the Massachusetts General Hospital Utility Multi-Programming System, or MUMPS for short.
00:04:30.950 MUMPS is almost the opposite of Ruby in the sense that Ruby is considered a general-purpose programming language.
00:04:36.380 MUMPS, however, is general-purpose with respect to its Turing completeness but very specific about the kinds of business problems it addresses.
00:04:43.400 It turns out nobody likes saying the entire acronym, so it is commonly referred to simply as M.
00:04:49.910 It’s worth noting that naming it after a deadly disease was perhaps not the brightest decision.
00:04:56.390 MUMPS looks archaic by today's standards; however, if you rewind the clock to 1966 when it was created, it was comparatively modern.
00:05:02.390 Despite its archaic appearance now, MUMPS has some of the most intriguing and, I would dare say, novel features.
00:05:08.690 It's difficult to find some of these features anywhere else, showcasing how it addressed business issues at the time.
00:05:14.989 I want to take you back about fifty years to 1966.
00:05:22.340 In 1966, NASA had just finished the first-ever space docking.
00:05:28.330 The U.S. Supreme Court had just decided on the Miranda case, establishing the Miranda warning.
00:05:34.210 And the Batman series starring Adam West had just debuted on television.
00:05:39.219 In the same year, the New Orleans Saints were created as an NFL franchise.
00:05:47.349 The NFL needed an antitrust exception to merge with the AFL, and the two senators blocking it were from Louisiana.
00:05:56.050 They agreed to create the New Orleans Saints in exchange for votes to pass the deal.
00:06:03.550 However, you probably don’t care about any of that because as a technology director for the Massachusetts General Hospital system, something much more important happened in 1966.
00:06:11.120 Transistors, which had been around for a while, started becoming miniaturized and cheaper.
00:06:18.050 They began finding their way into sensors in small devices capable of taking readings from patients.
00:06:25.440 Doctors loved these sensors because they eliminated the need for a team of nurses to gather routine patient data.
00:06:31.430 What used to take an hour could now be done by a set of wires and recording instruments.
00:06:37.010 This means each doctor could handle more patients than before and provide better care.
00:06:43.110 However, the challenge was how to implement this in a hospital of that size.
00:06:50.050 How would you manage the multitude of data points being collected every second?
00:06:56.080 How could you report this data in a way that would be human-readable and accessible to practitioners?
00:07:01.060 In 1966, MUMPS was trying to solve a problem akin to today's IoT challenges.
00:07:08.200 At that time, the sensors were distributed all over the place and really basic—they could only write data.
00:07:14.790 If you missed just one or two data points or recorded the wrong value, it could lead to a false diagnosis or incorrect treatment.
00:07:20.340 In the worst-case scenario, it could mean not noticing a patient had a serious health issue.
00:07:27.020 So how could you get that wide stream of data into a system that would reliably record it? That's what MUMPS was designed to tackle.
00:07:36.030 MUMPS has a built-in database.
00:07:41.599 When I say "built-in database," you might think of a standard library function for talking to databases or some communications protocol.
00:07:48.110 But that's not what I mean. The memory model for MUMPS programs is not like the linear memory of most modern environments.
00:07:55.240 Instead, it's a key-value store, which means that you read and write variables in memory by addressing and querying them inside this database.
00:08:01.350 Essentially, all MUMPS programs had a tiny version of MongoDB inside them long before it was cool.
00:08:07.990 That was MUMPS, but let’s consider what that might look like in a pseudo version of Ruby attempting to achieve similar functionality.
00:08:15.080 A standard assignment in other programming languages might look like the following, where you assign the right-hand side of an operation to the left.
00:08:22.600 In MUMPS, the operations are very different—it's a matter of setting keys and then querying those keys in the database.
00:08:30.590 Instead of straightforward assignment, you can perform operations that yield new keys or sets of values.
00:08:36.090 While it might visually seem similar to assignment, what's unique about MUMPS is that you can, for instance, ask to show all variables that start with a particular letter.
00:08:43.700 This functionality would be more challenging to replicate in modern programming languages.
00:08:50.220 When we talk about dynamic capabilities of MUMPS, we are considering features akin to metaprogramming.
00:08:56.850 Remember, we are looking back to the year 1966, when metaprogramming was not yet a widely recognized concept.
00:09:01.149 The ability to introspect your program dynamically was an innovative solution to the challenges they faced.
00:09:09.560 They essentially took all of this data and dumped it directly into this database—there was no intermediate remote connection.
00:09:17.060 The database was the program.
00:09:24.140 This is a revolutionary way of solving problems: integrating a database directly into the execution process.
00:09:31.590 This raises the question of whether we can apply what we've learned from Ruby's predecessors in similar ways.
00:09:38.020 Languages are designed based on the best solutions available given the constraints of their time.
00:09:44.559 Thus, Ruby also reflects the influences and ideas from those that came before it.
00:09:50.039 Just look at Ruby's ancestors or its historical influences. When we consider the evolution of programming languages, it's essential to acknowledge what contributed to Ruby's shape.
00:09:56.590 For instance, Lisp, a historical predecessor, is one of the oldest high-level languages, while Smalltalk introduced an idea of dynamic objects.
00:10:04.040 Ada and other languages continued to develop structural elements that Ruby later benefited from.
00:10:10.150 What about languages that are roughly contemporary with Ruby? Consider JVM-based languages such as Java.
00:10:16.230 More recent languages like Scala and Clojure have also drawn inspiration from Ruby.
00:10:22.090 On the other hand, newer languages like Elixir and Swift have taken cues from Ruby or featured developers who were originally Rubyists.
00:10:30.120 So today, I want to discuss the aspects of those languages that might be interesting to bring back to Ruby.
00:10:35.000 I'll divide this into a landscape of possible choices, representing things that could lead to improvement for Ruby.
00:10:43.600 On the left axis, we'll look at things that yield more payoff for Ruby.
00:10:48.480 The bottom axis, from left to right, comprises things that require more work.
00:10:54.410 For instance, implementing gradual typing might require more effort compared to something like altering a few error messages.
00:11:01.080 On the line, we will identify a fair trade-off: effort and payoff.
00:11:07.540 Things above the line have more payoff for less work, and those below require more work for less payoff.
00:11:12.970 We'll start off with relatively easy implementations based on my simplistic approach and a Ruby GitHub repository.
00:11:20.490 Let’s take a look at error messages.
00:11:25.900 When starting in any programming language, the first thing you encounter is probably the REPL or a simple 'Hello, world!' program.
00:11:34.030 However, the second thing you see is when you mess up, and you receive an error message.
00:11:40.500 Your first negative experience will be defined by how helpful that error message is in guiding you to fix the issue.
00:11:47.920 Let’s start with a simple but incorrect C++ program.
00:11:54.460 It’s not syntactically valid because it needs a type for the variable and lacks a main declaration.
00:11:59.390 Imagine counting the number of error lines generated by trying to compile this program. How many errors do you think there would be?
00:12:05.310 This is, of course, a trick question! So let’s hop over to the demo.
00:12:10.650 Here’s that same file we saw before; let’s try to compile it.
00:12:16.460 After compiling, we generate about twenty thousand error lines.
00:12:22.670 And the result states that the type needs to be defined and becomes convoluted.
00:12:30.300 This experience, while extreme, is not user-friendly.
00:12:36.300 So let's look at Ruby. When you write a simple program to add two arguments, and you provide different types, Ruby will return a type error.
00:12:43.720 However, in addition to showing a problem, Ruby also indicates the source of that issue.
00:12:50.290 In comparison, Elm shows an error with contextual information, highlighting the line and explaining why the mismatch occurred.
00:12:58.310 This clear communication indicates both what the expected type was and what was actually passed.
00:13:07.250 Returning to Ruby, when we experience actual errors, we're often just presented with a stack trace.
00:13:14.400 Ruby tells you the line where the issue is but lacks precise contextual definitions for that error.
00:13:20.260 It’d be much better if Ruby could indicate which value contributed to the error and why.
00:13:27.040 Adding context to these error messages, clearly identifying salient values involved and defining the differences between expectations and reality, would be extremely beneficial.
00:13:34.060 Let’s move on to exception handling.
00:13:41.700 Ruby primarily follows a bipartite strategy: one part of the code handles when things succeed, while another addresses failures.
00:13:50.050 In contrast, Lisp and some functional programming languages utilize tripartite handling.
00:13:54.870 In this approach, you set an invariant.
00:13:59.390 When that invariant is violated, the code will branch into a section designed to handle that specific issue.
00:14:06.530 This way, you can create a repair mechanism directly in your error handling.
00:14:12.038 Another area worth discussing is pattern matching.
00:14:17.810 In Ruby, we have case statements for branching based on object states.
00:14:24.700 However, pattern matching requires you to enumerate every possibility for the object, ensuring no stones are left unturned.
00:14:31.570 Essentially, it guarantees that any possible outcome is handled in your code.
00:14:36.460 This is kind of like static type checking without a full static type system.
00:14:41.599 Next is the topic of explicit module shadowing.
00:14:47.640 In Ruby, when you mix in modules, you might want to override a method that is already defined in one of those modules.
00:14:54.970 However, without a clear note indicating that you are overriding a method, it can be confusing for future readers of your code.
00:15:01.130 We could benefit from a solution that explicitly marks when methods are being overridden.
00:15:08.600 This way, anyone reviewing the code can understand the intention behind the method definition.
00:15:15.900 Another topic is type inference; while not new, implementations are cropping up more in different languages.
00:15:23.590 Type inference allows the programming environment to deduce the type of a variable.
00:15:30.530 Imagine a future version of Ruby that utilizes gradual typing; type inference could make transitions smoother.
00:15:35.290 This way, the user won't need to redefine types for everything they’ve created.
00:15:43.220 Instead, the Ruby interpreter would automatically fill in the necessary metadata.
00:15:49.660 The incorporation of all these ideas and a healthy appreciation for learning from both predecessors and contemporaries can empower Ruby.
00:15:57.000 Ruby has thrived before and can continue to do so with these insights, ensuring it remains exciting and enjoyable to use.
00:16:04.290 This concludes my talk; thank you for listening!
00:16:22.510 Let me see if there are any more Twitter questions. Is the mic on? Yes? Okay.
00:16:33.920 Keith Walsh asked regarding type inference, have you checked out Crystal?
00:16:45.100 Crystal looks almost exactly like Ruby but with strong typing and interesting features.
00:16:52.290 It’s appealing to those who enjoy the aesthetic of Ruby but prefer static typing.
00:16:58.400 However, none of the libraries from Ruby work in Crystal as they are not binary compatible.
00:17:05.510 In contrast, languages like Elixir share some similarities with Ruby thanks to their Rubyist roots.
00:17:12.640 The beauty of Ruby is evident, inspiring many to modify and enrich the core concepts further.
00:17:19.370 Yes, Keith, I have heard of Crystal; it’s cool, but I’m still learning more about its traits.
00:17:26.570 Are there any other questions?
00:17:34.350 I think there's another question about the font.
00:17:39.950 The font is fast! Size VIII is my favorite.
00:17:46.010 Thank you! I hope you enjoyed the talk.
00:17:51.050 I didn’t see any other significant questions, but I will follow up with everyone afterwards.
00:18:00.520 Thank you again for sitting through the technical difficulties, and have a wonderful rest of RubyConf!