 All from this slide, my name is Randy Coleman, apparently, since I'm so creative in choosing my online identities. This slide is an exercise in just how many times I can get my name to show up on one slide. As of two weeks ago, I worked for Zeal, so a new job. It's kind of fun. I'm still getting my feet under me, but I'm enjoying it a lot. So a lot of us probably flew into this conference. So you've been on an airplane, long flight, maybe across the country. You get in, you need to find a way to your hotel. And let's say you decided that maybe a bus was the best way to come, because if you're like me, you're cheap, and you maybe don't have the best judgment sometimes. So you take a bus, and you get to where you need to get off, and you're trying to get out the back door of the bus, and you see this. There's these nice little bars on the side that maybe you think you should push, but no. You have to touch that yellow stripe in the middle, and that's not obvious, so they had to add the yellow stripe with the documentation on it. And apparently, that wasn't even enough. They had to add the white arrows as well, and say, no, you got to touch here. So documentation on top of documentation. So you finally manage to struggle your way off the bus with your suitcases, and then you have to cross the street to get to your hotel. And you have this button for doing this. And there's these bright red lights at the top or orange lights at the top that kind of scream, push me, push me, but no, that's not how you cross the street. You have to push that much dimmer button down below. And because that wasn't obvious enough, they had to add these arrows to point you at the right button to push. So you're starting to get a little frustrated. It's been a long trip. You're tired. You get to your hotel. You just want to get cleaned up a little bit, and you find a sink faucet that looks like that. In theory, you can get water out of that somehow. I'm not quite sure how. It's not really clear, but fortunately with this one, they provided instructions. Or not. So at this point, you're about to rage quit life. But fortunately, so what we're talking about here is something called affordances. Now, this is a physical design concept. I first read about it in Donald Norman's book, The Design of Everyday Things. I actually read it back when it was called the philosophy or psychology of everyday things, but I think he renamed it for more mass market popularity or something like that. But the idea of an affordance is that physical objects afford certain operations or actions. You got the crash bars on the doors out there are made for pushing. Door knobs are made for turning. Those are affordances. And affordances have also come to me in a little bit. How well does an object communicate its intended use? So these ones I just showed you were poor affordances, but what if you walked up to an escalator that looked like that? How many of you can figure that out pretty quickly just by looking at it? I think it's a brilliant design. Stand on the right, walk on the left. So there are good affordances and bad affordances. That's the physical design world. Affordances, I think, also apply to software. The most obvious place would be in UI design. You want your UIs to be intuitive. You want people to be able to figure out how to use them well. There's a saying that if you have to provide a manual for your website or your web app, you've lost. And that's probably true in a lot of ways. Affordances can also apply to APIs as well. You want APIs that are consistent, discoverable, easy to use. I've seen examples of APIs where not only do you get your payload back, but you also get a list of here are the URLs that are now valid given the current state of the application. And so those are also a form of affordances. In this talk, I want to argue that affordances also apply to programming languages. Different languages afford different kinds of solutions. And so by using the affordances of one language, we can solve problems in a way that's kind of unique to that language. But maybe we can take those ideas and bring them back to Ruby as well. Since this is a Ruby conference, all my examples will be applying back to Ruby. So let's look at an example of what I'm talking about. Let's look at a simple point class. So here's a point class in Ruby. I know you can use a struct. I'm using a class here. And you initialize it with an x and a y coordinate. And then you construct it by newing it up, just like normal Ruby. But what happens if you also wanted to support polar coordinates? I absolutely love the Cartesian bear. I have to keep that slide in this talk. No matter. I could change the whole talk, but I have to keep this slide. So if you don't know polar coordinates or you don't remember them, the idea is that you can specify points like we normally do with an x and a y coordinate. But you can also specify a point with a distance from the origin or a radius or r, it's called, and an angle from the positive x axis or theta. And there's trigonometry formulas for converting between the two. Those are polar coordinates. They're great for orbital mechanics, radio motion equations. It makes the math a lot simpler if you use polar coordinates. So if you're writing a library that uses points or a general purpose library for points, you probably want to support both Cartesian coordinates and polar coordinates just so that the class is flexible enough to be used where it needs to be used. So how do we do that in Ruby? We already have our initialized method defined. It takes two numbers. The r and the theta are also numbers. So how do we distinguish between Cartesian and polar coordinates? We could maybe add a third parameter that's like a tag that says, oh, this is polar. I know this is Cartesian. That's kind of ugly. Let's look at small talk instead. I know most of you probably don't know small talk. I'll try to teach you just enough for the syntax to understand the code. But this is the identical code in small talk. In small talk, all method names are keyword messages. So you have the colons there. So the x colon and the y colon are the keywords. And the nx and a y are the parameters. And so we have a class method. And this is actually the constructor of the point class. It takes an x and a y. And the little carrot is a return. So we're sending self the message new, which gives us back a new object. And then we're sending that new instance and initialize y colon method. And that's how it initializes. And then that method just assigns the parameters to instance variables. And we construct the object by sending the x colon, y colon message to the point class. So point x colon, 3, y colon, 4 at the bottom. So that's exactly the same as the Ruby code I just showed you. So in small talk, supporting polar coordinates is completely obvious. You just add a second named constructor method, r colon, theta colon, that takes the radius and the angle. This one forwards to the other constructor, the x, y constructor, and constructs the object. And so internally, it's still representing the point as an x and y coordinate. But you can construct a polar coordinate point. No problem. So small talk is providing this affordance of named constructors. And it's just the natural way to write constructors in small talk. There isn't one initialized method. There's just named constructors. And so the solution is completely obvious. It's affordance provided by that language. So can we apply that to Ruby? Well, sure we can. We can write a class-side method x, y, and another one called polar, that take the right kind of coordinates. Again, the polar constructor is forwarding on to the x, y constructor. And now we can construct a Ruby point, either with x, y, or with polar. And it's very clear that way, using named constructors. For bonus points, I pretended to make the new method private, although in Ruby, nothing's ever really private. But at least I'm communicating my attention here. Private class method, I think, is relatively new, 1, 9, or 2, 0, or something like that. So older Ruby's didn't have it, but you can actually do that. So that's one example. Here's another example. What if we want to find something in a collection, or detect is the other name for it? Small talk uses detect. Ruby has both. So here's small talk again. The hash with the parentheses is a literal array. And we're looking for an element in that array that's odd. So detect is the message name with the colon on the end. And then the square brackets is a block. And the colon each is actually the block variable. I know it's weird having a variable named each when Ruby, you have a method named each. But this is the small talk idiom, so I used it. The one difference from Ruby, though, is that if there isn't an element that matches the condition, then it raises an exception, whereas Ruby would just return nil. So here's the same code in Ruby, exactly identical. I use find here, because that tends to be more idiomatic Ruby, whereas detect is used more in small talk. But what if you want to do something other than returning nil or raising an exception when an element isn't found? Well, in small talk, there's a variant of detect called detect if none. And you pass a second block with the if none keyword. And that block is what gets evaluated if an element isn't found. So in this case, we're going to return the none symbol. That hash none is a symbol. So small talk has this affordance of being able to pass multiple blocks to a method. And it's used in a lot of places. In fact, small talk conditionals are an if true, colon, if false method that you pass blocks to. And they're implemented as methods on the true class and the false class. So it's actually a polymorphic message send to do a conditional in small talk, which is a completely different talk. So I'm not going to go into any more details on that. But passing multiple blocks in small talk is just natural. You do it all the time. Can we do this in Ruby? Well, it turns out that the find method in Ruby does take an optional parameter, and you can pass a proc or a lambda to it. So it's like passing a second block to it. How many of you knew that Ruby could actually do that? I see a few hands. I did a version of this talk at Mount Westrow this year, and there was one hand raised, and it was tender love. So not very many people know about this. But it works in Ruby as written. I didn't do anything special to make this work. So you can actually pass a proc or a lambda. I'm using the stabby lambda here, which should make maths happy, I think. And that lambda will get evaluated if no elements are found that match the pattern. People don't use this in Ruby because I don't think it reads as well as in the small talk. The focus of this code should really be, what am I looking for in the list, the main block looking for odd numbers? And this new, the second lambda kind of takes the focus away from that. So I don't think this code communicates as well, but it's perfectly valid code and it works fine. There's actually another example in active support testing assertions. Assert difference actually can take a lambda or even a ray of lambdas in it. So there are cases in Ruby where this is used, it's just not quite as common, but it's a neat trick that you can use when you need it. It is possible to pass a second block-like thing to a Ruby method. So there's a theory called linguistic relativity, or you might also know it as disappear-warf hypothesis. I have no idea if I'm pronouncing that correctly, but that's what it is. And the idea is that the language you use influences the kinds of thoughts you have or the way you conceptualize your world. Now there's a bunch of debate about whether this is actually a valid theory or a valid description of the way things are. There's a strong form and a weak form and you can go read up about that on Wikipedia like I did. But the idea is that our language influences our thoughts. Now this is talking about natural languages, but I think this also applies to programming languages. Corey Foy did a talk at Software Craftsmanship North America a couple of years ago called When Code Cries, which I love the title of the talk, it's awesome. But he asked two really interesting questions in that talk. And one is, what does a language allow you to say? What kind of ideas can you express in the language? And also, what does a language force you to say? Does the language force you to say things that you don't want to have to say? And he used an example from natural language where some languages have gendered nouns. So if I was talking to you and I said, oh, I went to a movie with my neighbor, you might, especially if you're my wife, want to ask me, well, was your neighbor male or female? And unless you're my wife, I'm probably going to say, well, that's really none of your business. But if I was speaking to you in French where they have gendered nouns, then when I used the word for neighbor, I would instantly be telling you whether my neighbor was male or female because of the gender form of the noun that I used. And so French is forcing me to say something that English doesn't force me to say. And that's also true in programming languages. Some languages force you to say things that you don't want to say. For Java, for example, you have to say your types over and over and over again. But also what languages allow you to say is important as well. Now, all of our languages these days are basically Turing-complete. You can express any computation in them, but they're not all equally expressive, and that's important. When I was researching this talk, I came across an old presentation by Maths at OSCON in 2003 talking about the power and philosophy of Ruby. And one of the things he said on one of the slides is languages are not only tools to communicate, but also tools to think. And he wanted Ruby to be a good thinking tool, and I think he succeeded very well, but that's important. So the languages we use influence the thoughts we have and help us to think better thoughts sometimes. So let's look at a few more examples. When we're programming, we often have to clean up after ourselves. Now we have garbage collectors now, so that helps with one kind of cleanup, but there are other kinds of resources we have to clean up, file handles, socket handles, threads, locks, et cetera. And so we often have to worry about cleaning up after ourselves. We have to free up resources when we're done with them. So I'm gonna show you some really nasty C codes, so there's a warning. Fortunately, there's a party right after this, so you can kind of go drown the sorrows of what I'm about to show you. How many of you have seen C code that looks like this or this specific C code? Yeah, there's more hands than probably you're comfortable admitting there are. Anybody recognize this particular piece of code? Yeah, there's a few. This was an SSL bug that Apple had back eight or nine months ago. It's called the go-to-fail bug. And the problem is that somebody deleted a line of code in the middle there, and because this code uses a particularly egregious set of coding styles, it introduced a bug. But the whole point is that there was a necessity to clean up no matter how we finished this function. We had to go down to the bottom and free up those buffers at the end. So there's gotta be a better way than this that doesn't result in bugs like this. And I'm not gonna try to clean up Apple's code. I'm gonna give you a slightly more simple example. I have this very expressively named function called foo or a method called foo. And in it, we have to acquire some resource, do some things with it, and then release the resource when we're done. Now, there's at least three or four ways that you can get out of this method, and only one of those ways is actually gonna release the resource when it's done. And that's the natural progression right through the end. There's an early return in there. That's the obvious way that you can get out. But also any of the methods I call in there might raise an exception. And if they do, I'm gonna leave this method and I'm gonna blow up and not free my resource. So I've acquired the resource and I've caught the exception out of an outer layer and I did not free my resource. I just leaked it. And if I run this code a lot in my system, eventually I'm gonna run out of resources and my program's gonna blow up in production. And that's not cool. So we have to write our code differently to protect ourselves against these problems. So here's one way you could do it that actually solves the problem. It releases the resource when the exception is thrown. But look at what we had to do. We had to change the early return into a nested if statement. And so now we've got what I call wedgie code, where it's all shaped like a wedge because of all the levels of nesting. We had to catch an exception that we really don't care about here and then re-throw it. We had to duplicate the code for releasing the resource. Those are like three ugly things we had to do this code. And I'm not saying the original code was all that great, but this is worse. Feels to me like running a stove like this where if you want medium heat, you have to press a button like six times to get it. Fortunately, they give you two buttons so you don't have to press it 12 times to get high heat. But still. Or maybe dialing a phone like that. Anybody remember those? Interesting thing I read once is that the bigger cities in the US have area codes using lower numbers like New York is 212 and Chicago is 312. I think LA is 213 if I remember right. And the idea is they were actually optimizing for the more frequently dialed area codes. They figured the more populist places, those area codes would be dialed more often. And so they made those as efficient as possible with the dial. That's totally a side note, but I thought it was kind of cool when I read it. So what can we do instead? We can use an idiom from C++ called resource acquisition is initialization, which speaking of affordances is not a well-named idiom at all. But the whole idea is that you acquire your resources in constructors and you release them in destructors. And the reason that works in C++ is because C++ has deterministic to structure semantics. When an object goes out of scope, its destructor is called immediately right then. It's not later when a garbage collector runs. It's not never. It's always right when that scope ends. And it doesn't matter whether the scope is ended normally by just exiting out of it or abnormally by raising an exception. It always calls the destructor right then. And so there's a pattern you can use in C++ that takes advantage of that. And so we can write a safe resource class. And safe resource, we acquire the resource in the constructor, we release it in the destructor, and I added a get method so that other code can work with the actual resource itself. And then we can look at our foo method and now we create a safe resource at the top of the function. On the stack is what it's called in C++. And when that function exits, safe resource goes out of scope, its destructor gets called, and it releases the resource. And it doesn't matter how we exit the scope, that will get called. And so now our code looks basically like it did before. There's a couple extra get calls in there. But it has the same form as it did with the early return. We're not catching the exception we don't care about. We don't even have to call the release call anymore because the destructor does it for us automatically. So this is even a little bit better. And this works. It releases the resource. So we have this affordance from C++ called deterministic destructors. Can we take that affordance and the solutions that it allows us to create and apply those to Ruby? Well, Ruby doesn't have deterministic destructors. So what can we do instead? Well, we could use begin and ensure everywhere, which is kind of ugly. Every client would have to do that. It's like using try and finally in Java. And if you've ever read much Java code, there's tons of that littered everywhere. I don't like that idea very much. You can actually define a finalizer in Ruby. You can define a method that will get called when the garbage collector finalizes an object. That's not quite deterministic because it only happens when the garbage collector runs. But you can do that. Not very common. People don't do it very much. But Ruby has blocks. And so maybe we can do something with blocks instead. So here's a safe resource class in Ruby. There's a class side method called acquire that allocates the resource, acquires the resource, yields the resource to a block provided to this method and then has an insurer that releases the resource when it's done and then initialize and release or the acquire and release of the resource. And we can use that in our foo method just like we did in C++. We have to do it a little bit differently where we have to use this class side acquire method. So we can say safe resource dot acquire and then the do end is the block that we're passing to it and that code will get executed while the resource has been acquired. And when the block exits, whether normally or abnormally, the insurer block in the acquire method will make sure that we release the resource when we're done. So this is very similar to the C++ code. We're using blocks to give ourselves those semantics. You've probably used this idiom before in your Ruby code. If you use file open that takes a block, it opens the file. The block executes while the file's open, closes the file when you're done. There's lots of places in Ruby where this idiom is used and that's basically the way you solve the problem in Ruby and actually Smalltalk as well uses the same idiom for this. Blocks are great for this. And just showing you that works as well. All right, another example, kind of similar to cleaning up after yourself and this is places where you need to restore state. So for example, in a graphics program, you might want to use a certain pen or a certain foreground color, do some drawing and then set that state back to where you were. This time I'm actually gonna use Emacs list for my example language because I used to program list years ago and I love it, it's pretty cool language. So here's some code where we want to delete some text between a couple of delimiters and so the interactive there just means that this is code that's gonna be executed interactively by the user or it can be, it's not just a function to be called by other code. Emacs list is the language used to customize Emacs editor by the way. And then there's a save excursion thing that I'll talk about in a minute and within the code we're just skipping backwards to find a delimiter and then skipping forward to finding a delimiter, remembering the two places where we found those delimiters and then deleting the region between those two points. That's what that code's doing. What save excursion does is it basically remembers the state of what buffer you're in, where's the cursor located, where's the selection, all that kind of stuff and once save excursion is done, it restores that state back. So in Emacs list when you're writing functions to manipulate some text or find things, you can put everything in a save excursion and then you can go all over the buffer, do whatever you need to do and then save excursion will take you back to where you were. And the way it works is, now the actual implementation is in Emacs C code but it works as if it was written as a macro. List macros are really cool. They're probably more powerful than most things you've seen. There's a little back quote there that basically quotes all of the rest of the form there and so when the macro is expanded, it's like it generates that code that's protected by the back tick. So what we're doing is we're remembering the current buffer, the current location of the point, the current location of the mark which is another Emacs concept. Unwind protect is like an insure block in Ruby. Progn says here take a list of forms and treat them as one form and return the value of the last one and then the comma at sign basically splices in the body we provided to this method into that location in the macro. And so this is gonna expand out to code with the let form, the unwind protect, then all of the code that we provided in the body of save excursion and then the three forms at the end are what's done by unwind protect as that code exits. So you don't need to understand the list very much but this is a very common pattern in a list macro where you do some stuff, splice in some forms and then do some other stuff. Okay, so we have this affordance of macros in Lisp. What can we do in Ruby? Well, the answer again is blocks. Blocks help us here again. So we can write a version of save excursion in Ruby where we remember the state at the beginning, we yield to a block and then we ensure that we restore the state at the end. And so again, we've been able to use Ruby's blocks to substitute for at least one kind of macro that you might write in Lisp. And there's our delete and close text where we call save excursion, we pass it a block where we do the work we wanna do and save excursion takes care of restoring the state back where it need to be. So any kind of code where you write, where you kinda want something in a certain state while you run the code and then you wanna automatically restore it back at the end, again, you can use this pattern with blocks very much like Lisp macros. There's some other examples in this blog post I read recently by Kevin B. Cannon of 8th Light where he takes a couple of other Lisp macro ideas and applies them back to Ruby again using blocks. Interesting article to read. I have one last example for you and this is the idea of an image reader. This is again from Smalltalk. I programmed Smalltalk for like 13 years before I started my new job two weeks ago. So I like Smalltalk a lot, it's a great language. But the image reader ideas, we've got this base image reader class and we want it to be able to read any kind of image and we wanna be able to even support images we haven't even thought of yet or we haven't implemented yet without having to change our image reader class. So this is code actually in the VisualWorks Smalltalk base image. I've changed it a bit for presentation purposes but it's essentially the same. This is a little bit of a wall of Smalltalk but what this is is a class side method called from file, you pass it a file name. It opens a binary read stream on the file and then it sends itself the reader class four method with that stream and assigns the result to reader class. If you can't find one it raises an exception but otherwise it instantiates the reader class on the stream and then closes the stream when it's done. So the idea is it's gonna search somehow for a class that can handle this format of file and we're not looking at file extensions here, we're actually looking at the contents of the file. So reader class four takes the stream and what it's doing, a Smalltalk class knows all of its subclasses. So you can ask actually for its direct subclasses which is what we're doing here or it's all of its descendants, there's an all subclasses method that does that. And so we're asking the class for its subclasses and then we're doing a detective none which we saw earlier. So we're looking for a class that satisfies this first block. We're resetting the stream back to the beginning and then we're asking the class, hey, can you read this stream? And the class is gonna return true or false depending on whether it understands that format or not. And when we find one that answers true, that's what we'll return from this method. So that's how we find our reader class. So we have this affordance in Smalltalk again of being able to ask a class for its subclasses and iterate them all. Can we do this in Ruby? Well, let's see. We have a read method on the class side, takes file name, opens a binary stream on it and then calls this findReader class method with the stream. Raised as an exception if we can't find one otherwise creates the class on that stream. So far it looks pretty much like the Smalltalk. Well, here's findReader class. How does that work? Saying subclasses.find, so reason find instead of detect and ask the reader class, can you read this stream? Again, very much like Smalltalk but how do we get subclasses in Ruby? Ruby doesn't keep tracking that for us, does it? No, it actually doesn't. But we can simulate it with two little methods here. So a class has a hook method that's called when a subclass is defined. And so when you define a subclass of imageReader, this hook method inherited will get called and it'll pass in the subclass that was just defined. And so what we can do is we can shovel that onto a lazily initialized array and remember it. So this class is keeping track of its subclasses as they're defined. And that's how we can iterate them. We just were calling the subclasses method and iterated them all. If you're using active support, it actually does this for you. There's a subclasses method defined by active support. There's also a descendants method that gives you all of the descendants of the class. So active support is doing this for you but you can do it yourself in plain Ruby with these two methods. And so we can write a bitmap imageReader and all we have to do is implement the canRead method and it's looking for the bitmap signature which is the first two bytes have to be VM. The read image is the method that would actually read the image here. I'm just printing out a string so you can see it's doing the right thing. There's a JPEG imageReader. It looks for the JPEG signature and that dot B on the end of the string there is because encodings. That's about all I have to say about that. And we can have a ping imageReader which looks for the ping signature which is actually eight bytes long and it's kind of actually fascinating. There's things in there to detect byte ordering and carriage return line feed conventions and so on that whole signature has meaning there. It's there for a very particular reason which I found kind of interesting. And so we can run this code over a set of files. I ran this over directory with one of each kind of file and it reads each one by just looking at the content. And so because it's looking at stream content you can even use this class directly on a stream by reading it back from like an HTTP endpoint or something like that, getting back image data. You don't even have to have it in a file if you don't want to. So that's kind of cool. Very similar example is a blog post by Andre Bernardis I just read a few weeks ago called Inverting Dependencies where he's trying to solve a very similar problem. The way he solved it is the subclass when you define it it would actually call a method on the base class to register itself with it. You can solve it the way I did here with just keeping track of subclasses as well. But it's very similar problem. You see this from time to time. I've seen it for like URI scheme handlers where you want to define new handlers as a subclass of a basic handler. And you really don't want to have to go back to the base class and change it like to add a case to a case statement or something like that. So this technique is great for that where basically as long as you have something that requires in the class that you need it kind of automatically participates in the resolution of what you're trying to resolve. So it's kind of cool. So what have we learned today? The first thing is that languages afford certain kinds of solutions or designs and inhibit others. So you just naturally solve problems certain ways in certain languages and other solutions don't come so naturally in those languages. Our languages influence our thoughts. So when we're programming all the time in one language we think one way and we solve problems one way. Whereas if we use a bunch of different languages it expands our thoughts. And so by learning new languages you can increase your solution space. So when you're trying to solve a hard problem the more things you have to draw from the wider the set of solutions you'll have to consider and the more creative your solutions will be. You'll come up with better ideas, better designs because you know more things. So I guess my encouragement is to learn as many languages as you can. And even if you don't ever use them for real code just becoming fluent enough to understand how to think in them will help you with your Ruby or whatever other languages you're working in. But don't go too crazy with it. You can get a lot of great ideas from functional programming for example but if you tried to go full on immutable data structures in Ruby you're gonna give the garbage collector fits. Other languages are much more optimized for that kind of thing but certainly take the ideas that work and don't go too far. You also want people to be able to understand the code you write and you want to use the language for what it's good for and its strengths. Years and years ago I was forced to write code in VB6 and I'm almost done with my therapy finally. But VB6 does not have implementation inheritance. And back then I didn't know this but implementation inheritance is quite overrated but when you need it you really need it. And so I came up with a way to kind of simulate it in VB6 using composition and delegation. And I'm not sure my coworkers really understood my code all that well. I kind of taught them the pattern but I'm not sure they really got it. That was probably too far. So don't go too crazy with this but certainly take the ideas. It's amazing how many times I learned something that doesn't seem related to my job and yet within two weeks we'll come across a problem that's like oh I just read about this thing and it works here. This happens all the time. So just learn what you can and expand your space and your ideas. If you're interested in this topic if I caught your attention a little bit I actually wrote a whole series about this on my blog. I cherry picked the examples that applied to Ruby but I kind of gave some other examples that applied to other languages as well. Tom Stewart did a great talk at GoGuruko a couple of months ago called refactoring Ruby with Monads. Probably the best introduction to Monads I've ever seen and also is very much along these lines where you can take the Monad idea from functional languages and apply it to Ruby code to come up with better solutions. So I highly recommend checking that talk out. I want to thank Zeo for sending me here. And there's references to everything I talked about. Thank you Adam. I'll have the slides up on speaker deck later today or tomorrow. And I'm on speaker rate. If you want to give me feedback on the talk I'd appreciate it. I'm always trying to get better. Thank you very much. Enjoy the party tonight.