A book club for developers.
BookBytes is a book club podcast for developers. Each episode the hosts discuss part of a book they've been reading. And they also chat with authors about their books. The books are about development, design, ethics, history, and soft skills. Sometimes there are tangents (also known as footnotes).
(Intro music: Electro swing)
Hello and welcome to BookBytes. This week, it is just Jason and I. We are going over “Seven Languages in Seven Weeks”. This week, we’re going to talk about Ruby and maybe a little introduction to the book, as well.
So, this is one that I’ve wanted to do since we started the podcast. I think you might have mentioned it, or maybe I did, I don’t know, but this book has always intrigued me.
I think I’ve mentioned it in Discord, probably every time that we’ve had a gap, of, “Let’s do this!” because we have a topic every week that is timebound and well defined as to what to look at. So, glad we’re finally starting it.
Okay. Do you have anything to add from the introduction that you’d like to talk about?
Um, I guess, I did like some of the things called out in the introduction, like how the language choice was done because there are so many languages.
That’s kind of my reason for even wanting to look at the book, it’s putting me in a place where I’m working with languages that I have less familiarity with.
Yeah, yeah. I thought it was really interesting that he wanted to pick out different languages that explore all sorts of different programming models. So he wanted languages with different typing models, different programming models, how you interact with it, is it compiled or interpreted? Does it have an interactive shell? Different design construction, core data structures… And then just languages that have unique features.
But it’s not going to be able to teach you all seven languages in one book; it’s going to skip over some of the basics and it’s going to dive deep into certain areas and then not into certain areas, and I think that’s really interesting.
Yeah, I think so, too. Something to at least spur your interest in taking a look at a language and have you in a mindset of the way that you do things is not necessarily always going to be the way that we do things as an industry.
He brings up the paradigm shift in the industry of things like the big movement towards object oriented programming and I was definitely not around when that transition happened, but you can even see it today where there’s such a big push on the functional front of things and how, I don’t know, just things that we know and we kind of rely on, could get flipped on us pretty quick in the industry. And so-
Having an awareness of what’s out there is a good thing to have.
And I always think learning a new language is uncomfortable. It can be fun, the beginning stages are fun, and I think in this book we are going to see a lot of the beginning stages that are fun, but once you get past that initial step of starting to learn a language and you really try to become fluent in it, it’s uncomfortable.
And I want to be continually learning new languages and not just be good at a certain language, but be good at learning languages.
And with that, too, you definitely have to be willing to set down the things that you know and are comfortable with in the language that you use most regularly, to say, “No, this is a different paradigm and not everything has to work like what I know.”
But one of the things it does mention in the intro is that, “Hey, maybe there’s something that you learned in a certain language and you can take some of those ideas to a different language.”
Definitely, I would agree with that. Having been exposed to different languages in the past, they all have one level of influence or another in the way that I write today. So there’s definitely influence and there can be some crossover, but it is also sometimes obvious when a language comes- or when a developer comes from a specific background and moves to another language, sometimes.
Right. Right. Okay. Well let’s move onto Ruby then. Oh wait, sorry. I should mention the languages that are in this book.
So there’s Ruby, Io, Prolog, Scala, Erlang, Clojure, and Haskell. And so looking at this list, I was like, “I’m not familiar with anything except for Ruby, that’s pretty popular. I’ve also heard Scala is pretty cool, and I’ve heard of Clojure and Haskell.”
Clo-jure? I don’t even know how to pronounce it!
And Haskell. But the two that really stuck out for me were Io, I’d never heard of, and Prolog? Maybe I’ve heard of that?
For me, I have actual production experience in Ruby which is the one that I’m most familiar with. I had never heard of Io. Prolog always seemed very out there and I’ve never spent any time with it. Scala I’ve tinkered with, Clojure I’ve tinkered with, and Haskell I’ve tinkered with.
And I think that’s all of them? Maybe I missed one, but yeah, Ruby definitely is the most familiar one for me. Ruby is a very dynamically typed language. I guess in order to describe dynamically typed, I’m probably going to botch it and get it opposite of what it is, but the types of things are…
So the types of things aren’t checked until runtime. I mean, it is strong in that it won’t do coercion for you. Like, if you try and add something like a string and a number, the computer will yell at you, “Cannot compute.” Unless you teach it which, I mean, inevitably somebody has made somebody more capable of handling weird cases like that because the flip side of Ruby is that it is very open and extensible.
So if you want to make big changes to the language and the way that it works, because its objects all the way down and classes are open, you can extend anywhere; and I like that within the book it refers to that as a sharp scalpel.
Yeah. It gives you the rope to hang yourself with.
(laughs) Yeah. So, from my experience with it, I actually wrote Ruby for about four years, about four years ago.
So it’s been a little while since I actually have written any Ruby, but I was doing primarily web dev, but I was not doing Rails. I was a, I don’t know, a Rails holdout. It never quite worked the way that I wanted it to, or I never got comfortable with that.
So I actually used Sinatra and SQL rather than Rails and Active Record for doing things.
But, yeah. I did that and I definitely think that it held up well for doing the product we were doing. Like, we didn’t have major performance considerations with what we were working on and instead, kind of like the book talks about, that timed market was a big, big factor in that. In just getting something put together because it was a small, scrappy startup. It worked excellently for that; for building something out and then iterating on it quickly.
What about you, Adam?
And then the only other one I have some experience with is Scala. About seven years ago I went through a little bit of a course on Scala. I think it was on Coursera and it was taught by the creator of Scala. Then it was just-
Oh yeah, Martin Ordersky, of course.
It was very difficult for me at the time and I thought it was very interesting, I was just not ready for the functional programming paradigm. So yeah, I mean, I have a little production experience with Ruby but I never really sat down and learned the syntax.
That’s interesting having just... had you jump kind of straight into it, I guess that could be the contract world, right?
Yeah, and I was doing some pair programming, trying to just jump into the deep end and keep my head above water, but it was difficult.
What would you say was the most difficult thing when approaching it?
Well, the code base itself was pretty big and so I wouldn’t know where to go for certain things. There were views… there were views that were written in all sorts of different types of languages. So I think there were some views written in YAML, but then I think there was another one that was similar to YAML, but not quite? So it wasn’t exactly HTML, and then there were just like-
Files… different files connected and you kind of had to follow the path but there was no, like, no explicit imports. So, I think Ruby does some sort of file resolution thing where it’s going to look in the current folder and if it doesn’t find it there then it looks in the parent, and then if it doesn’t find it there…
And then I think Rails adds some stuff on top of that where it looks in certain common places for certain types of files, for routes and views and things, and I just didn’t know where anything was because I didn’t know any of the conventions.
Yeah, I know that that was a real key part of the Rails learning process that I didn’t spend a ton of time or get super familiar with. I know that it was really big on organizing things like your models, your views, and your controllers; because Rails was huge on the MVC realm.
And I also believe that one of the things that Rails had, was that it used Bundler, which was the Ruby package manager. I guess Ruby Gems is the underlying thing, but Bundler is what everybody uses in order to do it because Gems was just like a global install type of thing and Bundler actually let you create a file that listed out your dependencies.
And one feature that Bundler had was the ability to go and require all of your gems in, right at the start of the application which was nice, or convenient, for not having to go and require everything. So all of your dependencies would just be loaded and available because Ruby just works with a global namespace where, like, at the base of it all there is the kernel object that has everything on it like when you go and, like, you can go and define stuff on there and hope that your things don’t conflict with each other.
But it is true, like, not having explicit imports? That was probably the thing that challenged me the most sometimes with Ruby when it came to debugging, it was figuring out where the specific behavior had come from.
Yeah, and I think we’ll get into more later, but you can do meta programming with Ruby and so you may literally not be able to find the place where the code is being run by searching around in your code.
Because it may not exist as a naming method or something, yeah.
Right, it may not be a named method, it’s like generated.
So, I mean, Day One, it talked a lot about just going and getting set up.
Oh yeah! So, I thought I was way behind going through this first week because I had, like, three days left and I was like, “I haven’t started!” And then it turns out there’s only three days.
Yeah, I think that’s great. While, I mean, there’s definitely take home work, or do it yourself work, the commitment on that front, like, three days, I think is not enough to learn the language, but to get exposure, for sure.
Yep, and I mean, it’s 34 pages. So you’re doing, like, 10 pages a day, it’s pretty nice; and then the exercises. So, total-
So total, I spent 2 hours and 45 minutes reading, and 2 hours and 45 minutes doing the exercises. So it’s not bad. I thought it was going to be a huge commitment to go through an entire week of a language and then an entire week of another language, but yeah. So Day One you kind of get set up and learn some basics, like, “Hey, arithmetic works as you would expect.” But then there’s other things like, “You can do dot methods... on anything! And find out what methods you can call on it, that’s awesome!”
Yeah. It is definitely a useful thing when going and debugging something or inspecting it to see, like, what can you do, or what can you do with it?
Yeah. I also thought it was really cool that single quotes versus double quotes were different. The double quoted string gets evaluated so you can have string interpolation; but then I noticed, like I noticed with examples throughout the book, sometimes they’ll just use single- they’ll just use double quoted even though they don’t need it to be evaluated. So I’m not sure what the convention is.
I don’t know for sure. I think back in the day it used to be harder on it of being consistent on use single quotes if I'm not interpolating and then use double if I am, but I think they did some measuring on it. I remember looking at-
Old, old blog posts that said it really didn’t matter, and so there’s not necessarily performance overhead that you’re going to bump into. So maybe you could just go with double unless you need them? I don’t know on the hard set of rules and it doesn’t seem like they stuck to it either. Maybe that’s just the Ruby-ism of-
Like, just express how you feel (laughs) and Ruby will do the rest. Like, you aren’t worried about top-notch performance, but instead, having a good developer experience.
Yeah, so that’s the other thing it talks about is how Ruby, it compares it to Mary Poppins. It says, first off, Mary Poppins is a great nanny, but secondly, she’s fun! And Ruby is supposed to be able to get things done but be really fun and put the focus on developer happiness and productivity.
And I learned about this concept that Ruby and Ruby on Rails is supposed to be fun several years ago. Let’s see, five-six years ago? And I thought I would end up being a Ruby on Rails developer because that sounded really cool! And it didn’t turn out that way, but if I had gone to the backend I definitely would have wanted to use Ruby.
That was something that actually brought me into Ruby. Before I started a job with it, I had started going to Ruby Meet-Ups for quite a while and just seeing how passionate and excited people were about writing Ruby code. Like, I don’t know if I’ve been part of groups that are quite that thrilled. I mean, don’t get me wrong, there are definitely groups that are making amazing things, but there was so much, like, Ruby-love related stuff. Like, it was all hearts, and kittens, and “We’re so glad to be writing Ruby!”-stuff that it was just really a feel-good community to be a part of. So I think that the language and the community definitely came together on that front.
Yeah, yeah. So you were talking about dynamic typing, it also mentions that it uses duck typing which is it...
Yeah. So there’s no hard interfaces that exist. So when you go and define a method, you don’t say what it is that’s getting passed in. It’s just based on usage of whether or not the thing works. So if you have a method that’s, uh, I don’t know, is called…
2S? Like, 2 strings?
Yeah, 2S, sure. If it’s got 2S on it, it will just call it on whatever it is and not really care what the underlying type is.
So you could have an array of lots of different types within that array and then map over it and call 2S on everything in it, and as long as each of those objects has their own 2S method it will work.
So, yeah. If it walks like a duck…
...and quacks like a duck, it’s a duck!
I definitely like some of the things within it, too, that they give for convenience of, like, say you wanted to go and perform something ten times-
Being able to literally write 10.times and then pass it a block of what you want it to do, that is really nice versus a-
Yeah, and then after 10.times you can just have a block. So, a block is not really a thing I was familiar with that is just a piece of code. It’s not a function, it’s just a piece of code and you can pass it around or you can use it in different ways. So if you do 10.times and you have a block of code you’re just saying do this block of code this many times.
Right. Yeah, there are... let’s see... there are blocks and procs and lambdas, I haven’t spent enough time looking at it in a while.
Blocks, and procs, and lambdas?
Oh, my. (laughs)
(laughs) Oh, my. Yes. And I think what a major difference is, is that a lambda is very much like a function that can get passed around and you kind of write it the same. I mean, you write it the same way, you can even write the word, “lambda”. It’s a keyword within Ruby.
But a block is special in that it can, like, force the outside to return. Like, if that makes sense? So if you’re doing 10.times and you’re iterating over that, if you were to go and do a return there-
Then you can go and make the outer function return, if that makes sense?
So then times would actually return something.
So not the times itself, but the- So, if you had a function that was called “do something ten times” and you did 10.times and inside the block you returned on the fifth iteration, for some reason, then you could return from that block and it causes the outer function to return.
Wow. So it would actually break out of anything after that point in the function? Okay.
Right. Yeah. So that’s kind of the distinguishing part if I remember right, and maybe we’ll have to go and add some errata later where I was wrong on this, but I’m pretty sure that that’s part of it because otherwise, if you needed to do, like, early return then you would have to go back to a more traditional for loop or something.
Yeah, and blocks are just surrounded with quotes, or curly braces, unless you want maybe multiple lines, you could start off with “do” and “end”. And I must still have some vim plugin installed from my days of working at Ruby because it auto completes the word “end” for me, and it actually feels really nice to type “do” and then hit enter and then “end” is just there. Or if you’re doing a function, so day 2 gets into functions, and you do def and the name of the function, hit enter, and it puts the word “end” on the end. And I really didn’t think I would like that; using words instead of curly braces, but it’s not bad at all. It’s kind of fun.
Mm-hmm (affirmative). Yeah, you definitely adjust to it. It also spares you, sometimes, the ambiguous syntax that you can wind up with when using the curly braces.
Yeah, ‘cause curly braces can be used for so many things.
Mm-hmm (affirmative). Yeah, they can be used for blocks, but then, and this is something that I think I bumped into, was passing a hash in, the hash being just like a key value lookup, passing that in but the literal syntax is using the squiggly brackets, or curly braces, and-
It was taking that as a block.
Interesting, I didn’t have that problem with that challenge.
Yeah. And so, yeah. If you try and pass it in, unless you use parentheses around it.
Oh, yeah! So that’s the other thing, so in Ruby the parentheses are optional a lot of times.
If you’re invoking a function, you just have the name, space, and what you’re passing in. But what you’re saying is that since the hash that you were trying to pass in was surrounded in curly braces, you had these parentheses?
Yeah, I didn’t have that problem ‘cause I just... I wasn’t thinking like a Ruby developer and leaving off parentheses.
Yeah, it’s kind of nice in that it cuts down on some of the syntax.
And I remember that being a nice part of being able to write tests, that you could avoid a lot of curly braces in cases, and so, I don’t know, you can write more, like, just human readable stuff.
Even just things like “puts”, putting that in front of stuff.
Like, if you want to do it to see it and not having to go and unwrap things. So there’s some nice convenience there but occasionally you can bump into the syntax.
Yeah, so I noticed that “puts” will print out stuff to the screen with a new line-
And if you don’t want the new line, then you can use “print.”
So in Day Two, it also says arrays are Ruby’s workhorse ordered collection, so you can do lots of different interesting things with them. You can do a negative index to count from the end and then it has methods like push and pop.
Yeah. So you can use their arrays like a number of different data sources. So, you can… yeah, if you’re using push and pop then you get stack-like behavior and you can… And then there’s also the shovel operator, as well.
Yes. So, (laughs) that is less than less than.
Oh! Okay, I saw this in one of the examples, I think, and I wasn’t sure what that was.
Yes, so that is to go and put something into it that-
Oh, okay. Nice. I thought it was some sort of assignment operator.
So, I mean, yeah. I guess it doesn’t assign… it jjust modifies it.
And it’s also, it’s something you can do to arrays, it’s also something that you can do to strings, as well, because strings in Ruby-
Oh, does it do an incatination?
Well, it actually modifies the string. So a string in Ruby is actually mutable. So-
Yeah. You can tell it to freeze, like, I think it’s just string.freeze in order to go and freeze one.
But, yeah. Strings in Ruby are mutable. So rather than having to bust out some sort of string builder or pushing a whole bunch of things into an array and calling join or something like that, in Ruby’s case, yeah, a string is a mutable thing.
Yeah. What else I thought was cool was ranges. So you can do square brackets and some number, dot, dot, another number and you can actually access an array using a range. So you can do animals, and then say zero, dot, dot, one and you’ll get a new array with the first and second item. First through second item, I should say.
Right, and if you want it to be exclusive and not include that upper bound, you can use three dots.
Oh, right. Yeah.
That was something that I had to pull out of memory, as well. So two dots, inclusive. Three dots, exclusive. ‘Cause they had one-
That’s incredibly concise!
And I can imagine it tripping me up.
Because it’s just an extra dot.
And then you have an off by one error, and that’d be tough.
(laughs) Like, why do an extra dot when you can just make the second number one less? But I could see why, if the second number’s a variable, you don’t want to subtract one from the variable and just add an extra dot. I could see it.
Yeah. Yeah, I don’t know why I opted for it. There was the one exercise where it said it handles the contents of 16 numbers. I think that was it. So it wanted you to slice an array of 16 numbers into four slices of four numbers and with that, I wound up making a range of 0-16 and then sliced that in chunks of four, or did each slice of four chunks. So the 0-16, I don’t know, it just made since versus making 0-15. Like…
Yeah, I probably took too much code to do that one. I did array.each and then inside of there, I did a modulus on four.
And so, if I modulus four is zero, then I would use a “puts”; and else, I would use a “print” because it just wanted you to print, you know, print out four on the same line and then print out the next four on the next line. Yeah, so it would basically just, “Keep printing it, when you get to the fourth one, do a “puts” so you have a new line.” (laughs)
Interesting. That’s something I actually want to see afterwards, Adam, is what your code looks like and compare it to my exercises, just to see.
Yeah, and some of them for Day One, I did it one way, and then after reading more, I rewrote it a different way. I would say, “In Day Two, I learned you could actually do it this way which is a lot better.”
Do you have a specific example?
Yeah, just the first one. Well, the third one on Day One says print your name ten times, and so the first time I just did a while loop.
And then after I went through Day Two I did three dot times.
In the block, it just says puts Adam. So, that’s just a simple example.
But there’s another one where you needed to print the string “This is sentence number one” and then change it where it is “...sentence number two”, “...number three”, all the way to ten.
The first time I used a while loop, and then the second time I did a range from from one to ten dot step one. And then-
I’m using string interpolation to just change the number on the end.
So learning about ranges and steps helped. Step is really interesting though because you tell it what you want to count by.
I guess I hadn’t even thought about using a step, but…
What did you do on that one? On... what did you do on this is sentence number one through ten?
So for the… just doing the range? I did a 1-10, like a range of 1-10 and I called .each on it.
That’s probably better ‘cause I’m going by one. I’m going by one, so you don’t really need step one. But yeah, I think that’s part of Ruby. There's so many ways to do it. Like, whatever makes sense to you, you should be able to do it that way. Even down to when you go into the Ruby REPL which is like an interactive way to work with it. REPL is, like, read, evaluate, print, and loop. So you can type in some code, see what it evaluates to. Type some more code and see it.
But when you’re in there, you can get out of it either with quit or exit. And they could have just picked one and then when you tried to use the other one, just, “Hey, unknown error.” Or it might have said, “Hey, did you mean exit?” But instead they’re like, “It’s fine! Whatever you want to use, we know what you mean. So we’re going to give you multiple options.”
That makes me think of Ruby gem that used to exist - or probably still exists - it’s basically like, “did you mean…?” And it goes it abuses, or method missing-
To the extreme, to where every object is extended to if you call a method on it and it happens to be close, then… if it happens to be close text-wise then, or like within a certain hamming distance, then it’ll say, “You probably meant this.” And it will just call it.
(laughs) It will just call it? Silently?
Yeah. Yeah. So it was definitely, like, a joke gem, but if you think about socket.receive or something.
Ooh. I mean, if it, like, threw an error that gave you some helpful information I would probably use that, but…
(laughs) Yeah. But, to just flat out go and call it? It's definitely a joke package, but you do think about it though. Like, socket.receive, I can’t tell you the number of times I’ve written the word receive for some method or function and botched spelling “receive”.
The e and the i? Yeah.
Yeah. And I mean, it is powerful enough that it could just work because it’s close enough.
I don’t like it, though, you know?
(laughs) I know.
You’re searching through your code base for receive and you’re not going to find it because it’s misspelled, but it still works.
It’s true. (laughs)
(laughs) Yeah, so then it talks about hashes which is pretty interesting.
Kind of like an array but you can give it a key value pair. It also talks about using symbols which are kind of like strings, but you just do, instead of surrounding it with quotes, you do a colon and some characters. That was really cool because then it talks about how, like, when you use a symbol, it’s always the same symbol. When you use a string with the same characters, it’s not the same stream and it, in fact, has an ID that you can see. So you can do .objectID and you can see that it has a different ID for different strings. But if you do the same thing on a symbol you’ll get the exact same ID.
And that was just interesting to me, that it exposes an ID for objects. And I was curious if that gets used in production code or if it’s…
Checking the object ID?
I… I don’t know a specific case off hand, but like, if you want to assert that two things are exactly the same thing, and-
That they’re not just equal, but the actual same reference, object ID would get you that.
Yeah, so I guess it might be used under the hood for some assertion libraries.
Yeah. And I mean, I guess knowing that strings are mutable also makes more sense of why symbols exist; because symbols are not mutable.
Yeah. And then it talks about how Ruby does not have named parameters but then you can use symbols as a way of emulating named parameters by just, like, “pass in an object hash” and then inside the function you can access the object and then the key that you try to access is some symbol.
So, that is actually something that has changed in Ruby since the book was written.
Yes. So there are keyword arguments.
So, uh, y- (laughs)
Yeah, I noticed it’s using, like, 1.9 or something? And I was on 2.something.
Yeah. I know that for a long time Ruby 1.87 was the long-lived version because Ruby 1.9 made some big changes, but also came with some big performance improvements. Then in later versions of Ruby, they added things like keyword arguments. They also added, I think in Ruby, they added a new syntax for Lambda that was like an arrow with parentheses. Like, it was-
Like, rather than writing out the word “lambda” you got to be way more symbol heavy and yeah. So, they do have that now.
Was it like a dash and a greater than? Or like an equals and a greater than?
Uh, yes. So like a dash and then greater than and then parentheses for your arguments and then curly braces for your block.
Yeah. Super terse over writing out lambda.
Did you take on the trie exercise?
Yeah! I did. That was the, what was that, day 2?
Oh, I guess there were 2 Day Two thing. So… But one of them was making a trie that took a hash and converted it to a trie.
Yeah. Yeah, I did that. So it gave us some code that was a trie, but the way that you had to construct the trie was to pass in the name and the children. So if you wanted a trie that was more than just one thing with some children, your second argument had to be an array of more tries that you were creating; and so it was super verbose, and the challenge was: We should just be able to pass it in with a clean interface where you just type out a hash of the whole trie. It was a little bit challenging but actually easier than I thought. What about you?
Yeah. Yeah, I took it on and, like, any time that you have the word trie brought up, it’s time to bring out recursion, right?
And actually, I don’t know… I don’t know if you did this, but in my implementation, I allow you to use either syntax. So you can pass in the name and an array of tries you create yourself, or you can pass in a hash.
Nice! I made a separate function on the trie class. Like, a static function that was called “build”, so you could do trie.build and give it a hash.
Oh, okay. Yeah.
So instead of overloading the constructor.
Yep. Yeah, I just overloaded the constructor. Which, is the constructor always called “initialize” in Ruby?
Okay. Yeah, so when you pass in name to initialize, I check if name.instanceof, and I actually really love this in Ruby, if the method is returning a boolean, the convention is the name ends in a question mark. So instance of hash. So I find out if it’s hash, then I pass it to a different function to create it.
Mm-hmm (affirmative). That definitely seems like a more Ruby-ism. Just thinking about it now, or you describing that because it’s more of a “give me what you want and I’ll figure out what to do with it. Like, if you give me something reasonable, I’ll work with it.” So…
Nice. And it also asked about doing a grep. So I also took on that ‘cause… yep. At the end of Day Two, it says-
That one was a lot shorter than a trie.
Go and write a grep that will read in a file and go and find lines that match the pattern. Yeah. That was really short. I think it was about 10 lines. Like I said, I have a few line spacing things and like… well, it was 10 lines because I have error handling. If you don’t give a pattern to the command line-
Do you see that?
I actually forgot to (laughs) let you choose your own pattern. I’ve got a pattern hard coded in my code.
Yeah, that’s the starting point. (laughs)
‘Cause I intended to pass it in from the command line and I didn’t yet figure out how to get a command line argument.
Ah, so in order to do that, there is a constant that’s available-
ARGV, and then that is an array of all of your arguments and so…
Okay, yeah. So, I thought I did this, but I guess not.
Yeah, so doing ARGV sub zero was what I took and I used that pattern.
And then can you just surround ARGV zero with slashes to make it a regex?
Uh, I actually just did line.match.pattern so you can pass it to the regex constructor.
I think you can do interpolation in a regex. I’ll have to see that.
That’s right, I didn’t actually make it a regex so even my implementation fell short. But, um...
I believe… Yeah, so you cannot actually do interpolation inside a regex. So if you did slashes and then the interpolation syntax then yes, you could do that. Yeah.
Cool. Yeah in Day Two it also talks about mixins which is a pattern I’m not familiar with. I’ve heard about them in Sass, I think? Which is a CSS preprocessor.
But yeah, it was interesting. Instead of inheriting behaviors you can just include - Oh I’m going to do a terrible job of explaining this - you can just include a mixin, which is a module, and then that mixin may actually call functions from your class. So in order to use a mixin you may have to implement certain functions. So it, kind of, reminds me of an interface.
Like, I want to use this interface.
Okay. In order to use this interface you have to make certain methods.
But I think with Ruby, it’s not necessarily going to warn you or give you an error if you don’t do that.
Not, like, I wouldn’t think so. I would expect it to fail if you tried later. So like, if you go and… a really common one is the enumerable module. Like, going and including that.
So if you go and implement “each”, then you get all of those things that that array has, or at least a lot of them, where you can go and call map, and filter, and all the other things that enumerable provides.
Oh! That’s another one! They have “map”, but they also have “collect”, which is the same thing with a different name.
Mm-hmm (affirmative). Yeah, they had all of the “-ect” methods for-
consistency. So, like, they had “collect” and they had “select” if you wanted to filter out to a list of things.
Oh! Words that end in -ect!
And they had “reject”.
And, yeah, I don’t know if there were more of them, but yeah. I knew that they had two of them.
Or, like, two forms of a number of them. So, depending on where you're coming from.
I know one that would always catch me is there was “find” if you wanted to find a single item in a list, and then there was also “first” that was allowed, or that existed; and “first” is to get the first thing out of a list or out of an enumerable, right?
But something that is easy to screw up is you can call, say you have an array and you said “array.first” and then you gave it a block of some conditional, the block can get past any method even if the method doesn’t ask for it.
And then it would just get flat out ignored. So it would go and call, like, “array.first” and say I want to match whatever item has the name of alice and it would always just give back the first item and ignore the block entirely because the correct thing was “find”.
But you could always pass a block to whatever because Ruby doesn’t care.
(laughs) Yeah. Okay, so did you do the serious challenge on day three?
The serious challenge on day three? Yeah. Yeah, I did go and take it on.
So it involves doing meta programming. When I first heard about meta programming, I totally misunderstood it because it says meta programming means writing programs that write programs.
And that sounds like something completely different. It sounds like the program is going to create a text file and write out some code, but that’s not what it's doing. It’s just, while the code is running, there are classes or methods available, let’s just say methods. There are methods available that are not written in your code but you can call them and they’ll work. And I love the example of Roman Numerals.
Yeah. I like that one.
I’ve done Roman Numeral stuff before, converting from numbers to Roman Numerals and so forth, and all they do is make a class called Roman that defines method missing, and so then you can just call Roman.iv and iv is not a method on Roman, but hey, it has a method missing and it can take the name of the method that you tried to use and figure out what to do with it and return a number. So, that was pretty cool.
Yeah. It definitely is cool. It’s something you obviously have to be careful with but it can make for some really nice looking domain-specific languages or DSLs.
Yeah. So the challenge was to take this axis CSV module and, let’s see, and then create a new method on it called “each” that returns a row-
And that row will let you call the name of the field that you want to get. So even though in your code you don't know what fields are going to be in the csv file. You Can do then do, like if you if you’ve got a csv full of cities you can do, like, row.name and it will grab the name of that city on that row.
Yeah, or row.state or row.zipcode
I mean, I know rows can have more than one, but yeah, you can write it in really handy syntax like that.
Yeah. So I’ve got a line here at the bottom of my challenge that says “something.each” and it’s got a block and then just puts hey row.city is in row.country with a population of row.population.
Yeah, I did that same thing, as well. I mean, I guess I stuck with the kind of one and two examples of lions and tigers and I’ve got bears and sheep.
Okay, I thought the example was a little weird because the headers in the csv file were just one and two which doesn’t explain what kind of data is supposed to be in the file.