00:00:12.080
So, I brought a special little story this time. I love stories! But before we get into that, let's start a little bit with who exactly this madman is up in front of you speaking.
00:00:18.570
My name is Brandon Weaver, and you see, I started as an artist. I like to illustrate things—like that avatar up there in this entire talk.
00:00:27.270
It started when someone said, "You know, web design is a little bit more profitable; it'll get you a bit more reception." So I tried it. I enjoyed it; it was a good time. Maybe not the CSS part.
00:00:35.969
But then they said, "How about some JavaScript? That'll make you more effective!" Okay, so I added some JavaScript.
00:00:41.999
Then someone suggested, "How about a back end?" And it went very far downhill from there.
00:00:54.690
So far downhill, in fact, that I ended up becoming a frameworks engineer over at Square, where I'm currently working as a Ruby architect. But that's not why you're here; you're here for a story. I have a story today for everyone, so shall we get started?
00:01:12.810
Our story begins with young Red and his master Scarlet. You see, Red was studying diligently when his master came in and informed him that she was going to be leaving. "Now, Red, I’m going to be leaving. The Council 3.0 has called and I'll be gone for a bit, so be sure to study your hardest for the test because I'm going to have it as soon as I get back."
00:01:31.710
With that, Scarlet left, and Red made sure she had actually gone. He was a mischievous little lemur, and he had some very, very bad ideas. You see, my esteemed audience, in the castle of Master Scarlet lies secrets.
00:01:43.440
Forbidden corridors, libraries filled with knowledge unseen and untold for generations. Red was determined to find a few of those secrets.
00:01:56.970
So down he went, down into the depths of the castle where the candlelight faded into blackness and where all light seemed to vanish. There, at the very end, he found it—a massive door made of steel, locked tightly. The door he had often dreamt of opening.
00:02:10.560
A secret only whispered in the halls of the castle. Great and terrible knowledge lay beyond that door, perhaps even the secret to mastery.
00:02:24.069
With that power, Red could become a master, and studying would become a thing of the past. Tests would be a thing of the past. After all, masters don't need to study, do they? But the door did not open at his touch. This must have been a sign—divine providence.
00:02:49.569
So, Red entered, and in that hall, he found a vast library, the likes of which were unmatched in the land of lemurs, surpassing even the grandest city libraries. At the center, he saw it—the Book of Legends, a grimoire of infinite power and possibilities, a dark manuscript whispered in the histories of lemurs, rumored to contain wisdom beyond the capacity of a normal lemur.
00:03:13.750
But Red was no ordinary lemur, so this was absolutely fine. With the book in hand, knowledge would soon be his. He took a moment to savor his triumph and opened the book. Upon its pages, he found words he didn't quite understand, but then things started getting stranger.
00:03:40.180
The words seemed to blend together on the page, and everything faded. Something changed in the air; the room grew suffocating. The words on the page faded, disappearing into swirling fog, and an angry, red, hot fog crept in.
00:04:07.030
Then a new phrase appeared: "Welcome to the Ruby Grimoire!" And thank you for freeing me, young one." "Free? What does it mean, free?" Then another phrase appeared: "Behold the Dark Lord Crimson!" Red looked up, and standing there was a specter—a malignant being swirling in red fog. The Dark Lord Crimson was free!
00:04:43.550
The specter let out a scream—well, for a moment, at least. You see, I like fun stories, even if they are a bit horrific. So let's get back to the fun part. "Keep it down, keep it down! No need to be rude! I can't see a thing with that lamp. It's been a while since I had visitors down here.
00:05:09.440
Step back and stupefied horror a scrim—how long has it been since there was a lemur that actually bothered to open it? Welcome! Welcome, welcome! It's been so long, dear chronologist! At last, how exciting!
00:05:16.010
What lesson should we learn first? What stories should we attempt? So many possibilities! Indeed, tales and lands beyond, delving into deep, shelled languages, old and new.
00:05:24.140
Power beyond your wildest imagination is all written upon these pages. But I must ask, young one, are you willing to pay that cost?
00:05:30.200
Poor, poor Red. He was transfixed and started nodding vigorously. You see, there was knowledge here, beyond him—and knowledge, as he would learn, no matter the cost.
00:05:55.060
The true nature of the grimoire is that it is a journal of my journeys into lands beyond Ruby, where I met several wise ones, beyond anything I had ever seen before.
00:06:01.689
And if all the tales be good told, we shall start with three, and some of my personal favorites: the tales of the lemurs of Scala, of JavaScript, and of Haskell. Each fairy tale holds knowledge beyond what I'd imagined, so we will take a glance at each today.
00:06:20.090
From the lemurs of Scala, we shall first learn. Lemurs of Scala wear conical hats, spires to the heavens, cloaked in robes that change colors and styles.
00:06:37.150
Their programming is unique. Where Ruby has flexibility, Scala has even more. The lessons they bring us give insight into those flexibilities.
00:06:43.450
They teach us parts of closures, spell known as placeholder arguments, where an underscore can act as shorthand for arguments to a function.
00:06:57.190
Now, you might know this from Ruby, but what if we could do the same in Ruby? Before we can perform such tricks, we need to know a few little tricks.
00:07:05.000
Consider with me a function—a lambda—which takes an argument, a. It returns a function which takes an argument, b.
00:07:12.650
Why would someone do something like this? The outer function takes in a value, a. The nifty part about these functions is that when that function is returned taking an argument b, it remembers the value of a.
00:07:27.250
This is what we call a closure; it remembers the context where it was created. Now, why is this useful? Whenever we call add with one, it remembers that we've added one, and we can call add one right afterwards with the value of two to get back three, remembering the one from above.
00:08:05.180
So, why again is this useful? Let's say that we put that in a map expression using an ampersand, which is two proc. We can add one to every element of a list by this, or we could just inline this code directly.
00:08:23.100
But if we wanted to, we could even make it more succinct with square brackets being equivalent to call. But that's short and confusing; we'll prefer a longhand from now on.
00:08:35.899
How does a plus operator work in Ruby? Well, as it turns out, there's a secret there—it's no more than a method call. And we can define methods, and it looks something like this if you squint hard enough and pretend C code is Ruby, leaving out a few more details.
00:09:10.750
Red stared with a doubtful expression. "What is the lesson? Not an exact science?" Anyway, moving on.
00:09:20.270
Now, with these two tricks, we have enough to make our placeholders. We just need a little bit more Ruby magic to dance the fine dance. Remember our entity class? What if we made our own class that had a plus defined on it? We can call it P, our placeholder arguments.
00:09:46.910
Now, here's another fun trick: there's nothing that says you can't define plus on the singleton of a class. You might wonder why you'd want to do this because it allows you to do something that looks like this, and that works—that's very valid Ruby!
00:10:11.710
We can call plus directly on the class. If we do that, we can use a lesson on closures to perhaps return a function instead because there’s also no rule on what that needs to return.
00:10:38.990
You know, people who are studying get bad ideas. Yes, yes, great! Magnificent! I love bad ideas! This brings us to a very interesting feature of Ruby: I discovered that two proc applies after infix operators.
00:11:00.520
So we can do something like this, which applies to proc on the function that we just returned, allowing us to get something which looks very much like Scala, doesn't it?
00:11:26.400
If we're particularly naughty lemurs, we can always redefine underscore. Now, this can undoubtedly do bad things, but we wanted to prove a point, so we're going to do it anyway.
00:11:43.849
Now imagine we rewrite the rest of the possible operators—maybe we use method missing to allow it to use any other function, or perhaps respond to find out if it can even do that.
00:12:01.290
If we really wanted to, we could even make this into a stack builder and do something like underscore plus one double equals two, and we could add these operations and have them reduced onto a stack.
00:12:21.990
Imagine the possibilities! But that's a tale for another day or a later chapter in the grimoire.
00:12:27.360
As they walked, Red stopped and had to ask, "Aren't these dark magics? It feels like we're just doing bad things to language. Why would we want to do that?" Crimson replied, "Now come now, you're not one of them, are you? Some call these dark magics, while I would simply say we're exploring the possibilities of language.
00:12:55.740
Imagine the use of such things and how much more powerful Ruby might be with it. They might even merge it into Ruby core, word in these days."
00:13:10.290
Red nodded, suitably convinced, and they moved on to the glimmers of JavaScript.
00:13:30.380
In my journeys, and lands not far from this one, I found the lemurs of JavaScript fascinating masters, with lessons more fascinating indeed. The lemurs of JavaScript were fashionable, with all forms of accessories, colors, designs, and decorations.
00:13:50.360
They could even change the very language which they communicated with by using different jewelry, accessories, and a wonderful system called Babel. They brought with them an art of destruction beyond that which we know in Ruby.
00:14:09.440
It allows them to pull values out of objects by name. So, say we had a move north function, which can extract the x and the y values from the object passed into it. This is known as the art of destructuring.
00:14:20.440
But what exactly is that doing? You see, inside this function, the value of x is 1 and the value of y is 2, because it extracts those values from the object passed in. We can use those values to add 1 to y, and make it move north, as it were.
00:14:45.850
But there's another magic in JavaScript, one I have not found a way to emulate no matter how much I might try, known as punning. And of course, we love punning in Ruby! Yes, yes, several famous Rubists love punning, but this type of punning is different.
00:15:08.110
We have to ask what cost would it be to add this to Ruby? This allows us to make a new object with x unchanged and y with one added. But I need to figure out how to make this thing work.
00:15:28.420
Anyways, we can do destructuring in Ruby, but first we must learn the art of extracting arguments from a proc. Yes, you can do just that!
00:15:49.400
Say we had a function f, and the body doesn't matter. We just have arguments x and y, empty for now. Only arguments. Now, there exists a method called parameters on a proc; it returns back an array of pairs, the first being the type and the second being the name.
00:16:11.200
If we were to map the last item of those, we have the names of the function arguments. There are fun things we can do with this.
00:16:36.500
Now we need to make our own idea of destructuring. If we know the names of the arguments, we can use them. Let's say that we have a point—a simple struct. Now, for those not familiar with a struct, it’s vaguely like this, but it's a lot of code to write, and I don't like that.
00:17:01.890
So, for simplicity's sake, we'll start with the point at an origin of x of 0 and y of 0. Then we're going to make our own destruction function that takes in an object and a block function.
00:17:22.470
We can assume for now that the object is our origin point and our function will have arguments x and y.
00:17:43.620
So the first step is to get the names of arguments that we passed in. In our case of this x and this y, it means these arguments are effectively x and y.
00:18:05.130
Now that we have those names, we can do something very bad in Ruby. We can map over those names and use the object to send to extract those values from the function arguments. So the cases of our origin point of zero-zero and our function that takes the arguments x and y.
00:18:28.990
This means that the arguments become x and y. Our values are effectively going to be object.x and object.y, or in the case of origin, 0 and 0. Both are extracted using those argument names.
00:18:48.450
Now, what do we do with those values? You see, there's no rule in Ruby for when you need to call a function that is passed to a method. So we can call it at the end with those values we extracted, meaning we're effectively doing this with our origin points.
00:19:04.350
So, let’s step back to our point in origin. We can use a destruction method on this point, passing it a block function which takes arguments x and y. Because it's (0,0), this means that x inside that function is 0 and y inside that function is 0.
00:19:24.150
Inside this function, we can create a new point using that x and that y to add one to the value of y, which moves it north. Now, look how much fun that is!
00:19:45.940
Now, a clever lemur might be able to redefine methods with some of those same tricks to add a destructured decorator that can tell the difference between the object passed and its expected arguments.
00:20:03.370
But now the chapter I'm afraid is beyond us for the moment.
00:20:16.900
By this point, Red was very worried and had to say something about this. But surely, that's evil! Isn't metaprogramming the root of all evil?
00:20:34.160
Dreaded metaprogramming has its uses and is a fast, albeit seldom well-understood territory. Of course, there are dangers, but must one discard such power simply because it's dangerous?
00:20:52.420
No, it depends on the context and the wisdom of the wielder. Fast is too strong a word for what is merely misunderstood and abused by those not ready for it.
00:21:10.080
You're ready for it, aren't you, young Red? Yes, I believe so. Red nodded, convincing himself he was obviously ready for such an art.
00:21:28.720
Now, I have one last lesson for you from the wise sages of the realms of Haskell. Descending from their ivory towers, they bring knowledge far beyond even me.
00:21:45.740
But this knowledge is fascinating—the implications that may shake the very foundations of how we think about programming. They bring with them an art of lenses—an ability to focus on something and see or change its value.
00:22:03.360
I cannot say I fully comprehend them, but I find them fascinating nonetheless. And of course, I've tried to write them in Ruby.
00:22:30.430
Now, lenses allow the lemurs of Haskell to look deeply into a nested data structure, performing magic on that data without mutating them.
00:22:56.680
The examples they shared with me from the book of Hackage were very confusing at first, so I took some liberties in trying to make things more understandable.
00:23:20.540
I cannot say I understand how to make lenses work beyond that they fill in a lot of the code that makes lists. But I may be able to explain the rest.
00:23:39.930
We have a data atom with an atom containing a point, and we make lenses for both of those. At least, I assume that's what's happening.
00:23:57.709
Can we create a function that moves an atom to the north and returns a new atom, presumably moved north? Now, the point has x and y coordinates.
00:24:14.677
But what is that function doing down there? Let's simplify again because this is still confusing.
00:24:29.410
Now we have a move north function which uses the function over lenses and allows us to execute it over something which looks or behaves like a lens.
00:24:49.400
And now we're specifying that we want to do something over the y of a point and want to add one to that to move it.
00:25:03.500
Lenses allow us to specify a path to something and run a function over them to retrieve or change values without mutating the underlying object.
00:25:24.590
All this seems abstract, but you'd be surprised to know that you already know something in Ruby which does something similar.
00:25:40.930
The method dig references something like half the idea of a lens. It allows us to find a value that’s deeply nested in a hash, an array, or even a mix of both.
00:25:59.090
Oh yes, that's very fun! I’ve had so much fun with that! The key thing to pay attention to here though is the path.
00:26:14.050
With the path, we know how to get a value. Would it be that far of a leap of faith to say we could also set that value down there?
00:26:35.120
The path is the basis of a lens and lets you know what path you need to focus on. Lenses are much like glasses—scopes, or something like that.
00:26:50.670
If we wanted to apply something like this to Ruby, it may be difficult, but I believe we can get close. For this neat exercise, we can assume we have a nested set of hashes.
00:27:09.710
We'll use this to demonstrate. We start with the idea of capturing paths in class. We can call scope.c; it even sounds like a lens. We're making progress!
00:27:26.300
Now, we want to capture the path of what we're looking at within the scope and then define our own get function.
00:27:43.300
You might ask why we would wrap this in a function. Well, using the art of closures from before allows us to go over a collection and do something that looks a lot like this.
00:27:56.190
We can have a scope focus on a, b, and c, and we can map using the get to extract the values of one through five from those hashes we defined before.
00:28:13.430
But to set a value is a little bit more difficult. I had to do a few unique tricks to make this work.
00:28:26.600
The first thing we need to do is clone the object, to ensure we're not mutating something we don't want. This is a quick way to make a deep clone of a hash.
00:28:40.030
I can't say I understand how it works, but it does—and that's good enough for now.
00:28:57.790
Then we start by getting the path we need to get to our value. You'll notice that I left one of those paths off as a talking key—the last key that we need to focus on.
00:29:10.120
Let's get into that with a generational example: we use a, b, and c, meaning the lead-in to get to that value would be a and b. The target key would be c.
00:29:30.620
Now amusingly, to bury a value in Ruby, you would need to dig down to it first. This gives us a target location right above where we need to put the value.
00:29:44.260
This means that we have an array of a and b and a collection of a, b, c, with values "1" that means we're going to dig into that collection to get back the hash c:1.
00:30:06.600
Now, the next thing we need to do is decide what value it is that we're going to set there. If we happen to be given a block function, we're going to yield or call that function with the value at the target location.
00:30:25.670
In this case, it would be c:1, and the target key of c means we've added one to c. The new value will be 2.
00:30:43.350
Or let’s say that we didn't get a block; we could set it to a static value, which isn't quite as fun, but it's still useful.
00:31:05.370
Now we're relying on a value being set, so leading into our shenanigans—why did we want to do the entire lead-in thing? Well, if we want to overwrite that value at that location, we have to be just above it.
00:31:25.890
Because otherwise, we cannot overwrite the value of c in Ruby. We could use merge, but that's slow and I don't like slow code.
00:31:37.900
The Haskell lemurs were very put off by my interpretation of mutation-free code, but it works, and it technically doesn't mutate. We’ll call that good enough for now.
00:31:55.060
After all that, we started by getting the values at the path we need to gather the data at.
00:32:03.490
It could be used to deeply set a value according to paths. Imagine the possibilities—if we were to use this on JSON or large hashes.
00:32:19.700
We could even use triple equals to decide if we’re dealing with schemas or not, or if we allowed this to traverse any indiscriminate depth across any hash looking for a matching path.
00:32:34.630
I can't say much more on Haskell, considering I believe they don’t like me for some reason.
00:32:52.400
Going beyond magic, Red was fascinated by all the implications of Crimson’s tales—the possibilities! What else might lie in the grimoire?
00:33:03.620
So Red had to ask, "How many more tales are there in this grimoire of yours? How many more stories? What new tricks do you have in there? How many more from tribes and societies far and wide?"
00:33:21.360
There are tribes beyond all things—the conventionally Java lemurs, the mystical disbelievers, all the way to the orderly and well-dressed Python lemurs.
00:33:31.980
But there's one, or many, many tales—and there’s an entire universe out there, powers beyond imagination!
00:33:51.660
And so many more chances within the grimoire. Let it remind the potential of the fold lemurs out there, who taught us all their tricks.
00:34:10.000
We would be absolutely unstoppable! So the books left and right turned, and what he found behind him scared him far more than Crimson ever had.
00:34:33.660
Because Master Scarlet was back—and she was not amused. So Red turned quickly, trying to get help from his new friend Crimson, just to find a sign saying, "Good luck!" and a puff of dust from where Crimson had been standing moments before.
00:34:55.360
It seemed Crimson was also afraid of Master Scarlet for some reason. "We have much to talk about now, don't we, Red?" Red broke into a nervous sweat.
00:35:13.020
"Proper magic! This is a dangerous book!" Red was full of all forms of knowledge that he might not be ready for or know how to use appropriately.
00:35:35.150
He made a particularly intense study of the possible fears that awaited him. He must remember, for all languages out there, to always use Ruby.
00:35:54.800
For Ruby magic can indeed be confusing, unwieldy, and difficult to control. It's even harder to understand for those not ready.
00:36:09.690
But even given that, there are many lessons to be learned, wisdoms we may apply to the highest levels of Ruby.
00:36:23.210
And language is always evolving. We need people who are willing to experiment to drive its future.
00:36:36.180
Consider the lesson of the placeholder arguments: such a thing now exists in Ruby 2.7 with numbered arguments. And many more may well soon follow.
00:36:54.360
What is considered magic today may very well be canon law in Ruby tomorrow.
00:37:06.200
Now, there are many more tales in this grimoire and more lessons I’m sure Crimson could teach you.
00:37:29.200
But be cautious and wise in pursuing such knowledge; the cost is high for using such magics.
00:37:44.880
The great weaves of production you do not entirely understand yet, but the cost is higher to pretend they do not exist at all.
00:38:03.680
In the meantime, I do believe I have a test ready for you upstairs! I do hope you studied while I was gone because I'll be giving it as soon as I get up there! And with that, Red made a dead heat run towards the stairs.
00:38:23.150
Epilogue! So there, behind Master Scarlet, Red hurried up the stairs in a bit of a panic.
00:38:40.150
Once she was sure he left, she grinned and called out into the darkness, "So the Dark Lord Crimson, eh? Quite a title you've taken for yourself now, haven't you, dear brother? I thought you'd enjoy that one!"
00:39:01.520
Oh, just having a bit of fun, that's all! It's so rare to have visitors. You keep on knocking them out; I had to prepare a special surprise for such a momentous occasion.
00:39:19.030
Can you believe it? Someone actually wanted to learn from me today!"
00:39:34.600
"Surprise! You nearly scared the poor child out of his wits!" "That's not so surprising! That's horrific!"
00:39:52.910
"Yes, well, perhaps a bit too surprising. It's been a while! I really did enjoy getting to speak to Red. I suppose he has grown quite a bit since you've taken him in, hasn't he?"
00:40:06.240
He has, and I believe he’s finally ready for some of the lessons you and the other lemurs down here can teach him.
00:40:24.420
Interesting you should say that! It was quite strange to see him down here, especially with that giant door you had put up in front of my library to make sure he didn’t get into something beyond him.
00:40:40.890
It’s almost as if someone left the door unlocked on purpose! Now, whoever could do a thing like that?
00:40:57.010
Who indeed! And so it was in the tales of the Ruby Grimoire that Red the lemur would come to know of its magics.
00:41:07.300
That his master Scarlet would give him permission to study under Master Crimson, and he would move one step closer to his own mastery. For you see, magic is integral to Ruby.
00:41:25.470
To explore, to express oneself in code beyond what’s possible in many languages. The beauty of programming and Ruby is to have the freedom to do just that.
00:41:45.160
And that very experimentation can, and sometimes does, become a core part of the language, and sometimes it drives discussion around what Ruby should be in the future.
00:42:02.150
What we should be doing in programming, how we should be programming.
00:42:17.660
But there was a cost mentioned here; the cost can indeed be very high.
00:42:35.650
It takes a lot of discretion and great wisdom to handle such magic in production.
00:42:51.160
And often, the simplest of code is best. There’s a special type of magic in very simple, readable, and understandable code.
00:43:07.330
But that's a lesson for another day. To wrap up: it's been fun! This talk involved custom illustrations, 62 illustrations, 85 hours of work, and about 156 slides.
00:43:23.000
And your steel wouldn't see for good measure! Now, the scary part of this talk... you thought all those magics were just me doing presentations?
00:43:41.090
Oh no! Those who know me know very well that’s not true; it’s real, oh it is very, definitely real!
00:43:58.090
And there are gems currently. I might get a chance to do exactly that!
00:44:07.040
Placeholder arguments, the first Scala part we saw! SF happens to be the stack builder!
00:44:18.379
There are two little experimental things I would not touch—easier said than done, I might add! They break a lot of things!
00:44:34.869
Not surprisingly, destructuring was maxed into Qo, which was also an implementation of pattern matching that I’ve done.
00:44:48.610
And some of that ended up becoming pattern matching, and lenses are currently in something called XF.
00:45:01.640
And I'm still trying to convince Matz that we need a berry function—so we’re working on it! I’d still be quite fond of that function.
00:45:17.050
But we’ll endeavor nonetheless!
00:45:29.680
So, if you wish to find out more about the lemurs and our next adventures—because I fully intend to make more—follow me on any of these social networks.
00:45:43.640
I’ll be posting slides, examples, more. And honestly, we have to give credit where credit is due!
00:46:02.800
A talk like this doesn’t exist without a lot of help from the community—from those willing to entertain my mad scientist experiments.
00:46:18.440
What I can only call a very odd form of the hallway test—"Hey, you want to see something cool with Ruby?"
00:46:31.390
And those who did have time, I think them very much! Because those mad science experiments really built up a community of people who enjoyed hacking around and having fun!
00:46:49.000
You may also notice a few foxes—I hid them around earlier slides. This is because my first Ruby book happened to be written by a certain lucky stiff.
00:47:02.310
As you can see, it still influences the way I write and teach code today. Ruby needs more fun and whimsy.
00:47:16.650
So don’t be afraid to submit your own wild illustrated talks because I look very much forward to seeing them one day!
00:47:34.020
And, as with years past, we’re playing a little bit of a fun sticker game again!
00:47:48.110
You’ll find five Square engineers, myself included (yes, I have stickers!) up here, as well as several other presenters!
00:48:02.180
They’ll be off around the conference. I posted pictures of them tagged with #lemursofrubyconf.
00:48:15.870
So, if you can find them all, send me a picture, tag it, and we’ll have a special raffle with an indeterminate prize, which I’m still working on.
00:48:29.879
That’s how raffles work, right? But that’s about all I have for today.
00:48:39.670
So it’s been fun! Thank you for allowing me to tell you this magical little story.