AV-Portal 3.23.3 (4dfb8a34932102951b25870966c61d06d6b97156)

Metaprogramming? Not good enough!

Video in TIB AV-Portal: Metaprogramming? Not good enough!

Formal Metadata

Title
Metaprogramming? Not good enough!
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 license.
Identifiers
Publisher
Release Date
2016
Language
English
Producer
Confreaks, LLC
Production Place
Cincinnati

Content Metadata

Subject Area
Abstract
If you know how to metaprogram in Ruby, you can create methods and objects on the fly, build Domain Specific Languages, or just save yourself a lot of typing. But can you change how methods are dispatched? Can you decide that the normal inheritance rules don't apply to some object? In order to change those core parts of the language, there can't be much difference between how a language is implemented and how it's used. In this talk, you'll make that difference smaller, building a totally extensible object model on top of Ruby, using less than a dozen new classes and methods.
Loading...
Web-Designer Metaprogrammierung Online help
Slide rule Programming language Programmer (hardware) Greatest element Programming language Internetworking Software Web page Feedback Different (Kate Ryan album) Convex hull Twitter
Programming language Programmer (hardware) Default (computer science) Code Time zone Bit
Boolean algebra Laptop Programming language Macro (computer science) Monad (category theory) Metaprogrammierung Metaprogrammierung Monad (category theory) Erlang distribution Mereology Macro (computer science) Erlang distribution
Programming language Mobile app Inheritance (object-oriented programming) System call Electric generator Inheritance (object-oriented programming) Code Metaprogrammierung Energy level Pattern language Endliche Modelltheorie Social class
Programming language Programming language Inheritance (object-oriented programming) Object-oriented programming Object model Object model Core dump Bit Endliche Modelltheorie Data structure Data structure Social class
Inheritance (object-oriented programming) Programming language Code Artificial neural network Mathematical analysis Parameter (computer programming) Mereology Revision control Prototype Tablet computer Pattern matching Type theory Different (Kate Ryan album) Object model Software Aerodynamics Implementation Abstraction Programming language Axiom of choice Inheritance (object-oriented programming) Decision theory Suite (music) Primitive (album) Code Bit Semantics (computer science) Open set Object-oriented programming Programmer (hardware) Function (mathematics) Atomic number Endliche Modelltheorie Representation (politics)
Functional programming Building Group action System call State of matter Code 1 (number) Set (mathematics) Parameter (computer programming) Function (mathematics) Mereology Disk read-and-write head Mathematics Hooking Different (Kate Ryan album) Object model Single-precision floating-point format Core dump Arrow of time Diagram Extension (kinesiology) Error message Lambda calculus Social class Exception handling Physical system Graphics tablet Programming language Computer virus Sampling (statistics) Bit Maxima and minima Instance (computer science) Message passing Root Order (biology) Normal (geometry) Right angle Pattern language Cycle (graph theory) Permian Data structure Surjective function Ocean current Point (geometry) Trail Implementation Inheritance (object-oriented programming) Link (knot theory) Simultaneous localization and mapping Letterpress printing Online help Power (physics) Latent heat Goodness of fit Tablet computer Object-oriented programming Root Energy level Data structure Implementation Default (computer science) Default (computer science) Dot product Key (cryptography) Inheritance (object-oriented programming) State of matter Generic programming Plastikkarte Core dump Line (geometry) System call Object-oriented programming Kernel (computing) Pointer (computer programming) Loop (music) Personal digital assistant Network topology Social class Routing
Functional programming Building System call Run time (program lifecycle phase) State of matter Code Multiplication sign Sheaf (mathematics) Parameter (computer programming) Mereology Disk read-and-write head Mathematics Different (Kate Ryan album) Single-precision floating-point format Object model Core dump Diagram Endliche Modelltheorie Volumenvisualisierung Lambda calculus Social class Physical system Exception handling Programming language Software developer Metaprogrammierung Binary code Electronic mailing list Bit Message passing Order (biology) Normal (geometry) Right angle Modul <Datentyp> Quicksort Permian Spacetime Point (geometry) Implementation Inheritance (object-oriented programming) Link (knot theory) Virtual machine Limit (category theory) Drop (liquid) Login Coprocessor Revision control Goodness of fit Object-oriented programming Energy level Normal (geometry) Module (mathematics) Default (computer science) Execution unit Multiplication Inheritance (object-oriented programming) Information State of matter Line (geometry) System call Uniform resource locator Object-oriented programming Loop (music) Social class Intercept theorem Routing
Point (geometry) Slide rule Building Inheritance (object-oriented programming) Computer file Link (knot theory) Code Multiplication sign Computer programming Twitter Writing Online chat Prototype Pattern matching Conjugacy class Object-oriented programming Bit rate Object model Touch typing Boundary value problem Energy level Cloning Endliche Modelltheorie Computing platform Address space Physical system Social class Programming language Email Dependent and independent variables Multiplication Computer virus Electric generator Inheritance (object-oriented programming) Software developer State of matter Shared memory Electronic mailing list Sampling (statistics) Fitness function Entire function Symbol table Object-oriented programming Social class Physical system Row (database)
Point (geometry) Programming language Meta element Implementation Metaprogrammierung Multiplication sign Coma Berenices Function (mathematics) Instance (computer science) Programmer (hardware) Right angle Macro (computer science) Spectrum (functional analysis)
all right well hey everyone hope you've
been having fun so far you're not totally acknowledged out yet I'm Justin Weiss and I lead the web development team at Abu where we get people the quality legal help they deserve before we get going at the
bottom of these slides that's my twitter name feel free to ping me with any questions or feedback and I'll check it out afterward and there's also a hashtag over there at on EOG's free to use if you tweet about or take any pictures or anything like that no I guess most of us are here because we love Ruby I mean this slide kind of says it all for me but I mean how many of you have started to wonder what your next favorite language is gonna be right I mean this isn't a totally new thing one of the
biggest things that stuck with me after reading the pragmatic programmer so many years ago was this idea of learning a different language every year so I did
and I still do after I read that book I decided that Ruby would be the language that I've learned for the year I built everything in it like I felt like it was my new language so naturally I thought that next year's would also be my new language but you're - I learned another language and I went back to review your three I learned another language and I went back to Ruby and Here I am over ten years later and my primary language is still Ruby and this kind of bothers me a little bit because I want to think of myself as open-minded like I want to be more flexible than that I don't want to identify thyself by the language I write in and I don't want it to like automatically default to one just because it's the one that I'm most familiar with but why doesn't anything else stick quite as well as Ruby didn't if you think about this a little bit you come to this question what makes Ruby Ruby why do you use it when you think about Ruby what comes to mind what about programmer happiness I mean
if ruby was designed to make programmers happy I feel like it's wildly succeeded I've never had a language fit my brain so well or helped me turn my thoughts into code so easily and that's really cool but there's also something else like what do you think about if you think about language features and just
like you might think Erlang animals actors or Haskell equals monads or list equals parentheses sorry macros with Ruby I think about metaprogramming so what do you think guys would be happiness or is it metaprogramming why
not both I think the metaprogramming part in a
way leads to the happiness part I can see by some of your faces that you don't quote totally agree but I do with metaprogramming you can craft the language to you and what you need to do you aren't stuck with what the language gives you and the language doesn't fight you those things they make the language feel like a part of you you know like your favorite jacket or your laptop covered in stickers of your favorite things not just a tool that you use to get through the day that's how I feel meta programming leads to happiness Ruby helps you feel joy by getting work done more quickly and having a lot more fun while you do it and in my experience meta programming plays a big part of that but what if you
wanted to want it to know what else is possible what if you wanted to wanted to do more than what meta programming it allows you to do what if you wanted to change how a language works at a deeper level ideas like basic inheritance like if you what I met that is called if it
doesn't exist in your class call it in your superclass those patterns are usually hard-coded into a language and they can't really be changed easily even if sometimes you want to skip a generation but what if you wrote code in a language using the same pieces you use to build that language you'd be able to change almost anything about how the language works you'd be able to mold the language to the ideas in to the mental models that your app uses and you can learn about a language at a deeper level that you normally have access to the neat thing is we can get there and
to do it we'll try building a brand new object model on top of Ruby okay
object model is a little bit jargony what I mean by that is the core concepts the data structures the methods you use to build things in your language do you have classes objects method missing inheritance all of these things are pieces of an object model if it a language is how it looks you can think of an object model is how it works and if our object model is flexible enough it can change itself and that's what we're going for so what would that flexibility look like there's a paper I
found called open extensive
object models that describes how to create a flexible object model like this from only a few small parts and will follow along but will also take advantage of some of the flexibility that's already built into Ruby so we won't follow it exactly and all of this starts with a question if you're given a
method name and you have some arguments how do you know which a version of the method or which code to call so many interesting differences between languages you know like whether it has inheritance or pattern matching or prototypes or proxying they all come from answering this question in a little bit of a different way but what if you could describe encode how did find the right method and what if you could change that code to act differently in different situations you could change the entire style of your language just by overriding a method in a language
with simple single inheritance that lookup code might look something like this you look up a method by name in your object if it doesn't exist you find it in your parent instead but already we're starting to assume some things like object class parents do we really need to lock those ideas down already what's the bare minimum that we need in order to really be an object model it helps to think about what an object actually is it needs to keep track of some states like a person's name or their favorite food and it needs some way to access or change that state like a set name or an eat method those methods make up the objects behavior so state and behavior those are really the two kinds of things that we need there's a big difference between state and behavior though you can share behavior between a set of objects like every person object might have an eat method and that method would run the same code no matter who calls it so - but state is specific to a single object so for instance while two people could have different favorite foods that food can be eaten in the same way this is an important part and it kind of drives a lot of the rest of the stuff that comes in here so it's it's good to solidify state is unique to an object but behavior is shared between a set of objects so what is behavior then if you think of behavior as a group of methods shared by a bunch of objects the answer starts to solidify a little bit a group of methods is state right it's just a collection so what if behavior it could be an object itself it might look something like this it has a set of methods that could be used by another object that points to it you could even call this kind of object a class you know like a person class because it acts a little bit like a ruby class different objects that inherit or that use it can all use its methods but if a class's state is a set of methods what would a class's behavior be what if you went one step further this is where it starts getting a little bit tricky because it's a little bit beyond what we're used to day to day remember behavior helps you access and change your state so if you wanted to add a method to something we're treating like a class where would that add method method come from how would that class know how to look up methods that are on it or its inheritance tree just like how the eat method on a person object comes from its behavior the add method method on a class object comes from its behavior you just follow those arrows those links you can think of this object this one on the far left over there as the class's behavior or the classes class this is a little bit weird and it gave me a headache at first because what is the class's behaviors behavior and then what is the class's behaviors behaviors behavior and so on but eventually it all goes recursive and you can stop thinking about it what's cool though is that classes class objects and behaviors they're all kind of at their core the same thing they're just state and behavior but you start to extract these these kinds of patterns as you start playing with them and hooking them together and filling them out even though they're all the same thing though here I'm going to describe them as a few different things because if you think too abstractly the stuff is impossible to keep in your head trust me I tried so in for now I'm going to call an object any of these things a class a thing that builds objects holds methods has a parent like one level abstracted from your objects and a behavior a thing that holds specific methods like lookup an ADD method that make up the core of this object model so what do we have so far we have a simple object we have a way to add methods to an object state and we have a look at method that you can use to find methods given a name in smart and there are really only a few more things that we need you know if you have a class you need some way to create objects from it like new objects that can use that classes methods so we'll write a method for that that will call build object and you'll also need to create new behaviors or subclasses so you can override methods for now basic inheritance is enough to get things started so we'll need a method to handle that well name that one delegate because after calling it unknown methods get delegated to the thing that's linked as the parent the class that you call a delegate on and then the last thing we need is a way to actually call methods by name so we'll name that ones send so we have five methods add method lookup build object delegate and send and one super generic object layout and with just those parts you have a healthy object model you can use to build in almost any language and extend in almost any way that you can imagine so I said we can build it in almost any language were true become so let's build it in Ruby to keep Ruby's helpfulness as far away as possible well define our object as a basic object if you haven't seen basic object before it's just like a normal object except it's missing all the methods that make object useful so we want to keep ours small and simple we don't want to accidentally run into that stuff and and cheat a little bit so this is a good fit and by the way don't people need to remember or completely understand fully all this code I'll include a link with a gist for all the sample code in it towards the end so we'll need to write those core methods those ones that I just described once that's done we can use those core methods to start creating objects and hooking everything together the first one we need is add method this one defines a method by adding it to a class remember classes store methods in their state so this one is pretty easy it just adds the method implementation to the state under a methods key for all these methods as you can see by my beautiful ASCII art arrow up there we passed the thing the method was called on as the first argument so if we're calling person dot add method or like Justin not hello or something like that Justin would be passed as that first argument and person would be passed as that first document the next one we'll write is the lookup function at least the default one this is that's fun to override this one's kind of big so we're gonna take it in parts the first thing we'll try to do is find the method that we're trying to call in the current behavior of the current class of State remember an ADD method we just put it in there here we're just pulling it right back out if it can't find it it'll go through the parents and all of the rest of its ancestors by calling itself recursively so here's what that looks like all put together we try to pull the method out of the behavior state and then if we don't find it we call itself recursively - on the parent to try to track it down somewhere in our parent hierarchy the next one is build object this one is the one that's kind of like dot new it creates a new object from a class or from a behavior this creates a tiny object object one of those ones that we just defined earlier it sets an empty state so we don't have to worry about initialization or anything like that and it points the behavior to the class that we're calling build object on so if you call person that build object it's going to take your new object and it's going to say this is a person it has access to those person methods and so on the last one we'll need to build is our delegate method our inherit from a class create a subclass that kind of thing this one is probably the trickiest out of all of them so we'll start with a diagram in this example say we want to create a baby subclass this baby subclass needs to have access to our core methods like add method lookup all that stuff but how does it go how do we get that like maybe we need to create somehow so we have to call build object on something to create it but what do we call build object on well just like we just saw you call build object on a class or behavior and it links to there so it has access to all those methods that's you can see that arrow pointing over to it so we want to call our build object on this default behavior way up in the upper left the problem is we don't really have direct access to that we're not calling delegate on that default behavior we're calling delegate on the person but the person has a reference to that behavior so what we want to do all put together is we want to grab the default behavior from the person call build object on that to build a baby object and then set up the parent link and that methods hash
and so you can see from the code up here we do exactly that we get the behavior from the parent class we call build object on it and we get our new sub class the rest of the method is the easy part we set the parent class in the state we said an empty methods hash to the state so you don't have to worry about like lazy initialization or anything like that and then we return the new sub class and again that's what that looks like all put together there's a little edge case at the top of it don't worry about again we grab the perry-class behavior build an object from it get the subclass initialize it and then return it so we this has been pretty fast but we built our object structure and most of the methods we need we still need the send method so we can call methods by name but because we can call each of these things manually for now we actually have enough to set up the kernel of our object model so we'll do that when we're done it's gonna match this diagram we have our default behavior which is going to hold all of the default implementations of the methods that we just wrote and we have a root object class which you can think of like object and Ruby that all other classes in the system are going to ultimately inherit from so if you want something to be on all objects you would add it as a method on the root object class we'll build this step-by-step the first thing we need is a thing that we can start hooking all of our methods on that default behavior well create one by calling behavior delegate because this is going to set up that methods hash and the the parent link in this case we don't have a parent because there are no objects in the system to inherit from but we'll fix that later the next thing is this default behavior needs behavior right like you need to be able to add methods to it you need to be able to look up methods on it and so where is that gonna get its add method and look up methods from well if it's the thing that holds those and you follow those behavior arrows to figure out which object you need to you know where your methods are then you just cycle back around to itself so we'll do that by setting the default behavior that behavior equals default behavior I know next thing we'll do is we'll define the root of our object tree like I said this is kind of like Ruby's object class this one doesn't have a superclass it'll never have a superclass because it's where inheritance goes to die so we'll set its method to that so we pass nil again and then it'll need access to add and look up in all those other methods that were putting on the default behavior so will point over to that default one that we just created okay so we have a root object we have our links for default behavior we have our default behavior we can start cooking methods onto but there's still one thing missing I said we were gonna fix up that default behaviors parent thing later on so this is a good place to do it we want our default behavior to act like an object if we define in a method on object default behavior should be able to use it so this is pretty simple we'll just set it manually for now so this is actually all the code that we just saw for hooking up our object model it's like five lines of code we create our default behavior we set it to loop back to itself good object class pointing to our default behavior and then hook that parent link back up we're still missing those important methods though you know like add method lookup all that kind of stuff so here we're going to use add method to attach each of those to our default behavior so we have something that holds those default implementations to the system and that's pretty much it for setting up this object model this is how an example of how you might use this so imagine that you have a that you wanted to create a greeter class you could call delegate on the route object class that would point reader class's behavior to the default one it would point the parent link up to route object class and you have a class that acts like a class then if you wanted to add that hello method to greeter class you can call add method on it it's gonna find the add method implementation from its behavior it's going to add that method into its state you could call build object on greeter class to create a greeter which is going to then be able to use that hello method because again you just follow those behavior lines to figure out where your methods are and then you could set some state in your greeter object which could then be used by your hello method or any other methods that are defined on that greeter class remember it's all about what's shared and what's not and that's what drives a lot of this implementation state is unique so state exists on an object method implementations are shared and so that's why you find them through that behavior link because many objects can all use that behavior link to link to a single class or behavior but we still need to be able to call those methods you know you don't want to have to pass actual objects that you think all as methods you just want to be able to say hey I want to call a method named whatever so for that we need to define send send uses a helper method called find method up there which takes an object and a method name and it returns the right code to call then if it finds it it's going to call it's going to call it with the right arguments if it can't find it it's going to throw an error pretty simple all the complicated stuff is in fine method just kidding fine methods is also really easy it calls the lookup to find the right method and this is where you get your power because that lookup method it could do anything I mean you could append in a two to the end of all your methods before you find it and look them up that way I don't know why you would but you certainly couldn't but you might have noticed a problem with this fine method calls objects and objects and calls fine method which means that you have an infinite loop over here might be able to tell from that suspicious whitespace that there is a little bit more pad so if we know that we're going to call that default implementation of lookup well hard code it so in this case we say hey if this is the if we're trying to find a lookup method on the thing that informs the kernel of our object model just call the method manually that behavior lookup that we defined a few minutes back okay we're done with setup but before we try this out it'll help if you get a little bit more comfortable with each of these core methods so just to quickly review we have add method which adds about to do a class lookup which we'll find an implementation from a method name we have build object which like new it'll build an object from a class or behavior we have delegate which inherits from a class or behavior and we have send which calls a method by name on an object now let's try this out the first thing we'll do is we'll call delegate to subclass the route object this is like in Ruby doing the less than object when you're defining a class you can see this is a little bit the syntax is a little bit wonky because we're calling methods manually this is using object send to call the method by name that method it's calling is delegate and it's calling it on the route object class this is going to return a subclass of the road object class that greeter class the next thing we'll do is we'll add a method on to that class that'll print hello world all of our methods take at least one parameter which is the sender of the method you can think of that as a way to access like self and Ruby or this in JavaScript actually don't think of it as a way to access this in JavaScript because that's just gonna get confusing so think of it as self in Ruby that's how you get your object state so you can think of if you could access the object state off of that object parameter the next thing we'll do is we'll create a greeter object from the greeter class using that again object send to call a method by name it calls build object on the greeter class and that's going to return a new greeter object that has access to all the methods that that greeter class defines and then we'll call the hello method on the greeter object and we get our output so here's what we just did we subclass brut object to create a greeter class we added a Hello method to it we built an object from it and we called hello on that object we called hello it followed that behavior line to find the hello method on greeter class and I called the implementation and printed out our message this code looks terrible I know we did a lot of work to create an object model that looks a little bit more functional than it does object to eat we've dug ourselves into a pretty deep hole of awful awful syntax so how are we gonna get out of it well
dig our way out what could fix bad syntax except adding a whole lot more meta programming so we're gonna go straight to the method missing luckily it doesn't take much this looks big don't try to completely get it right now all this does is it walks through our objects ancestors looking for an object send method once it finds it it calls it passing our method name and arguments it's just a fancy way of turning a code like this into this much much much nicer code so instead now instead of calling object send call like reader hello we can just call greeter dot hello it's gonna make the rest of this much much easier finally we'll add object send to a route object so that all of our classes in the system have at least one that they can fall back to this might seem like cheating and it is but I figured the syntax is or the stuff is hard enough to understand without the syntax fighting you the whole way through now remember objects can have their own different state so let's try that out and let's write a method that accesses the object state to print out a different message depending on what kind of is in that object say we'll create a few objects Alice and Bob will give them names Alice and Bob and we'll call that new method hello name you can see hello name even though it's the same implementation reaches into the object state to print out different messages so now that we have this object model what kind of stuff can we do with it I mean you can define classes and add methods and C++ and that was invented like forever ago it seems like we've done a lot of work and just ended up making the same kind of stuff that we could always do a whole lot harder but remember we're trying to get out of this is flexible method dispatch so let's take a look at some interesting new models that we can build on top of our basic one what if you wanted to log all of your method calls to an object like every time you make a method call you want to print some information about that method call that's not that hard to do we can write a new look up method that uses the old look at method to find a method wraps it in some function that can do anything and then returns that function so that any method we call goes through that interceptor function on the way through a method that wraps another method you know we'll call that interceptor method it might look like this you pass it a method name a method implementation and some arguments it prints out some stuff and it calls the method as part of its implementation so that we do the work that we were planning to do now if you want to override a method on a class you subclass it and then override the method right it works the same way on a behavior if you want to override one of those core methods you can just subclass that default behavior add a method implementation and point the new behavior to it so now like I said if you follow those behavior lines you should be able to see that the person class and anything that comes from the person class is going to use that new lookup method I'm intercepting behavior to do our intercepting stuff before the method is called remember you just trace those lines so here's what this looks like in code first we'll use delegate to inherit from the default behavior to create our intercepting behavior and then any methods that we define on that intercepting behavior are going to override anything on that our default behavior for anything that points to that behavior this is our new lookup method again it's big so we'll take it in pieces first we need to be able to find our old lookup method so we need something that acts kind of like super so how do you find that old version well if sender is our person class like we're calling lookup on our person class you can once again just kind of like try to navigate that to find that lookup method on our default behavior up in the upper right over there so if we want the old version of that method that's centered up behavior to get to our intercepting behavior you go through the parent link to find the lookup method to find out its parent and it'll find it that way so that's what that code does you can see it grabs these super super behavior from center drop behavior about state parent it grabs the lookup method from that super behavior and then it calls that look at that old lookup method to grab our original implementation if we find a method we'll wrap it in a new interceptor function you define that function so you can do whatever you want in it you can you know log method calls or do something totally different then we passed some details like the method name the original method so we can call it and the arguments so we can call it and then we'll create a person class that will use that new behavior just like in Ruby our person class inherits from the route object class again this is like saying person like less than object next will manually point the person class to our new intercepting behavior this is kind of cool so take a look at what's happening here with a single line of code we've changed how method lookup works for anything created by that class you see like using the old method is the new method is the old method is the new method is the old method method so here's that logging function again same thing as before in the last line we make it the interceptor method for that class we'll define a few methods on this class name and location so we can test it out and then we'll create a person object using build object on the person class and call those two methods there's our logging now what happens if you reset the intercepting class's behavior back to the default one at this check it out vlogging goes off so it's not only you can change fundamental ways of how methods are found and called you can change it on the fly you can change it at runtime just by pointing to a different behavior one more quick intercepting example what if you have a method that sometimes randomly fails I mean I know nobody in this room has that problem but I hear of developers that have this problem and methods randomly failing sometimes so here's one that fails two-thirds of the time what if you could automatically retry this method until it succeeds here's an interceptor function that does just that it's going to try to call the method every time it returns false which will consider a failure it's going to sleep a little bit until the method succeeds what happens when you try it hey it works eventually okay now we're gonna move on to something completely different but before we do let's take a second to let
this intercepting method stuff drop out of our heads so that we're ready for the next one take a sec all right I'll good let's go last example we're gonna build multiple inheritance where a class can have more than one parent class if you can't find a method on your class it'll search all of the parents to be able to find a method implementation so let's draw this out again I always find it easiest to start with diagrams well start with this object in this example the very well named just an object this object has a class and it's this class that'll have multiple parents so how would you build something like that our class with multiple parents will look just like a normal class it still as the methods passionate state but instead of a parent at sort of a parent class it has a parent's array those parents could be anything they can be normal classes or interceptor classes or basically whatever but in order to get those multiple parents we need to be able to add parents to that parent list so where's it going to get that I mean when we we said that a you know any of these objects are going to be able to get their methods from their behavior but there's no add parent behavior except for that suspicious-looking blank space in the lower right hand corner which I'm going to fill so since methods come from a behavior we need a behavior that can do two things we needed to be able to add a parent to that class we need a way to be able to look up a method for all parents in that class which our original implementation doesn't do so we'll write it add parent method and will override the lookup method with a new one once again you subclass the default behavior to get your new one and then we'll write the add parent method this one looks big but that whole first section there is just for initializing it if we don't already have a parents of rain at the end it appends the new parent to that parents array so you'll end up with your original Parent PLUS a new one and then any time you call this afterwards you're just going to end up appending that new one to the end of the array and now here's the new look up method this is almost exactly the same as our original one with just one change instead of looking up methods in a single parent it's going to loop through all the parents and it's gonna break when it finds the first one so let's try this out here's two normal classes of person class and a greeter class nothing special about them they just inherit from our route object the same as anything else would and then we're going to define name on the person class and greeting on the greeter class and here's a class up the code at the top that inherits from both person and greeter to get that add parrot method at the end there we need to we need to point the behavior to the new one otherwise that method isn't going to exist so this inherits from the person class and then it adds the greeter class as a second parent to the social person class and now if we try it out it fails just kidding the it gets both the name and the greeting method from both of its parents so it gets the name method from the person method and the ancestor and the greeting method from the reader ancestor so this is a lot of flexibility we built three different styles of objects basic single inheritance two kinds of method interception and multiple inheritance and it all came from a class and five methods lookup add method build object delegate and send and our little tiny object and each piece of it is simple enough that you could build it in almost any language from sea all the way to review but ruby is also a really flexible language I mean you could write a lot of these examples straight in Ruby using things like modules and method missing and basic objects so what's the difference between this object model and Ruby's I see it as intent just like how Ruby makes metaprogramming a normal thing to do this object model that makes changing things at a deeper level a totally normal thing to do and even though all of this eventually becomes a bunch of binary code running on a processor on our machines the language you use and what's normal inside it it changes your brain it makes some things more natural and other things more difficult that's why I love playing like this you know that's why I love learning new languages even if they don't stick with me these experiments they hope you think in a totally different way you try on a new way to see your code and you keep what works and you drop what doesn't and so after these examples as I could see some of you looking at me like why like why would you do something like this it's
that how many of you learn best when you break something you know when you test the boundary when you're not sure that it's gonna work when you're pretty sure that it's not going to work I strongly
believe that the best way to understand the system is to test it to push it to break it and metaprogramming is a fantastic way to break all of the systems that you depend on when you push the boundaries you you'll be more confident with a language you'll understand at a deeper level how it all works so try writing code that might seem weird or irrational because who knows you'll probably learn something new and at the very least at least you'll have a good story to tell it could be a mess of metaprogramming spaghetti code that would generate active record models on the fly based on entries in it config file that was a bad idea don't do that but it could be an entire object model built from five methods in a class that helps you understand how object-oriented programming actually works and when you learn something like that when you learn a tool that you can use to investigate more tools like that's a platform you can use to learn new things by building them like building multiple inheritance or building prototype object cloning or building pattern matching and when that happens not only do you learn new stuff but you also increase your rate of learning new stuff and I really can't think of any better ways to become a better developer so what I'm asking of you is to give this a try you know take a look at the sample code that I'm about to give you and try to understand it not not by reading but by playing with it by trying to may be re-implemented these examples or take it a step further or build something totally new and if you're anything like me as I was several times when putting this together you're gonna fail miserably a few times I feel way more than a few times but eventually it'll click and you'll get it and when you done you'll understand a lot more about metaprogramming cycling classes like these deep levels of object models that you never understood before and so if you want to get in touch about that or I want to talk programming or really anything else I would love to talk with you my email address is up there use it I read in respond to everything and then if you're ever in Seattle let me know I would love to grab a coffee with you in chat programming i'm also on twitter at justin weiss where i share programming and other tech related articles and that last link points to a list of resources for this talk it's an important one you can think of it as like the show notes it has a just for the sample code with some stuff i couldn't fit in like prototype object cloning and it also includes like the slides for the talk and some other articles that are kind of in the same vein and i know i have some time i think about ten minutes so i'm happy to answer any questions or go deeper into any of this stuff as you're interested yeah I the first time I thought about
this so the question was have I thought about using things like define method and method missing to try to override Ruby's method implementation with something more flexible like this right and when I first read the paper I was so fascinated by this but that I decided that I was going to try that and then I had second thoughts when I realized just how awful the performance is likely going to be if it's not built into the language mm-hm so the question was how do other languages compare with Ruby and meta programmability there's there's a huge spectrum and it's also hard to tell because it's not until you really start to get deep into a language that you really start to make use of that like for instance I like my language for this year is elixir and elixir has a lot of heavy macro support which can be used for some really interesting meta programming stuff but I haven't got to a point where I've been using it enough to really be able to have a solid opinion on it definitely by I think the most meta programming ish languages that I've run into recently have been arriving over the over those years have been surprisingly objective-c I actually tweet this talk using some of that and and Lisp but yeah those are probably the two biggest all right well thank you once again for the time
Loading...
Feedback
hidden