 Hi, I'm Stuart Halloway and we're going to talk about the Clojure programming language. I'd like to start by talking about a few assumptions that I've made about the Ruby community over time that I found to be true. The first assumption that this talk makes is that this is a pretty smart crowd. And I found that certainly to be true in my experience as a Ruby programmer. The second assumption that I'm going to make is that I do not have to assuage fears. A lot of places that I go and talk about Clojure, the reaction I get is, ooh, I'm scared of the X, where X might be parentheses, or Lisp, or Java, or whatever. I don't think of the Ruby community as a group of people who are in general afraid. In fact, it's almost the opposite, right? I could come in here and say, I've got a technology that's scary and you can't handle it. And you go, I've got to go run off and do that right now. So the third assumption that I'm going to make is that I don't have to convince you that learning a new language every year is a good idea, regardless of whether you're going to put it into immediate practice. And so I have a very explicit agenda here. There are a lot of cool languages floating around out there. And some of you are probably going into the holiday season thinking, you know, what am I going to learn during my break? What am I going to learn over the holidays as my sort of language for 2010? And I'm going to give you seven reasons to think about why that language ought to be Clojure. So before we do that, we're going to talk a little bit about syntax just to give you exactly enough Clojure that you can read and follow along. Clojure is built out of data literals. We have lists, link lists, they're inside parentheses. We have vectors, an index collection, which are inside square brackets. We have maps, which are curly braces. Often it is the case that maps are going to be keyed by keywords, which are preceded by a colon. And we have sets, which are curly braces and have a pound in front. You may or may not see commas in idiomatic Clojure code. Clojure has commas as white space. So if you want to have commas in your vectors, knock yourself out. Now, that's the data. What about the code? Well, as a list, Clojure is a homo-iconic language. I said homo. And as such, code is just data. So if you want to make a function call in a language like Clojure, it's just function call and then some arguments inside of a list. Operators are also just data. And notice that we have prefix notation so that operators sit in function position. So I say plus 1, 2 instead of 1, plus 2. But really, everything is just data. If I want to define a function, and I'm going to go ahead and use the laser pointer. I know that's not the best for people who are watching on video, but you should have come to RubyConf. And I'm going to use this one. And I have with apologies to folks over there. I can't point to both at once. So function definitions, you define a function. You give a function a name. You give it a documentation string. And it's argument list, which is again just data, a vector. And then the body, the implementation, is just lists. So again, all just data. And this return value here says that I've actually defined hello in the user namespace. Users, the scratchpad namespace just for trying things out. Control flow is just data. It's a list that happens to have some control flow element as its first item. And then variable semantics. And so if is a special form that says, if hell freezes over, then we'll skate. Otherwise, we'll roast. Java interop is just data. So this says, I want to take stupid. And I want to run that through substring 0, 3. And then I want to run that through to uppercase. This dot dot form just says dot this thing, and then dot that thing, and then dot the next thing. So that's using a macro to sort of thread that form through. Couple of nice things here just for the list fearful. Using macros like this allows things to read from left to right or from top to down instead of the inside out that you get with a list. Error handling is just data. So it's just a list that has a try as its first form and some stuff that might fail and then catch. Namespace is an import. This is a fairly elaborate set of namespaces and imports. We don't have to go through the details of this. But namespaces and imports and managing names is all just done with data. So really, the entire language is just made out of data in the language. That's what homo-iconic means. There's a bunch of one-to-one mappings between Java stuff and Clojure stuff. I'm not going to go through all of this today. The slides are online, so you can go and look through that. The important point to take away, though, is that Clojure is very cozy with Java. We're very close to Java, and we're sitting very close to the JVM. Here is a point at which I'm going to take advantage of your rubiness and the trust that I want to build in this room and say there are a bunch of benefits to homo-iconic syntax. Normally, I would spend time saying, don't be scared of the parentheses. And in two or three years, you'll get to learn why they're cool. Instead, I'm going to say here, don't be scared of the parentheses. The parentheses give you the homo-iconic syntax, and the homo-iconic syntax simplifies metaprogramming. And we can't talk about all the details of how that works in the time that I have today, but I know that I can say, ooh, metaprogramming easy, and that's going to turn on a Ruby audience. Everybody's now sexually aroused, so it's all good. A real quick example of how this looks, just putting together an actual tiny program. I have a piece of data, which is a group of lunch companions that went out for lunch. It's a list of maps, so it's some people's names. And you might say, well, I want to be able to find out somebody's name. So you might write something like a getter function. I'm going to define the function last name of some object where I say get x last name. This is horrible, hideous, non-idiomatic closure. So just anyone who knows a little closure, just pretend like you didn't see that. But now that I've defined that last name function, I could say, sort by first name or last name, the lunch companions. So this notion of passing functions around as first class citizens, which in the Ruby world we're used to. We have blocks, so functions are first class citizens as long as you don't need two of them. So then you could say, I want to sort by an anonymous function. So this is one anonymous function form that Clojure provides. It's just a list, that function of n that says get in the first name out of n. Or I could take a more terse form. So this is a sort of syntactic shortcut for the same thing. So I want to write that anonymous function of some argument which is named percent. As with Ruby, we love the pearl. We reach out every once in a while, there's some punctuation characters in there. So this also says sort those lunch companions by their first name. However, given that we are in a functional language in Clojure, we don't have to be stuck with this notion of getting something out of a piece of data. What is the difference at the end of the day between a map, a piece of data, and a function that looks things up? There's no difference at all. So we'll just put the piece of data, the map, in function position. Throw away the get. There's no need to say get. A map is a function which looks things up. And as long as we're gonna be cute about it, we'll also say that a keyword is a function that looks things up. So you can just turn that around. You can say take a map and pass a keyword to it or you can take a keyword and pass a map to it. Of course, once you've said that, you're in the end game. And what would be idiomatic Clojure? Sort by that function which looks up first name which happens to be just the keyword first name. Now, for those people who are going to come away from this talk enthused and look into this further, here's a homework problem. Think about how this is accomplished in idiomatic Ruby. And think about the differences in how, because Ruby, you do something very similar to this, right? We do a trick that allows us to pass keys around as functions. And that difference gets at a lot of the philosophical differences between Lisbon and Ruby. Both Lisbon and Ruby have this very desirable property which is that good implementations have a one to one ratio of pseudocode to code. I can sit down and write my idea in pseudocode and then I can translate it into code and the language is flexible enough that I don't get stuck. I don't find myself going, oh well I said it in one line but I've gotta write it in 17 lines and fill out the department of redundancy in triplicate department form to make the code work. Also, those of you who can see down at the bottom, I'm really tired of being mistweeted. So any slide that has the little Tweety Bird icon down at the bottom, that's the exact texture supposed to tweet. So don't screw it up and say it wrong because then people get mad at me and it's just awkward. So here we are, we have a language that has terceness, concision, expressiveness, right? We have that already if we're in the Ruby world. Now we're gonna look at seven reasons why you might want to play with Clojure in 2010. The first one is the sequence library. So we have this notion in Clojure of a sequence and a sequence is an abstraction over data that to a first blush looks like lists, right? So a sequence is that which supports first rest and construct, right? I can get the first thing out of this collection, I can get the rest of a collection, I can construct. On top of this abstraction, you build recursively in with little helper functions, all kinds of other abstractions. So like take two, that's a recursion over first or drop two, right, a recursion over next or rest. And on top of that you build all kinds of stuff, again stuff that you're used to in the Ruby world. So you have range and filter and map and reduce and all the kinds of function to function type stuff. And you can do things like sorting and sorting by. And then we get to a slightly more interesting one. We have this notion of conge, conjoin and into. Conjoin and into are data structure specific. So they're not just about the sequence library. And these guys say, I'm going to build up a collection in that form which is most appropriate for that collection. So if I conjoin on top of a list, things get added at the front. If I conjoin onto a vector, things get added at the end. And the benefit of this is that you can write extremely data structure neutral abstractions as a first cut when you're implementing things, right? That may not be the fastest approach, it may not be what you land on if you're in a performance sensitive environment. But from the beginning, you can just say, I'm going to take a very neutral approach to data and worry about the complexities when they get there. Now, all of these data structures that I've shown you so far are immutable. I'm going to come back to that. But one implication of that right now is that all of these sequences can be treated lazily and can be infinite. So I can define using this function, iterate the whole numbers. Iterate Ink 0 takes a seed data and then a function that gets repetitively applied to that piece of data and returns an infinite collection. What this does is it takes algorithms that you end up implementing on a very small cached per collection basis and generalizes them for you for free. It also lets you write code, not really knowing how many things it's going to process, right? People who consume code, right? The very final end consumer of a set of libraries gets to say, oh, I want this many because that's how much memory I have. Now, of course, I need to be careful. I don't want to look at all the whole numbers at once. It'll make you go blind, right? So don't do that. I don't want to look at them all at once and there's settings for dealing with that. And then there's a whole set of sequence library functions that deal with these infinite collections. This is a lot of fun to play with and it has surprising implications, right? All the math folks are excited already. Ooh, I get to play with an infinite collection. But it turns out to be useful in real world business development settings as well. One other sort of oddball bit of syntax that I want to show you here, or oddball bit of API, is the get in, associate in, and update in functions, the ends. What these do is let you drill into a nested collection. And so here I've got John Doe, his name is John Doe, but his address is actually a nested map with a zip and various other things. I can say get in, John Doe, address and zip. So that drills in through the address and then drills in through the zip. And I can say associate in, John Doe, through the address and zip. So I can update. And obviously I'm returning a new John Doe, right? Because these are immutable data structures. Or I can update in and pass in a function. That's a stupid example, right? It's very unlikely that the postal service is gonna modify zip codes by incrementing, right? You might split a zone or something like that. But it gives the idea of what these functions do. This allows a style of programming, which is controversial every time I describe it. And it's not required in Clojure, but I had a lot of fun playing with it. And that is treating your data as your contract. I'm gonna treat my data structures as the primary contract of my application. Not interfaces, not duck types, but the data itself. And then I'm gonna reach into it, possibly deeply nested ways and play around with it. There are potential downsides to this. But if you haven't ever tried this with immutable data, I would encourage you to give it a try. Try to solve a problem this way, see what it's like maintaining that code over time. And to summarize what the sequence library gives you, it gives you an approach that relies on very few nouns, really one noun, right? The sequence abstraction, or as we like to say in the dark speech, right? One thing to rule them all, one ring thing to find them, one thing to bring them all in the darkness behind them. So the second thing I wanna talk about is how these data structures are implemented under their covers. Because immutable is great, right? We all know that immutable is cool, right? If I have a piece of immutable data, it has this really desirable property that it doesn't sneak away and become something else when I'm not looking at it. But it's not very efficient as it would be naively implemented. And Clojure's persistent data structures are immutable, but they also maintain the performance guarantees and full fidelity old versions of data. So I can build a address book with a million items in it, and then I can say give me a new address book which looks just like that one, but with these 10 items subtracted and these five items added. And I don't get this incredible memory explosion, right? When I copy, I copy the entire collection. The collections share structure. This is easy to understand with a linked list, right? I have a list of my favorite animals, turn, rabbit, tiger. Another user comes along, they have a list of their favorite animals and they add mute. And they can share data with me, right? We don't have to do a whole bunch of extra memory allocation. And remember, they're all immutable. So there's no danger that I'm gonna change my mind about which are my favorite animals. Or if I wanna change my mind, we'll deal with that in a different way. We'll see that in a minute. Now, this is great for lists, but what about maps? Well, it turns out that you can implement the contract of a map or a set using a bit partition tree. And that's what Clojure does. And with a bit partition tree, now we have, well, we said we have the performance guarantees of the collections we're used to. Well, that's not quite true, right? If we have a bit partition tree, then we're gonna end up, as a picture I drew there, log two of n, right? And normally, what do we want for hash lookup? Constant, right? We want constant for hash lookup. So log two of n, I kind of tricked you. Well, it turns out that log two of n kind of sucks, but of course, we don't have to branch our tree with a factor of two. And so all of Clojure's data structures branch with a factor of 32. And so, second tweetable moment, Clojure is cool because log 32 of n is fast enough, right? That is fast enough for the stuff that we build. You know, I was never good at the academic computer science part in college, and you're doing all the deep math about that stuff. I was much more about getting stuff done. And it turns out that that's not a constant factor, but for the sizes of data you can deal with in memory, it's close enough, right? It is a little bit slower to use these collections, but you get a ton of benefits out of using them. So, third reason, and this is probably the most singular thing about Clojure. Third reason to play with Clojure is its approach to values, identity, and state. Object-oriented programming is incoherent. We have identities that point to something, but it might be mutable or it might be immutable. It might be primitive and atomic or it might be composite. If it's composite, its pieces might be mutable or they might be immutable. And that turns out to get you into all kinds of trouble when threads come along. And then we have this other thing, which is really just a band-aid for the fact that we got this wrong, which is locks. And that's the way we work today. And the problem is that when you build systems this way, and this is pretty much everything we're building in most places in the world today, that mutable objects do not compose, right? Mutation cross-cuts your interface contract. And that's a deep problem. And so if I have an interface in a language like Java, and I say, you know, this is how it works, that interface doesn't tell me whether things are mutable or not, whether they can slide out from under me or not. It doesn't tell me what their locking semantics are, which means that I can replace one implementation with another that's interface compatible and passes our wonderful unit test suite written in some excellent framework R-spec or something beautiful and wonderful. It still doesn't work. And duck typing doesn't help, right? Duck typing doesn't solve this problem. Deadlocks like a duck and corrupts like a duck are not particularly useful outcomes, right? So this issue cuts across the whole static versus dynamic typing debate. Mutable objects don't compose. With mutable objects, you have to have coordination even for reads. Those of you who come from a Java background, the double-checked locking is broken problem, is a symptom of trying to wrestle with why do we have to coordinate reads? There's no general way to be lazy or cached with mutable objects because I can't do anything lazy or caching with an object that might change when I'm not looking at it. And this is all kinds of performance optimization strategies that go away. And, and this is really bad, reading code becomes a recursive exercise in speculation, right? It's like I'm gonna look at some code and decide if it works or not. It's like well, but that depends on that. But that could be mutable. I can't even tell from the damn duck contract or interface contract whether it is mutable. And that depends on this and that depends on this. And you have to do this recursive speculation to decide what code does. Now, maybe you don't believe this yet. So let me pose a challenge. What would reuse look like if mutable objects composed well? And what would be the outcome if they didn't, right? If they compose well, well reuse will just be objects, right? That's the bloody point. But if they don't compose well, then we end up with, and this is a mouthful, domain limited frameworks and plugins with constrained non-language semantics for state, right? In other words, the way we deal with state and mutation and concurrency doesn't work at the language level. So we're gonna write frameworks, web frameworks or messaging frameworks or whatever. And when you use those frameworks, you have to use a framework. You can't just do libraries. And inside those frameworks, you have constrained concurrency semantics that are not the languages semantics and you're not even allowed to use the language's tools for concurrency, right? It should be kind of a smell, right? An architecture smell that every framework we build says don't use the concurrency primitives that are built into the actual language, right? We should just go do something else. And I think that as this changes, then we'll see less dominance. There's other purposes to frameworks and plugins, but we'll see less dominance of frameworks and plugins and more dominance of libraries. Clojure's approach to this is that values are values. They don't slide out from under you and identities represent things that can change over time. So a value's immutable data and identity is a series of causally related values over time. I'm stew at time t. I'm stew at time t plus one, right? If you actually viewed that as a physicist would, right? Time can be played forwards or backwards. You could actually go back and look at the immutable me at earlier points on the timeline. And these identity types are managed by a set of different reference types that have different semantics. I know I'm not gonna go through this table right now because this leads into the next thing. How does this work from an API perspective, right? That all sounds, maybe that sounds cool. Maybe it doesn't, right? If it sounds cool to you, okay, great. Maybe it works, but what happens if the API is too hard to use, right? So let's take a look at what it's like from an API perspective. I wanna create a thread safe chat app. And I'm not gonna do the view in the controller here. This is a chat application where you can go in and create chat messages and add them. So first we're gonna have a reference that points to the initial state of the chat app, which is there are no messages, empty list. Then I can reach into the messages and see them, DRF messages, or at is syntactic shortcut for DRF messages. Tell me the current state of messages. This operation does not require coordination or locking to work, right? A thousand readers on a thousand threads can all look at this without interrupting things that are going on. If you wanna do an update, there's this function called alter. Alter takes a reference to some immutable data, applies an update function with some arcs. So reference at some point in time t points to the current value. And then we apply the update function to the old value with the arcs. And this apply has semantics that vary depending on the concurrency type you're gonna use. So using the one we're using, software transactional memory, I actually have to put this alter inside of a doosync. A doosync scopes a transaction. If I try to alter the messages outside of a transaction, boom, exception, right? You're not allowed to do mutable stuff without following the rules. All mutation in Clojure is constrained in that way. And every time you do something that's mutable, it's gonna be very clear in the API what it's doing and what its semantics are. It's not a big effing mystery, right? Where you look at a piece of code and go, well, I don't know what happens when I change this. Maybe something changes, maybe something doesn't. So the unified update model is updated by function application. Readers don't coordinate, readers don't block, writers don't block readers. And then there are some additional semantics that depend on the reference type, right? If the reference type does coordination across multiple references, then you also get automatic retry behind the scenes, right? So three references, and this is very much like database concurrency, right? If I try to do two different things to the database at once, the database makes it right, right? By letting one of them go and letting the other go. Clojure semantics for that are all automatic, so there's no, I couldn't do it, I fail. It's one of them we'll get to go through first and the other one not. So a sane approach to state permits coordination but is not required, right? We can do coordination, like with the transactions, but we don't have to have coordination and people can come along and read if they want to without having to mess around. And this unified update model has different function names but it applies across all the different reference types that Clojure provides. So we just looked at refs, we are now going to extraordinarily quickly look at the others. Now atoms allow you to do atomic updates. So I have one thing that doesn't ever need to coordinate with anything else. There's an application, you can go and download the slides and take a look at this, this is a cellular automaton like Conway's Game of Life. The only interesting thing that I want to point out is that the entire application is 100 lines of code and the mutable state's exactly this one line right here. Boom. How many of you do test-driven or behavior-driven development? All right, how many of you really do? About the same number of hands stayed up. What does it mean from a testing perspective when only one line of code in a hundred in your application actually deals with state, right? Those other lines of code are really easy to test. Functions are extremely easy to reason about and test. A third concurrency construct agents are fire and forget this gets updated on another thread. So in this case, I send off to an agent some function and then at some point in the future on a thread pool, the update happens. Again, it's well-defined concurrency semantics. Agents are not actors. So those of you who are doing Erlang or Scala or whatever, I don't have time to explain that right now, come talk to me afterwards. They're very different but they have the sort of asynchronous thing going. And then vars, the fourth current reference type encloser, actually there's a couple more. The fourth that I'm gonna talk about today. Vars are the things that we actually build our programs out of, right? The top-level things like data and functions. And vars have semantics for rebinding and let me just say here there be dragons and here there be nothing new. So I'm not gonna talk about it from a Ruby perspective, right? We can rebind variables and that allows us to do aspect-oriented programming. It allows us to do mock objects really easily. It also really cuts against the grain of doing immutable, lazy, blah, blah, blah. Because rebinding is like changing things when you're not looking, right? So, and I guess the point I would make here is that like Ruby, Clojure is a sort of mutual consenting adults kind of language, right? There's powerful constructs in here and if you need to do this, you know what you're doing. Don't come whining to me when you break your lazy code because you rebound stuff, right? We're not gonna build in protection for that kind of stuff. The fifth thing that Clojure provides is multi-methods. This is actually really easy to understand. It's a generalization of polymorphism, right? Polymorphism, if you think about it, is, you know, I wanna say square.draw or circle.draw. And I think probably a lot of us were introduced to polymorphism with exactly these kinds of, you know, drawing shapes on a canvas kinds of examples. And the idea here is that polymorphism is this magic black box that decides which actual implementation to call based on the type of the argument. But if you're a functional programmer, you say, well, that black box is really just a function, right? It's a function that says, tell me the class of this and make decisions based on that. Well, that P could really be any function, right? It's not special, right? It's really some function of all the arguments, and this one still happens to just implement simple polymorphism. But I could, if I wanted to, make my dispatch function a function of two arguments. And so now I'm gonna dispatch on the square for canvas and the square for surface differently. Anyone ever done this in Ruby? Right, there are libraries to do this in Ruby, but it's not, you know, idiomatic out of the gate. Or I can look at the same object, same argument twice. I can dispatch twice on the same argument. I wanna look at your type, and then I wanna look at your opacity. There's a ton of interesting stuff here that I can't get into today, but basically the capital summary of it is that you can discover types after objects are created. You can decide as a programmer when you're assembling things what the types are via the dispatch function instead of saying, oh, this thing doesn't match my contract until I need an adapter of some kind to put on top of it. Here's a very simple example, a coerce function that has some piece of data that we wanna convert to some destination class. And so we wanna dispatch both on what it is now and what we're trying to take it to. And then you can do things like, well, if I'm trying to coerce a string to a file, I just wrap it in a file, or if I'm trying to coerce a string to a boolean, well, strings are boolean true if on, yes, or true is true. And this is a particularly useful one. This one actually was written as a wrapper for a patching ant, where things come in as string values. But even if you're not in the hell of Java and XML, you still have the problem of user input doesn't actually come in the form true and false. It comes in other forms. So this kind of thing is useful more generally. The multi-method has a lot of other stuff that I'm not gonna show, including defaults. So the default behavior of multi-method is I just try to cast the object to that class. I turn around and leverage old school OO. So to summarize dispatch, all the languages that I work in regularly support basic polymorphism. Ruby is a lot more dynamic. You can change methods at runtime. You can change types at runtime. And then Clojure is more dynamic still. You can dispatch on all the arguments or on arbitrary functions. Ruby can actually do that too, if you're willing to pull in third-party libraries. And then neither Ruby or Clojure out of the box does pattern matching, but that's also possible with third-party libraries. So this is a piece of goodness that you might go play with Clojure and say, hey, that's cool. And then turn around and start using it in your Ruby code. You could actually do all of this stuff in Ruby code. Dispatch workarounds are the middle managers of the design patterns world. All of that stuff we just saw, if you're building good old-fashioned noun-oriented programs, you end up with 17 classes to represent one domain object. You have the person and the person DAO and the person DTO and the person factory. And I know you're all laughing because that's Java, but that happens in Ruby too. You end up with multiple nouns to wrap existing things. And we solve that problem in a different place in Clojure. We solve it in a dispatch function. So we solve that problem with a verb, not with a noun. And that's often the case in Clojure. The first approximation, what's gonna be different here? Problems that you solve with nouns, you're now gonna solve with verbs. Macros. So any of you who have read Paul Graham know that you really wanna have macros, but you're not exactly sure why. So consider a form like if. If is a special form. It has semantics that are not normal for the language. It has semantics that in either Clojure or Ruby, you can't trivially duplicate with a function. Because what do functions do? Functions evaluate all their arguments and then pass them to the function. Well if we evaluated all the arguments to if and then pass them to the function, we would go down the then branch, go down the else branch, and then check to see which one we should have gone down. Which doesn't really do you a lot of good. And so things that are like if can't be functions. Function calls evaluate the args, pass the args the implementation. If evaluates an arg and then decides what to do with the function arguments. And the list approach, or one list approach to dealing with this is macros. So a macro is syntactically like a function, but it's a function that processes source code and emits more source code. Again, metaprogramming. I probably shouldn't show these next five or six slides at all. I should probably say metaprogramming woo woo. And you'll all just go play with it. But you can do things like define a macro called when, which has different conditional control flow semantics than if, and then this implementation converts this source code at read time, or at macro expand time to that source code. This is an extremely powerful style of metaprogramming and is not easily available to you outside of a Lisp. And in fact, I am gonna skip a bunch of these slides. So nya nya, you wanna learn more about macros. It's a good idea, but not today. The seventh reason that you should consider Clojure is its approach to metadata. Metadata has a specific definition in Clojure, an operational definition, which is it's data that does not contribute to identity or equality semantics of the object. But it also has a practical use, right? It's data that's orthogonal to the value of an object. So you use metadata for things like documentation, serialization, protection scopes, if you've got this antiquated notion of public-private protected. You could use it to mark concurrency semantics. You could use it for optimizations. You could use it for relationships. If you were building a testing framework, you could associate tests with test Cs. You can even use metadata as a grouping or typing mechanism separate from traditional inheritance. I put a question mark beside that because there are some dragons there. Syntactically, this is super easy in Clojure. I can say, here's a piece of data, secret true, I'm sorry, here's a piece of data, password swordfish. And I also wanna make it known that that's a secret. So x now points to a piece of data, password swordfish, that is known to be secret. And then you can say meta x and find out that that data is secret. And you can use this for anything you like. We can't really go down the roads of design with this. But this is a general purpose tool that you can add metadata that rides along with your data. There's syntactic sugar for it. Again, that's sugar if you love pearl. So pound carrot says add metadata. So this says add that metadata here. And then carrot says pull the metadata off. So that, you can tell whenever there's a one character shortcut for something that the language designer wants you to do it. So getting metadata off of things is considered an interesting idea. There are some subtleties to metadata. It can be on the data or on the var, right? On that thing which points to the data. So I was just adding to the data itself, but I could also do this. I could also say I'm gonna define and now this says add the metadata to the symbol not to the data itself. And now if I look at Z's data, well it's no metadata on the data anymore. We actually placed it on the var. And I can also get it back off. So I can say pull off var quote Z and then get the metadata off of it. And notice that there's all this metadata that I didn't put on there. So Clojure uses, right? It dogfoods itself in this sense. Clojure uses metadata for all of its documentation, debugging, all that kind of stuff. Internally, you can go and find out. And if I had done this somewhere besides at the interactive shell, this would be the name of the file that this came from. And there's actually a ton of other metadata that might be added here. So Clojure puts metadata in for you and then you can add metadata yourself. There's one particular use of metadata that I want to call to your attention and that's type information. This is a function called capitalize. And what capitalize does is it upcases the first character of a string and lower cases the rest. This is not idiomatic Clojure, so don't laugh and go, I could do that in one line in Ruby. I can do it in one line in Clojure too. I'm doing this for a particular reason. And the thing that's cool about this is in Clojure you can turn on a worn on reflection flag. And when you turn on the worn on reflection flag, as it reads your code it says, you haven't told me enough, right? We're a dynamically typed language. You haven't told me enough to call these Java things non-reflectively. So they're gonna be called reflectively which as we all know is slow. Now we're a Ruby crowd so we don't really care about slow. But imagine that you did care about slow. Then you could go back in and add metadata to things and now Clojure detects this metadata and now the calls become non-reflective. And so if your performance problem in a Clojure program you'd be very careful with how I say this because when you make blanket statements about performance really nerdy people pop up out of the woodwork. If your performance problem in a Clojure program is caused by the overhead of reflective invocation you can generally get rid of it by going to your hotspots and adding this metadata and worn on reflection makes it easy to do that. And then once you've done that you could also refactor and make it somewhat more idiomatic and then the warnings would tell you hey as long as this new little helper here substring is itself non-reflective then the whole thing will be non-reflective. It turns out that I had an embarrassing moment, subs is not non-reflective so we need to actually submit a patch to make that the case. But nevertheless. So we've talked about seven reasons that Clojure is an excellent candidate for language to play around with in 2010. We've talked about lazy sequences, we've talked about persistent immutable data structures, we've talked about a concurrency model that's sane, the unified update model and then we've talked about some more traditional Lispy stuff which is cooler dispatch and generalization of polymorphism and macros and metadata. All that's really cool. Let me just say parenthetically, if you don't choose Clojure still learn a new language next year. I'll throw out my alternate favorites. If you're not gonna learn Clojure I would say learn Erlang or Haskell or Ioki. Those are the others that really seem to pop to me and again none of this is about getting shit done at your day job. This is all for the love. So understand that. And with that I wanna talk about love, sex and friendship. So there's a lot in common. There's a lot of reason that Ruby has have been going to Clojure and it has to do with this. Ruby and Clojure are both built for love. Matt's is about love, Rich Hickey is about love. The language benevolent dictator built something that he wanted and wanted to play with and built something that he wanted to play with both for academic and for practical purposes. A second important similarity is that Ruby and Clojure are both consenting adults kind of languages. They're not languages that say the language designer is gonna protect you from immoderate or immoral behavior. It's up to you to decide what's immoderate or immoral behavior and be responsible. And finally both of these languages have a community that's about friendship. If you're here you know that's true about Ruby. The Clojure community is smaller than the Ruby community right now but it has a very similar feel to me in terms of the friendliness of the community and people being willing to reach out and help others in the mailing list and the language creator hangs out on IRC and answers questions and it's just awesome. So the social aspect of being a Clojurean or whatever word we're gonna land on has been entirely fun. At the same time, love and sex and friendship all are better with variety. So the variety points, well let's start at the bottom and work up. I think of the reasons that Ruby is a language that lets you paint yourself out of any corner you would paint yourself into. And I don't wanna use any language that doesn't have that property. And the way that Ruby lets you paint yourself out of corners includes things like tasteful hooks. Anywhere you hit a problem that you need a hook Matz has probably already thought of it and there's a hook there. So there's all kinds of tasteful hooks within the language that let you do things. And flexible punctuation is important if you're writing DSLs, right? Those people who use active record. You appreciate that punctuations make this look like a declarative list. Lists have a different approach to the same problem, right? Instead of flexible punctuation, we're gonna have really rigid but almost non-existent syntax, right? Which allows you to do really easy metaprogramming with macros. I'm not gonna put a stake in the ground that one of these is better than the other. They're both really different and I'm really glad to feel reasonably facile with both of them and it helps me solve problems to be able to go back and forth between those ways of thinking. This is a little bit more of an important difference. Ruby is all about open classes and open instances. You can always decide that an object looks different. I'm gonna add this or take this off or put something into the inheritance hierarchy or whatever. Closure's not that, right? Because we don't really think about classes or instances. We just think in terms of data. And so copying is cheap and instead of opening things up and doing things to them, we just make new things out of old things and the new things have new stuff on them. So that's a different approach and we have efficient structures that allow that to work and then multi-methods give us kind of open functions which are actually more open than classes or instances. And then this is really where the rubber meets the road. The one killer thing. If Rich Hickey and people who are thinking like he are correct, then five years from now or 10 years from now, immutable data and the unified update model will be standard in all mainstream programming languages. And this is the reason that it's important to be learning Closure right now. I think he's right. I didn't learn Closure for this reason. I didn't really know a lot about functional programming when I started actually. I didn't learn it for this reason. I learned it for, I came for the Lisp, right? And I stayed for the functional. So that's a super important piece and this is a reason why I think Closure really deserves to be at the top of the list. Of course it's possible that we're wrong, but I don't think so. And with that, I have managed time such that I'm gonna take one or two questions if we can. Yes. So, I'm gonna say a Stuart Hallway talk is always sort of like a collage from a fire hose. Yeah. But I wanna respond to the point about multi-methods. And I think the multi-methods and generic functions are very powerful and very flexible, but sometimes you don't want that kind of power and flexibility. It's very hard to manage. For instance, who wants a car with four wheel independent steering? You'd never be able to drive it. And I think that multi-methods and generic functions are one of the reasons why CommonList is sort of, what it is today. It's a, so I don't wanna engage in a big debate, but I do wanna put it out there that there's not a uniform acceptance of that as a good way to approach program design. It's a good point. So the observation repeated through the microphone was that, let me summarize unfairly. Maybe multi-methods are too dangerous even for us. And a couple of data points about that. One is that multi-methods are, in my mind, tastefully done in terms of the complexity that they add. So they don't add a lot of mental model about how to, you know, diamond inheritance problems and things like that there. They have some tasteful decisions within them that make them, I think, simpler than what CommonList does. The second thing is, nothing forces you to use multi-methods, right? I mean, the most smug answer would be to say, yes, now I only have six really compelling reasons, right? They should go and go and look at Clojure. The other piece that's interesting is that single dispatch is optimized, right? The dispatch that we do is optimized on the VMs that we run on. And so there are new features in the one-one branch of Clojure right now, that actually on a branch, that allow you to better model a subset of OO done right with immutability. And so you're allowed to call DefType and do things that create types that have a more traditional dispatch but still have Clojure's immutability and other things. So there are some halfway grounds that are gonna become available. One last question, yes? I heard yesterday something about the shared state memory or something like that, similar to what MagLev is doing in Clojure. I mean, right, can you talk a little bit more? I know nothing about MagLev. So let me say one other thing. I'm gonna be doing the hallway track after this. So if you wanna talk about that or any other question, I will be wandering the lobby. And anyone who buys me a Mountain Dew can ask me as many questions as they want. Thank you very much.