Keyword Args — the killer Ruby feature you aren't using
This is a modal window.
The media could not be loaded, either because the server or network failed or because the format is not supported.
Formal Metadata
Title |
| |
Title of Series | ||
Number of Parts | 67 | |
Author | ||
License | CC Attribution - ShareAlike 3.0 Unported: You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this | |
Identifiers | 10.5446/37684 (DOI) | |
Publisher | ||
Release Date | ||
Language | ||
Producer | ||
Production Place | Cincinnati |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
|
Ruby Conference 201637 / 67
3
5
9
10
14
18
19
20
21
22
23
27
28
29
32
33
34
36
38
40
41
46
51
56
57
58
59
62
66
00:00
Content (media)Computer animationEngineering drawing
00:16
State of matterRight angleWordPrime numberCodeContent (media)Parameter (computer programming)Process (computing)Presentation of a groupKey (cryptography)Coefficient of determinationPrime idealComputer animation
01:52
BootingSoftware developerSoftwareDatabaseComputer fontPositional notationSoftware developerComputer configurationTwitterFunctional (mathematics)BootingWeb 2.0Declarative programmingPosition operatorSoftware frameworkParameter (computer programming)DatabaseCodeMultiplication signDifferent (Kate Ryan album)Block (periodic table)OvalRight angleComputer animation
03:29
Clique-widthClefDefault (computer science)Positional notationHash functionProxy serverParameter (computer programming)PasswordBitFunctional (mathematics)InternetworkingProcess (computing)Default (computer science)Hash functionProxy serverMultiplication signLibrary (computing)Formal languageServer (computing)Computer configurationQuicksortStandard deviationSystem callComputer animation
06:00
Server (computing)Proxy serverRevision controlCodeFormal languageQuicksortBlock (periodic table)Java appletSet (mathematics)IdentifiabilityGreatest elementEvent horizonRight angleParameter (computer programming)
08:16
Proxy serverServer (computing)Game controllerEmailGame controllerTable (information)Process (computing)Web 2.0Parameter (computer programming)Magnetic stripe cardQuicksortFunctional (mathematics)Email1 (number)Software frameworkComputer animation
09:27
Magnetic stripe cardOrder (biology)EmailPositional notationSolid geometryParameter (computer programming)InjektivitätQuery languageASCIILocal GroupDivision (mathematics)Block (periodic table)Functional (mathematics)Context awarenessMountain passPrice indexPosition operatorSet (mathematics)Functional (mathematics)Equivalence relationRow (database)Game controllerElectric generatorDefault (computer science)Magnetic stripe cardBitQuicksortDifferent (Kate Ryan album)Parameter (computer programming)Field (computer science)Web 2.0Table (information)Computer configurationBasis <Mathematik>Message passingLine (geometry)Order (biology)CalculationCodeHash functionWritingState of matterObject-oriented programmingTerm (mathematics)Social classSoftware frameworkFunctional programmingCAN busPartial derivativeVolumenvisualisierungSystem callElectronic signatureVariety (linguistics)Multiplication signContext awarenessRight angleTrailObject (grammar)Computer programmingInjektivitätExpressionComputer animation
14:57
Partial derivativeVolumenvisualisierungCellular automatonView (database)Price indexServer (computing)Proxy serverFunctional (mathematics)Key (cryptography)Equivalence relationQuicksortCodeMultiplication signFunctional programmingSystem callView (database)Functional (mathematics)CASE <Informatik>Default (computer science)Point (geometry)MereologyGame controllerTable (information)Coefficient of determinationSet (mathematics)WordRight angleElectronic data interchangeParameter (computer programming)VolumenvisualisierungBlogRow (database)ChainDifferent (Kate Ryan album)File formatRewritingComputer animation
17:12
LogicComa BerenicesComputer animationDiagramJSONXML
Transcript: English(auto-generated)
00:02
I'm going to get started, but before I go on to the content of the talk,
00:25
I feel like there's something I have to address, which is the election. This is very important. The District of Columbia has sent a petition or is about to send a petition to the Congress asking to be made a state. This will make the District of Columbia the 51st American state,
00:43
but I think we're missing an opportunity here. I think what we need to do is pick two more places, Guam and somewhere. Puerto Rico, make them states, because then we'll have 53 states, which is a prime number, and America will be a nation indivisible.
01:04
Thank you. Thank you. My wife said I should open with a joke. That's the only joke you're getting, though. Who here is using keyword arguments in their Ruby code?
01:22
Who here would say they're using keyword arguments enthusiastically in their Ruby code, like in most places? Okay. So with any luck, this will be the most useful presentation or one of that you see at this conference, because if I do my job right here, you will leave here
01:40
and change the way you write your Ruby code in a significant way. So I say the keyword args is a killer Ruby feature you're not really using. Who am I? I've been a software developer for 20 years, a Ruby developer for 10. I was in the room when Twitter was publicly announced for the first time
02:02
in Austin, I believe. It was about when I started using it. I taught at a boot camp for a Ruby web serving framework. I've been told if I mention this Ruby web serving framework at this Ruby conference, which isn't about the Ruby web serving framework, that burly men will come in and drag me out.
02:21
So I taught at a boot camp for that for about a year, and I do consulting around that and Postgres. And I've decided to start work, because people don't use Postgres and databases well enough in this community. I'm going to work on a book about that. Here's what we're going to talk about. We're going to make it clear what keyword args are and what they do,
02:44
how they make your code clearer, which might seem simple and obvious, but there's a little more to say about that than you might think. And then I'm going to talk about how keyword args can make the functions that you're writing more flexible and more functional in a couple of different senses.
03:02
So let's start with how keyword args work. Here's an example of a method declaration in Ruby that has every possible way of every kind of argument, right? So there's a positional required argument, a positional optional argument, positional argument splat, a required keyword argument, a optional keyword argument,
03:24
a keyword args splat, which it turns out is super interesting, and the block thing. Now, the clever folks who've implemented this feature have done a great job of making it nice and intuitive. So you can call a keyword args function like that,
03:42
you can take a hash and then call it like that, you can, if you're using something from like a millennia ago in internet time, you can call it like that. Here's a nice feature that I don't believe you can do with positional args, a keyword arg,
04:00
optional keyword arg can refer to an earlier keyword argument for its default value, which is really nice, and you can splat hashes into other hashes. So that's all very nice and intuitive and simple and fairly easy to use.
04:20
A couple of caveats, you have to put the positional arguments all before the keyword arguments, and because it does this business of interpolating hashes into the keyword arguments, if your last positional argument is a hash, Ruby can get confused. Yes, we're getting nodding over here. So I think it seems obvious that the main thing
04:43
that you're likely to get out of keyword arguments is that it's clearer. Here is a method that you might call from the Ruby standard library, and unless you've worked with this function very recently, I defy anybody to tell me what all these arguments are, right? They are in fact the server you want to hit and its port,
05:03
the proxy server you want to use, the port for the proxy server, and the last two arguments are, no, they're in fact the username and password for the proxy server. Now, Matz was talking about how Ruby is a human-centered language, and I'm afraid this is bad.
05:23
We can do better now with keyword arguments. So let's imagine a different world in which the Ruby standard library was rewritten around keyword arguments and what this method call might look like. Now, if you may have experimented with using keyword args and found yourself writing something like that and gone,
05:46
that's sort of better, but there's just ascii salad up here, you can't tell at a glance what's a keyword and what's an argument, it's sort of maybe a bit better, but not really, and fair enough. The problem, I think, is this book.
06:02
Now, let me be clear, I am an enormous admirer of this book. If you have to write any kind of technical book, you could do better than slavishly copy this book in every way you possibly can. Furthermore, I don't think we would be here today if it wasn't for this book. We, well, Matz wouldn't be here at all, and the rest
06:21
of us would be at a Java conference or something awful. Not only did it, was it responsible for teaching us all to use Ruby and showing the world what an amazing language it is, but it established a lot of the conventions that we all use, which is one of the delights of using Ruby. You can go and read somebody else's code, and because we all use the conventions that were established
06:42
in this book about how we write identifiers and blocks and all the rest of it, it's established a really nice sort of set of conventions. However, this book was written something like 15 years ago, and I don't think they have a version that covers the keyword args feature yet, and in any event, I think the conventions we've all got
07:00
around formatting our code come from this version of this book. So, in some ways, if we are to move on and use these new features, we have to be prepared to move past that book. So, if you're going to use keyword arguments, and there's more than like two of them, I think you should be prepared to write your Ruby code like this.
07:22
People, many people have suggested this too, are like kind of horrified, but I think it is quite clear, in fact, I can't imagine a way of making what you're saying here much clearer, right? I defy anyone to tell me that the bottom one is better in any way.
07:42
So, I've been going around, since I started really digging into keyword args, I've been going around saying this to people, and they're all like, yeah, okay, sure, it's, you know, it's a bit clearer, but I have to, to make it clearer, I have to change the way I work, and I like the way I work, and if I hire new people or show my code to someone else,
08:01
they're not really going to follow it, and you know, I kind of really like my buggy whip, and it's fair enough, like that's not enough reason to go away from here and start changing everything about the way you write code, right? But there's one advantage you can have, which is that it's clearer. There is a clear advantage, though, to keyword args,
08:22
which is that they are strictly more flexible than positional arguments. The first and most obvious way is that the optional arguments are all actually optional, so with positional optional arguments, you have to supply them left to right. I can't just give the third one, but with keyword arguments, I can pass in
08:42
whichever ones I happen to need for the job at hand. Keyword argument functions are strictly more flexible. Let's look at an example of what that might look like. So let's say I'm using some sort of a Ruby web serving framework, and I'm calling a, you know, controller functions,
09:02
calling a rendering function, and then later on I decide, well, I've got a new controller now, and it needs to be able to control what the headers look like. Well, I can add a headers argument to my function, now switching to the new style here in the function definition as well, and now I can pass that in.
09:22
And later on we decide, well, we would like to be able to control the striping in the table, say. So now I can add a stripes argument and pass that in. Now notice that one controller's passing in one optional argument, the other controller's passing in a different optional argument, and it's all nice and clear and easy to follow,
09:42
versus if you tried to do the moral equivalent of that with a positional argument function, you'd do something probably like that, and then you'd call it something like that, and that's obviously harder to follow, but past two or three optional arguments, you're just not gonna bother, right? You're gonna switch to some sort of
10:03
object-oriented solution, which is going to be more complicated. You're gonna have an initializer and then state that you've gotta track, and this lets you do things sticking to functions in Ruby, and that's sort of where the industry's going, right? Somewhat away from object-oriented bureaucracies,
10:23
and more towards a functional style of programming, and much of my message here today is that keyword args invite you to use Ruby in a more functional sort of style. In fact, I see nothing wrong with having lots of parameters, lots of optional parameters. It'll be a bit long, maybe,
10:42
but not hard to follow at all, I don't think. If this is a function that does a single thing, and there's just a variety of different options for how it should do it, I think this is fine. Why not? So keyword args are more flexible, and they allow you to rewrite code in one place
11:01
without having to change all the users more easily than if you'd used positional arguments. There's a term for that. It's called loose coupling, and that ability to have all the sort of assumptions up the top and to change them as you're going as you need is known as dependency injection, and both of these things are better if you write your functions using keyword arguments.
11:21
In fact, let's imagine that we're back in 2005, and you're working for a small company that's developing some sort of a Ruby web serving framework, but you have Ruby 2.3 available to you, and they say, we need a quick and dirty solution for an ORM, right? I want something where I can just sort of throw a where clause and an order by clause,
11:42
and it'll generate SQL for me. If you had Ruby 2.3 available, rather than the object-oriented bureaucracy that you might have done, you could write a function with a signature much like that, and if you think about turning that into an SQL function expression, it's cake, right?
12:00
So there's a lot of the time when you would until now have written object-oriented classes and all that, this feature invites you to adopt a more functional sort of style, okay? So I mentioned the keyword args splat as being super interesting.
12:21
So let's start out with the simpler uses of it. Say you have a salary calculation function, and then someone comes to you and says, we'd like to be able to override the arguments of that function on a per user basis, so there's a default set of behaviors,
12:40
and certain users get it different. So what you do is you add a JSON field to your user table, and you just do that. So what's really nice is that you can treat a hash in Ruby now as a kind of canned partial function, or whole function.
13:02
There's a term in functional programming called currying, and Ruby has a currying feature, but you can actually treat hashes now as something along those same sort of lines. And if someone says to you, okay, well, I want to override it on a company basis, and then override that on a per user basis if I want,
13:22
that's also cake. You just add a JSON field to the company, and you're done, and it's functional. It's more functional in a couple different senses, right? You're invited to do a functional solution, and it's easier and quicker to do. So I hope that's enough to convince you that you might like to leave here,
13:41
and go home, and maybe start writing your Ruby a somewhat different way, and writing much of it, or nearly all of it, around keyword arguments, because they're just better. Let me now illustrate something a little sort of wacky and crazy that I've discovered. I've not seen anybody else talk about this,
14:02
although I'm sure somebody else has discovered it, but it's a fun sort of interesting thing to look at to end this talk. I call it the context funnel. So here's what it looks like when you use it, and it just involves putting this star, star, C,
14:21
C for context, splat at the end of your functions. In fact, what you do is, in all the functions that you're writing and calling, not framework functions that you can't control, you always receive this splat, and you always pass it on. So let's see what that lets you do. Let's say I'm using a Ruby web serving framework,
14:43
and I'm calling a render table function, and maybe it looks like this. Now, since this is the first function I've called from my code, I'm adding the star, star, C, and in other functions that I call that I've written, I pass it on, and then maybe render row looks something like this, so the parts of my code
15:02
that I've written, in this case, a view, I pass that C onto again, and maybe my view starts out looking something like this. So I've got this sort of call chain that starts up at the controller with render table and ends with that view.
15:24
Let's say now, in some cases, I wanna be able to format that last name differently. So this is a sort of moral equivalent of the keyword args for a view, I think, right? So I'm allowing you to set a value if you want, and if not, I'm giving it a default behavior,
15:42
which is do the same thing we did before, right? Now look what I can do. Back at the top of that call chain, without changing anything in between, I can pass in this argument, and it gets passed down
16:00
by all the functions in between because they didn't understand and they didn't care about it, and it winds up down at the view. This is really interesting to work with, particularly as you're sort of exploring developing code. I was doing something, or I was parsing some complicated EDI code, and I was writing all these functions, and they were digging down inside this,
16:22
and then I realized down here I needed some value I had from some earlier point in the call chain, and without having to rewrite everything in between, I was able to change that. So this is an example of where a functional programming style and keyword args give you code that's more flexible. Anyway, that was just a little crazy thing I've discovered
16:42
that I'll put a post on my blog about describing that in more detail. Nearly out of time, but in summary, keyword args are clearer. They are more functional in a couple of different senses. They invite you to write a more functional,
17:02
simpler style of code much of the time rather than an object-oriented bureaucracy, and they are more flexible.