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!