Episode 37

Introduction to Ruby

00:00:00
/
00:40:56

January 17th, 2024

40 mins 56 secs

Your Host

About this Episode

The panelists discuss Ruby, a primary programming language at Acima, notable for its popularity in startups and major companies like Shopify and GitHub. They attribute its success to the Ruby on Rails framework and the language's community support. Mike shares a personal story to parallel the complexity of understanding Ruby, linking it to its creator, Yukihiro Matsumoto (Matz), who views Ruby as a language of love, embodying a philosophy of developer happiness and care.

Additionally, the group explores Ruby's technical aspects, focusing on its object-oriented and functional programming features and syntax that mirrors spoken language, simplifying programming. They discuss Ruby's history, its influences from languages like Perl, Smalltalk, and Lisp, and its evolution with Ruby on Rails. Additionally, they touch upon Ruby's versatility beyond web development, its role in shell scripting, and considerations regarding its scalability. They end with an endorsement of Ruby for its user-friendly approach to programming, prioritizing problem-solving and user experience!

Transcript:

MIKE: Hello, and welcome to another episode of the Acima Development podcast. I'm Mike. I'll be hosting again today. We've got a group of us here with me. But yeah, kind of starting, we've got Sergio, Eddy, Dom, and Jonathan.

Today is a topic that I have been interested in for almost decades now, which is the Ruby programming language. At Acima, we do a lot with Ruby, and it's been our primary language. It is not the only one we do, but we've done a lot of Ruby for a long time. And I've done Ruby for a long time. A lot of us here have done Ruby for a long time.

And certainly, there's reasons to do Ruby, you know, it's got a community. Ruby on Rails framework has been popular for a while. It was particularly influential, like, I don't know, 15 to 18 years ago [laughs] and has continued to be used a lot by startups in particular. And there are some, you know, major companies using it, such as Shopify or GitHub. There's a community out there of Ruby users. And there's reasons just for that.

But today, we're going to talk about the language itself and what it is. So, if you're interested in a quick whirlwind tour of Ruby, that's what we're doing today. And I'd like to start with a story. I think a story is a great way to begin a podcast. When I was in ninth grade, I remember an essay assignment I was given. And I remember because I had no idea what to say. [laughs] And I think we were studying Romeo and Juliet, and we were supposed to write some essay about love. And I don't even remember what exactly about love we were supposed to say, but we were supposed to write something about love.

And I remember that I thought about it, and I didn't know what to do. So, I wrote some sort of silliness about how love is poorly defined and lots of people see it differently. And I spent all of my time talking about the question rather than actually answering it. It was probably a pretty lousy essay [laughs]. I probably wouldn't even remember it. I think I stumbled upon it some years later, and I read through that [laughs].

But, you know, I had this question. At that age, I really wasn't sure. I didn't know how to define love very well. And there are a lot of different answers to that in the world. Well, there's one very interesting answer to that question. The Ruby programming language was created by a guy named...I'll try to pronounce his name right. It's Yukihiro Matsumoto, and he's lovingly referred to by the community as just Matz. They shortened his name to just Matz. And he's very much beloved by the community.

He has said on more than one occasion that the Ruby language is love, and that says a lot about what the Ruby language is. And I'm going to talk a little bit more about the history [laughs]. But the Ruby language was created to be an embodiment of that idea of, you know, I care about you. I want to make your life better.

The Ruby language is built on ethos. And, in fact, there's a saying within the community, "Matz is nice, and so we are nice," MINASWAN [laughs]. The creator is nice. He wants to be nice to us. He tries to be nice to us. He reaches out with his language and also just his demeanor. If you've ever seen him speak, he's just a soft-spoken, super nice guy. And the language reflects that aspect of Matz, the creator.

If there's kind of one thing you leave with about what Ruby is, it is this language that's supposed to make you feel good [laughs] and then lift you up as a person. And, hey, well, a programming language does that? Well, it's kind of its goal. Different programming languages have different goals. Some languages have been intended to be very high-performing. They're really good at running fast, and that's a great goal, right? We should have some languages to do that.

Other languages take a particular idea, like being functional, and take it to its extreme. What would happen if we made a purely functional language? And I'm thinking about Haskell here. But there's some other languages that go that direction. Other languages focus maybe on type safety or on whatever particular problem they have at the time.

Well, Ruby focuses on developer happiness. It's a language that was designed from the beginning to try to make developers happy so that if you're a software engineer and you use this language, it makes your day a little better. And that's what Ruby is about, as opposed to other languages. It doesn't mean the other languages are bad. In fact, Ruby is not written in Ruby; most implementations of it are not anyway [laughs]. Ruby is written primarily in C, which is one of those high-performing languages. So, every language has its purpose. But Ruby is intended to make your life happier as a developer. Did Matz succeed? [laughs] Do you feel loved?

EDDY: I'm curious about the time why the name Ruby was given. Was it just because it signified or represented love at the time, or is there some sort of correlation with the name and happiness?

MIKE: That's a good question. The one thing that I have heard about Ruby is Matz was inspired by Perl, which is another precious stone [chuckles]. And he came up with Ruby to kind of mimic that idea and [inaudible 05:08] Ruby is following kind of a similar niche, where it's an effective scripting language, easy to use. And it may be that Ruby references some of that a lot, you know, it's this red stone. And it's kind of heart-shaped frequently in its cut.

So, I can't speak to that for sure. I don't know the answer. You'd have to ask Matz. I have not heard about that. If anybody knows, you know, please speak up. But I was having the same thoughts as I was talking about it. Well, he says Ruby, the language, is love. That stone could represent love. And so, it [laughs] might actually be a symbol that's suggesting that gift he's trying to give back with. Have you felt the love when using Ruby?

EDDY: It's easy to pick up, I will say that. You take the layer of complexity of syntax out of the equation, and suddenly, you're one step closer to thinking as a programmer.

MIKE: Ruby is a language that's designed to read a lot like spoken language. That definitely changes the way you think [laughs]. Instead of trying to think like a machine, you think more like a person. Certainly, you do have to think somewhat like a machine for developers [laughs]. But the syntax fits a little more naturally to the way that humans speak.

Let's talk about that. Let's talk a little about the history and why that might be. So, Ruby, the first release—and I've looked this up—the first version of the Ruby programming language was released on the 21st of December 1995, so we're going on 30 years. It's been around for a long time. And Ruby was and certainly inspired by other programming languages. I'm going to try to quote Matz a bit [chuckles] in several ways.

But he said that he was inspired by several other languages. I'm going to point out three of them: Perl, Smalltalk, and Lisp. Perl is this kind of utility knife of a language. You use it for scripting. A lot of early websites...Perl isn't used as much for this anymore. But a lot of the early web applications were built in Perl because it's this really useful text processing language that was originally kind of used more for shell scripts but, well, for other text scripting scenarios like you have with a web app. So, Perl was a big inspiration for Ruby.

And Smalltalk–and I'm going to talk about that next; Smalltalk is a pure object-oriented language. It's not just a language. It's like an environment. You get, like, this Smalltalk environment you interact with, which was actually influential in a lot of other languages. Object-oriented coding has really taken off in the years since, but it was really experimental and new when Smalltalk came out.

And the thinking that everything could be an object was kind of a radical departure from some of the ways other languages think about things, and Ruby embraces that. In Ruby, everything is an object, and when I say everything, I mean everything. An integer is an object. You can call functions on an integer. A string is an object. You can call functions on a string. There are no true primitives in the way that a lot of other languages have. Well, here's the, like, when you think about Java, you have primitives that you don't call things on. They're a different thing from everything else. In Ruby, that's not the case. Everything is an object, kind of taking that Smalltalk inspiration.

And the other language that I'm going to call out is that Lisp, which is a very functional language, kind of the archetypical functional language that other functional languages have drawn from. In functional languages, you think about everything as a function, you know, the unit in functional languages is the function. In object-oriented languages, you think about...you structure your modules with objects, right? And your object is your unit. You have classes, and you build objects from those. Well, functional programming thinks about things a little differently. It groups things in functions, [inaudible 08:47] that objects don't have functions. But when you're thinking about kind of the primary organizational idea in functional languages is functions, and Ruby embraced that from Lisp.

In Ruby, every expression has a return value, which means that you can write anything that could reasonably evaluate as an expression in Ruby, and it has a meaningful return value. If you write the number one, you can run a Ruby program with just the number one in it, and that is a valid Ruby program. In some other languages, that wouldn't make any sense, but in Ruby, that makes sense. It's an expression. It's the number one. It has a return value of one. [inaudible 09:23] doing something, right? It's expressing this number, and it even has a return value.

And that changes the way you think about things, this idea that comes from functional programming where everything is an expression. Everything has an implicit return value because that expression evaluates to some value. And that idea is deeply embedded in Ruby as well. Not only is it object-oriented, where everything is an object, everything is also an expression, which implicitly has a return value, which means you could think about every expression as somewhat implicitly being a function as well. It also leans heavily into the idea of anonymous functions, but I'm going to hold off on that for a little bit and go back to this idea of its creation.

So, I want to give you a little history of Ruby. Ruby is this language that takes these big ideas of functional programming and object-oriented programming and smashes them together into a scripting language. And it gives you Ruby to try to make this tool that makes developers happy. Ruby was created in Japan. Matz is Japanese. He lives in Japan. I believe he still lives there [laughs]. And has developed there for a long time.

Because Ruby was originally in Japan and had documentation in Japanese, it became fairly popular in Japan. It became a popular programming language there because you could get documentation in Japanese. All of us like to be able to read things in our native tongue, so [laughs] it makes a lot of sense. So, it became kind of this niche language that was popular in Japan. Eventually, it started reaching out of Japan as other people discovered it. In particular, in the mid-2000s, there was a development team that decided that they would use Ruby to build a new web framework called Ruby on Rails.

And I believe that Ruby on Rails was—I'd have to go look this up—was released around 2005. It made a big splash in the web application community/web development community by its usage of convention over configuration [laughs]. At the time, most web development involved setting up lots of configuration files for everything. Anybody who did Java development back in the day, you know what I'm talking about [laughs], so many XML files.

The Ruby on Rails, this framework, cut through a lot of that and said, oh yeah, let's just do the obvious thing by default. You don't even have to configure it. And the object-relational mapper it had called Active Record, as a result, was really easy to use in a way a lot of other systems weren't. Now, other frameworks have borrowed a lot of those ideas. So, Ruby on Rails really isn't this path setter anymore. It's not in the vanguard because other frameworks have taken the same ideas, which is fantastic. Web development is better as a result.

But it meant that Ruby made a big splash and was heavily used by startups in the United States. You know, it had left Japan, still there in Japan, but it became heavily used throughout the world by largely web developers because of the Ruby on Rails framework. It's been somewhat in decline in recent years. Some other languages have become more prominent, but it's still got a thriving community behind it.

EDDY: Who did the transcribing for when it left Japan, do you know? Like, who did all the documentation translations and --?

MIKE: That's a great question. I don't personally know the answer to that. I know that Matz himself is, you know, bilingual. He speaks English [laughs]. Japanese is his primary language, but he knows English. He has spent some time in the United States, which I think has helped a lot [laughs], helped him to document things in more languages than one.

Let's talk a little bit more about the language then. We've talked a little bit about how Ruby is object-oriented all the way down. And it's also functional, deeply functional all the way down. So, I gave an example of how you can just write any expression. You could write a string or an integer. That's a valid Ruby program. Just put a string into a file; that is valid Ruby. It's not very useful [laughs], mind you. But you could run that as a Ruby file and give it a Ruby extension. You don't even need a Ruby extension. Call the Ruby interpreter, and it will be interpreted successfully and will run because every expression is valid Ruby that can be written in Ruby.

That has some side effects in that if you have a function written in Ruby, you rarely need explicit return values, and, in fact, most Rubyists don't use them. And this is common among functional languages, that the value of the final expression in the function is implicitly...because everything has a value, right? Every expression evaluates to a value. That is the return value of the function. So, to return something in Ruby, you just simply write the expression you want to be returned as the final line in your function.

And for those who've been using more procedural languages, that is weird. But I'm not going to tell it to return things [laughs]. But, in Ruby, it's not that way. Instead, you think about, well, what does this mean? Well, it's saying something. Well, that's what it's returning, the thing it said. You don't have to say, "Hey, this is the thing I want to say." It's already implied because I've already said it. And that idea, going back to this idea of convention over configuration, kind of goes all the way down. Everything is an expression.

I'll take that a little bit further. Ruby does not require parentheses in function calls. So, you can call functions without using parentheses; just put some spaces in there. [inaudible 14:30] put commas between your parameters. That means in cases where you have a function that doesn't take any parameters, it's indistinguishable. If you don't put parentheses, it's indistinguishable from another expression. And that can feel kind of weird if you want to be able to tell the difference. Ruby actually kind of leans into that; some Ruby actually kind of leans into that.

So, when you're reading the code, you don't have to know if a given line is an expression or a function because it's kind of both. And it allows you to build out domain-specific languages; that is, you can write out code that looks more like configuration than it does, like, a traditional programming language. And you can write out little sub-languages within Ruby that look very much like their own language where some of these things that look like keywords are really just function calls. But they appear to be a keyword because you don't need the parentheses. It makes for some very legible tools; tools such as RSpec, a popular testing framework in Ruby are built in that way.

One other thing about Ruby is that there is...I want to be careful how I say this. It is implicitly typed. We do not use explicit typing in Ruby. So, if I set a variable equal to an integer, I never had to declare that that variable was an integer. However, I can't then go and add that integer to a string. That doesn't make sense. So, it is strong typed in that there's not implicit casting; rather, everything is typed. It's just implicitly typed.

That also allows you to do some really cool stuff. Unlike in other languages where you might need to write five different copies of a function to take five different types of incoming parameters, you can just write a single method signature that can take the incoming parameter and expect the incoming parameter to be an object. In fact, that's how Ruby expects things to work.

Since everything is an object, you can pass an object into anything, and they handle the type later. It allows for really clean calling syntax. If for some reason I did want to add a string to an integer, I could write code to do that and make it very transparent. I could make it very transparent so that other people didn't have to know about it. It would just work within my program. I'm not saying that's a good idea, mind you [laughs]. But if you had some need where you needed to add two of your own kinds of objects that were neither integers nor strings, you use a plus sign. It's easy to just define that method to do so and put them together.

I can take this a little bit further. And this is both a strength and a weakness. Ruby leans into what we call duck typing. That is, if it walks like a duck, talks like a duck, quacks like a duck, it must be a duck [laughs]. And so, what you see commonly in Ruby code is that you don't have a lot of validation on parameters that get passed into functions. You kind of expect the callers to do the right thing.

So, if something meets the requirements of what your function needs, you're not going to ask about its type and, instead, you're just going to assume that they gave you what you needed. In other languages, you might use some templating features built into the language. Ruby, you don't need to do that. It's kind of implicitly a template. We're just going to assume that you're going to do the right thing.

And, of course, if you want to do validation, you're more than welcome to do so, but you need to be explicit about it, and it's not going to be built into the language. Again, this is a strength and a weakness. It means that you can have very easy refactoring of your code where you can pass in a different kind of object to a function, and it'll still work.

On the flip side, you don't get some of the type safety guarantees that you get in strongly typed languages that put a lot of validation on type. And it means you get different kinds of bugs. It means your code tends to be a lot shorter…a lot easier to reason about in Ruby. However, you can get some type safety bugs that you would not get in other languages because I think it's a big thing to notice.

This wading into, hey, you know, everything's an object; you can pass anything anywhere; it allows you to write code that's just amazing, legible, and terse, and easy to refactor. It also means that you can end up with subtle bugs sometimes because type safety bugs are hard to face. I'm not saying that it's a showstopper. But depending on your domain, you know, some people would argue that's a serious problem.

And there actually are several different tools within the Ruby community for dealing with this, for adding type, some that add type within the language, and some that add it by adding an additional file. It's kind of experimental, but you can add a type file adjacent, you know, kind of next to your Ruby file to add typing to it. So, you can get some of that type safety you get from other languages.

RAMSES: Yeah. There's tools like Sorbet that provides the type checking, which is very interesting.

MIKE: And for large companies, like, Sorbet came...did that come out of Shopify? I'm trying to remember --

RAMSES: Yeah, yeah, I believe so.

MIKE: I believe so, too. They built this tool because they wanted to have the best of both worlds. They wanted the expressiveness and ease of use of Ruby but still have the type safety. So, they've built some tooling to provide that. So, there's tools available to give you the type safety that you'd like to have in Ruby, if that's something that's important to your use case. And I think that it's important to a lot of use cases, something that I actually encourage leaning into in a new Ruby project. It avoids certain kinds of bugs and allows you to be explicit about what you intended to happen.

The next thing I'd like to talk about that Ruby does...we talked about everything is an object. We talked [laughs] about some of the things it does, getting those advantages of being truly purely object-oriented where everything is an object. Actually, I'm going to talk a little bit more about that. [inaudible 20:06] everything is an object. It also has some sort of class, you know, that prototype that you use to define it. And you do not have to completely define that class before your code runs. It can be written at runtime. It also means that you can reopen classes and start adding functions to them or even change their behavior at runtime.

Coming back to this Lisp idea [chuckles], I mentioned Lisp before as one of the inspirations for Ruby. In Lisp, you can rewrite the program. The program can write itself as it runs. And that's a really weird idea when you first hear about it. We actually do it all the time in Ruby. We have code that writes code.

I mentioned the Object Relational Mapper in Ruby on Rails, ActiveRecord. It accomplishes a lot of what it does by what people call magic, but not exactly magic. It just uses Ruby's features to go in and look at your database, check out the table name, and figure out where the columns are, and let's go ahead and write some functions. Go ahead and write some functions at runtime into your class to be accessors to those column names within a record.

And so, rather than having to explicitly define something that's already there, it can just look it up and generate it on the fly. You're not usually going to do that in your code, but for a framework, that's amazing. It means that a lot of the configuration...if something is discoverable in the world, the code can write itself. It can go out and write methods at runtime that didn't have to be conceived of [laughs] by the people who wrote the framework. They just had to write code that's able to do that perception of the outside world and deal with it accordingly.

It's amazingly powerful. And it's one of the strongest aspects of the Ruby on Rails framework because it allows it to be very terse and very easy to understand. So, it's a practical use, right? Why would a code want to write code? Well, it's because you don't necessarily know, when you're writing a framework, what code you're going to be working with. And you don't want to have to explicitly say all those things because it's discoverable. So, code that can discover some things about the world around itself and write new code within itself to deal with those things is actually incredibly useful.

Listeners can probably think, oh yeah, well, what's some things I could discover? Well, maybe you're working with some web service that tells you about the weather. Well, you could have code that goes and pulls that and figures out what fields are available and then creates functions to tell you. And then, again, while running live, it could do some self-analysis, some reflection on itself to determine what things are available, to determine what could be printed out to a screen.

It's a different way of thinking about things than thinking about things as just text processing. It leans into this idea of, well, this is an object, and I can learn some things about this object and use that for display. And this is just an idea popped up with-it might not even be a good one—off the top of my head. But it allows you to think about the world differently, think about the ability to create objects that represent the world on the fly that you didn't know about when your program launched. That's a level of usability that is really great [laughs]. And it may feel weird when you first hear about it, but it ends up being exceptionally useful.

The next feature I'd like to mention about Ruby that I think is maybe the most idiomatic of all of the Ruby features, and I've mentioned some things that are very Ruby-ish, but there's one that's the most Ruby-ish of all Ruby things, which is that Matz built-in language support with special syntax for anonymous functions. And that is fundamental to your development as a Rubyist.

We've talked a lot about the object-oriented features. Now, we're going to talk about some of the functional features. Again, Ruby has a built-in syntax with special scoping rules for anonymous functions. They call those anonymous functions blocks. And people who've started using Ruby might not even think about it that way. Like, a block is a function? Well, yeah, it's a function [laughs]. It's a section of code that takes parameters and can execute those parameters. Yeah, that's a function. And that's how Matz talks about them. He designed blocks to be anonymous functions in the Ruby language.

But, again, they have special scoping rules. These anonymous functions have special scoping rules such that their return semantics will return from the surrounding explicit function. So, if you have a function with this anonymous function inside, the anonymous function will return from the wrapping function rather than from itself if you have an explicit return statement. That allows you to not have to worry about defining it as a..., and this is a fundamental difference between Ruby blocks and anonymous functions in other languages.

You can return from a Ruby block and return from the enclosing function rather than just returning from itself and then having to figure out what to do. It allows you to build lots of these little lightweight functions throughout your code and not have to worry about handling the return values and then passing them up and then handling a return value and passing them up. Because they'll do just kind of what you expect. Again, Ruby is about trying to make things friendly. It pretty much does what you expect.

It also means that these anonymous functions are used ubiquitously within Ruby to the point that Ruby almost never uses looping constructs. I say almost never, occasionally, you'll see a loop. Maybe you'll see a while loop that runs forever in some sort of, like, web service listener where something really should run forever. So, infinite loops are actually more common in Ruby than non-infinite loops if it's done explicitly. Because, in most cases, when you have something that can be enumerated over, that is you can step through a thing, you'll just pass an anonymous function to it. You'll pass one of these Ruby blocks. Give a block to it.

And instead of having all of the bug-prone, hard-to-understand syntax issues that you get around for loops, or while loops, and maintaining a loop counter, all that just goes away because Ruby is built in containers like arrays, and what's called a lot of different things in a lot of different languages: an associative array, or a dictionary, or a map. Ruby calls it hash. Those are all the same thing. Ruby just happens to call them hashes. I'm talking about kind of the implementation behind it. So, an array, a hash, or a dictionary, whatever you want to call it, and those are, of course, the primary ones.

But there's some other subtypes of those like sets. You can enumerate over those by just passing an anonymous function to it. There is an array in each method. And there is an integer or a times method. You can do three dot times, pass it a block, and it'll run that block three times. It's a revelation for those of you who [inaudible 26:24] in other languages before you came to Ruby [laughs]. It's like, what? I can do that? [laughs] Yes, you can. Yes, you can.

Like I said, this is the most Ruby-ish thing that you can do in Ruby is you pass these anonymous functions to anything. And because of the nice scoping rules and these are a function, you can do some really nice setup and tear down. So, if, for example, you wanted to set up a connection to some remote service, do something, and then tear down that connection, well, that's great because you can have that in the function, right? You can build that into a function that will do all the setup and tear down and then just run the function that they passed in, in between.

It allows you to really wrap any piece of code in some setup and tear down and execute that code inside of it. Of course, you can do that in different contexts as well, but being able to pass the function in is just really convenient. In other languages, you do it all the time. If you look at JavaScript, it uses functions, anonymous functions everywhere. But it doesn't have the advantage of the friendly return context that Ruby has where you have to do lots of kind of weird binding sometimes in JavaScript to get the right returning values and get it to return the right thing [laughs] from the right place, where Ruby just kind of does what you'd expect, which is really convenient.

Anybody who's listening to this and you're not looking at the code, you're like, "Huh, well, what do I make of this?" Well, go look at some Ruby code [laughs]. And those of you who've been Rubyists for a little while, this may be the most; for me, it was really illuminating. Well, people are telling me about these blocks. This is weird syntax. What is this? Well, it's just an anonymous function. It's an anonymous function with special return semantics. And that allows you to just call this section of code, hand off this section of code to another section of code.

And it's really, really useful to be able to hand a section code to another section of code. That idea comes from other languages. Of course, it's not unique to Ruby. These are inspired some, again, by Lisp and macros and by...anonymous function [inaudible 28:19] other languages, but Ruby really leans into it. It means a for loop will almost never be found. I can't remember the last time I saw a for loop in Ruby. They just don't use them because you don't need them.

In fact, I can't really think of the last time I saw much of an explicit looping structure at all because you think about it functionally. You call map. You call reduce. When you think about your code, it's a series of change and transformations, much as the functional language people do. And I think it's a very effective and less error-prone way to write code.

DOM: You're talking about, like, enumerables and being able to iterate through things. And I actually remember, Mike, it was when you first interviewed me, like, two summers ago. You blew my mind. You were like, "You will never ever see a for loop in any of our codebase, like, at all whatsoever." And I was like, that's not physically possible. Everything I've ever done in my entire –-

MIKE: [laughs]

DOM: Software engineering career has included a for loop. It was awesome to see that you can use these block statements, and they're just so powerful. There's so much you can do to just information while you're running with them. And coming from a language like Java, it was a happy surprise. I was super stoked that I could do dot each and dot map and not have to worry about writing for int i, i is less than counter, i plus plus, you know, all that stuff.

MIKE: And was I right? Have you encountered any for loops in our code?

DOM: No, no. I have not.

MIKE: [laughs]

DOM: And I have adapted the map mentality, never using each ever again.

MIKE: Yeah. --

EDDY: That is an interesting observation. I've never actually noticed that we didn't use [inaudible 29:56] [laughs] in our codebase. I actually wanted to fact-check that really quick. And I went through my IDE, and I wanted to make sure I did global search before. Well, it did pull up some results, but it was just comments [laughter]. Nothing explicitly calling, like, for action on something, which is a really interesting observation I haven't noticed.

MIKE: It makes a big deal into the way you write your code. One thing that has happened in the evolution of programming languages for years is that we try to hand more and more off to the language instead of doing something yourself. We [inaudible 30:31] compilers to figure out the machine language so that we don't have to write the zeros and ones [chuckles] because we want to think about it at a higher level. And we don't use assembly language much anymore in most contexts unless you're maybe writing some sort of embedded software, writing device drivers, or something.

You write code that thinks at a higher level and then compiles down to that assembly language. Because, honestly, a compiler does a better job of thinking about problems than you do. Because there's been generations of smart people who've been improving those compilers to think about how to solve problems. And in almost all cases, they're going to solve the problem better than you can. And, likewise, now we've got interpreted languages. And there's a range of popular interpreted languages today: Python, JavaScript, Ruby, for example.

And if you let the language do the work, you're going to have fewer bugs, and your code is probably going to perform better. If you're writing the loop yourself, you might do it wrong. If you let the language do it, the language is going to get it right. Let the language do it. If there's one thing you take away from this, let the language do the work. If you're doing it yourself, you're doing it the wrong way. The people who designed the tool...if you think you can do it better, you're probably not right.

There's a lot of people who've been thinking about how to solve this problem within the language you're using, whatever that language is, and the language will probably do it better than you can because it's been designed to. It's been designed to. We shouldn't do the looping. We should let the language do the looping. This is a very functional way to think about things [chuckles]. Functional languages very much lean into this. You shouldn't be doing the looping yourself; let the language do it. Because it lets you think about what the problem is, rather than how you're going to solve the problem.

Well, here's the problem; I want to go through each of these things. Well, let the language go through each of the things. Don't do it yourself. As Dom was saying, use map [laughs], you know, tell the language to return a value from each one of these things that you can enumerate over. Don't do each where you're going to explicitly go through and figure what we're doing for each one. Usually, what you want is to transform a set of things into another set of things. And thinking about the code in terms of that transformation is transformational in the way you think about the problem.

EDDY: I do want to add more to sort of, like, the scope of what Ruby can be used for. When I first started, I initially thought, oh yeah, Ruby, you can do it for web development. And that's what is its intention, and that's what its functionality is for. We did a Skill Clinic project a few months back, going a little bit over a year, where we wrote a service purely on Ruby, right? To go ahead and do some of our assignments, you know, for pull requests.

And that really kind of dawned on me, right? Like, Ruby is a lot more dynamic than just web development, right? I mean, granted, you can do web development, like, but it can do, like, web servers, like, data processing, scraping, et cetera. So, it's [chuckles] much more broad than just web development. And I think that's something, for me anyways, that was a little bit of an epiphany when I realized just how dynamic it can be.

MIKE: Yeah, and it's used a lot as a shell scripting language like Perl. We've been talking a lot about web development because, again, that Rails framework. But there's a lot of shell scripting that goes on in Ruby as well. And some popular DevOps frameworks are written in Ruby; kind of think of it as the new Perl [chuckles]. Perl is still around, by the way. And it's an interesting language, if anybody's curious; not as popular as it once was, but still an interesting language. So, we've done kind of a whirlwind tour here.

SERGIO: Yeah, I just wondering why Ruby the popularity has been declining by the years, for example, in comparison with Python [laughs]. I don't know why. Because all the people say that it's because of its slowness, but no, I don't think so. Because many of the company has been using Ruby for a long time. So yeah, I don't know why.

MIKE: Yeah. No, honestly, I think Ruby sometimes outperforms Python, but they are kind of sibling languages. They're languages that fill a very similar role. Python happened to catch on within the machine learning community, which is, like, rocket fuel in the last few years [laughs]. And, really, I think that's it. Python happened to catch on really well within the machine-learning community, which has caused it to explode in popularity. And JavaScript is another interpreted language that's simpler than either Ruby or Python, and yeah, that's got pros and cons, right? [chuckles]

SERGIO: [inaudible 34:50]

MIKE: Simple is good in some ways and not as capable in other ways. But, JavaScript, you have to learn to do web development. So, everybody who has written any front-end code has to learn JavaScript.

So, when JavaScript became available on the server side, a lot of people said, "Well, why should I learn more than one language? I'll just go with one language." So, JavaScript, in some ways, has become...has filled a lot of a similar role as well. So, I don't know that it's so much that Ruby has failed anyway. It continues to be a popular language. But there are other languages that fill in the same niche, you know, they kind of do the same thing that are popular for other reasons. And that's great. Again, I'm not criticizing JavaScript or Python. I think that they're both very useful within their areas as well.

EDDY: I feel like there is a bit of a stigma behind scalability with Ruby, probably with Ruby on Rails as a whole. But I think the reason to why a lot of us get the impression, well, I'm speaking for myself, is that a huge factor to that was when Twitter decided, hey, it is not scalable. Let's switch away from Ruby on Rails and use a different framework, right? So, for me, that sort of just keeps ringing, right? I'm like, huh, yeah, no, maybe it's good for a quick startup, you know, but not necessarily scalable. And I've realized that that's not true [laughs].

MIKE: Well, I've read about this, I read a really interesting article about this many years ago, so I couldn't tell you where it is, about Twitter specifically. Twitter was originally using MySQL or MySQL, or whatever you want to call it, the database as a router for messages. And that didn't scale. And that's not speaking anything wrong about the database or about the engineers who built the application. It was a good way to do things initially, but that didn't scale as they grew because it wasn't the purpose of the database. The database is not intended to be like a telephony switch. It's not a telecommunications tool. And at scale, because that's not what it's designed for, the intense levels of reads and writes just didn't work.

And so, they decided to build their own layer to handle [inaudible 36:48] messaging and all the kinds of caching that go on top of it. And to do that, they did want to have something that was high-performing. And it made sense not to write that in Ruby, right? To use that using a very high-performing language. I believe they did it in Scala, didn't they? Scala, Scala, however, you pronounce it. And which was a kind of a preferred tool of the developer who did it.

And I don't object to any of those decisions. But none of that has anything to do with the scalability of Ruby at all, right? Ruby worked great for handling the web front end. But I wouldn't want to use Ruby to do something, you know, some high-performance computing. I'm not going to use Ruby to program a supercomputer because that's not what it's designed for.

You probably do want once you reach the kind of scale that formerly Twitter, now X, was [inaudible 37:33]. You're going to have to optimize certain parts of your stack. That is advisable regardless of the language that you're using. So, I think we had a lot of those claims. There was kind of some talk around that at the time that Twitter [inaudible 37:48] that I think was just really misleading.

And [laughs] if it didn't work, then why are big companies like Shopify and GitHub still using Ruby? Obviously, it works for large companies. That's not really where the concern was, but rather, they just had specific business needs. And really, yeah, they shouldn't be using Ruby for what those specific business needs were or really any language x, right? [laughs] Use the right tool for the job. Whether that'd have been Java, or JavaScript, or Python, anybody who reached that scale would probably have changed languages for that portion of their code, and rightly so.

In fact, the machine learning aspects, like the deep, nitty-gritty stuff that goes on in Python, isn't written in Python either. It's written in some variant of C, C++. The lower-level tools are not written in Python. But just like in Ruby, you can have extensions in other languages. Python does the same thing.

If I can go back to where I was at, we've been through this whirlwind tour [laughs] of talking about this language. And, of course, this is a podcast. You're listening to it. You can't see the code. I hope that if you haven't done Ruby, it's given you a taste of what Ruby does and what it's about, and, hopefully, some of why it might be really friendly to developers, why your developer happiness might be increased using that language.

You can think about things functionally. You don't have to do a lot of things that you would do in other languages, like working around the limitations of integers, of primitives, or having to do all the looping yourself. You can really think about problems in a way that maps well to natural language because it's designed to think more like humans do.

I love Ruby. I have done Ruby now for a long time, close to 20 years. And I've loved it. Again, there's no perfect tool. But I have been very grateful. Matz, if you ever happen to listen to this podcast, thank you. Thank you for your active love toward us in the development community.

EDDY: You know, I actually wanted to retort a bit earlier in the podcast and say, oh, yeah, it's developer happiness, and that's true. Until you have a nasty bug that you can't find for the whole day [laughter].

SERGIO: But you can find the same issue in whatever language, you know. So, it's in the language the issue.

MIKE: Yeah. And there are people who've complained about Ruby because it makes some things too easy, some of that magic [laughs].

SERGIO: Yeah, yeah, I heard that before.

MIKE: That you can't find anywhere [laughs]. It's really hard to find because it doesn't exist. So, there are some things that are absolutely harder to find because of that, and we've got to deal with that. So, there's a mindset issue here [chuckles] that you need to learn to think about problems in a different way, and that requires a different set of tools. It's a good call out. Thank you.

I hope that if you're curious, you do go give Ruby a chance. It's a great language. And if not, if Ruby isn't your language, that you've learned some things, to think about problems a little bit differently, and you can use some of the strengths of Ruby in whatever language you are writing. With that, until next time on the Acima Development podcast.