Metaprogramming
Forbidden Fruit: A Test of Ruby's Parse Tree

Summarized using AI

Forbidden Fruit: A Test of Ruby's Parse Tree

Chris Wanstrath • April 26, 2008 • Earth

In this presentation titled "Forbidden Fruit: A Test of Ruby's Parse Tree", Chris Wanstrath introduces the audience to the powerful features of the Ruby programming language, particularly focusing on metaprogramming and the parse tree functionality. Throughout the talk, Wanstrath highlights his journey with Ruby and how it differs from other programming languages in terms of dynamic capabilities. He emphasizes the importance of Ruby's metaprogramming features, which allow developers to modify their code on the fly, showcasing several methods such as 'definemethod', 'classeval', and 'send'.

Key Points Discussed:
- Introduction to GitHub: Wanstrath briefly mentions GitHub and his excitement about applying Ruby to real-world programming.
- Learning Ruby: He recounts his early experiences learning Ruby through 'Why the Lucky Stiff's Poignant Guide', which fosters a unique and playful approach to coding.
- Metaprogramming in Ruby: The main theme focuses on Ruby’s metaprogramming capabilities, where he demonstrates how these methods expose the underlying functionality of Ruby, allowing developers to write fluid and dynamic code.
- Saki Project: Wanstrath introduces his project called Saki, which enhances rake tasks management and integrates with a lightweight Ruby gem system, drawing parallels with Git's user experience.
- Using Ruby to Ruby: He explains the Ruby to Ruby gem which enables developers to introspect Ruby methods, thereby enhancing the debugging process and knowledge of Ruby internals.
- Real Use Cases: He illustrates practical applications of using metaprogramming to solve relatively simple problems in novel ways, such as dynamically generating rake tasks based on user needs.
- Ambition Gem: The talk transitions to discussing a gem called Ambition, which simplifies query building in Ruby, providing an alternative way to interact with SQL databases through Ruby syntax.

Conclusions and Takeaways:
- Ruby's dynamic nature and metaprogramming capabilities allow for elegant and expressive code.
- The ability to inspect and manipulate code at runtime is a powerful feature that developers can leverage to create more maintainable and flexible applications.
- Projects like Saki and tools like Ruby to Ruby showcase the innovative spirit of the Ruby community and its potential to enhance coding practices.
- Wanstrath encourages ongoing experimentation with Ruby's capabilities, especially as the community adapts to updates like Ruby 1.9.

By the end of the presentation, Wanstrath reaffirms the importance of knowledge sharing within the Ruby community and hints at the possibilities that lie in further exploration of the language’s features.

Forbidden Fruit: A Test of Ruby's Parse Tree
Chris Wanstrath • April 26, 2008 • Earth

Help us caption & translate this video!

http://amara.org/v/FGkk/

GORUCO 2008

00:00:13.719 All right, so my name is Chris Wanstrath. I'm a little nervous. I've got a new operating system, and this is also the first time I've given a talk as a corporate representative. I don't even know how to say it well.
00:00:20.199 Well, I've given a few talks before, and in all the previous instances, I've always been representing like myself or a consulting company, or some big corporation whose website I don't even want you to go to.
00:00:26.960 But this time, I actually have a product that I'm really excited about and want all of you to use. So I'm going to try not to hammer it home too hard, but this is the product: it's called GitHub.
00:00:40.160 One of the things I read when I was researching how to be a good presenter is don't ever talk about yourself; no one cares who you are. Build your reputation by giving a good presentation.
00:00:46.160 So I'm going to not do that and just say GitHub is really awesome. You guys should try it, and because it's awesome, you should probably listen to this presentation, which is entirely unrelated to GitHub.
00:01:06.040 That said, GitHub is a Rails site built in Rails. I started doing Rails a couple of years ago, and I've always done it on the side while I was learning how to program and getting good.
00:01:12.240 To me, what was interesting was that Rails exposed to someone like me, a web developer, a really powerful dynamic language. What I did when I was learning Rails was not read the Agile Rails book right away because it wasn't out.
00:01:24.320 I read one of the only three books that you could get your hands on, which was 'Why the Lucky Stiff's Poignant Guide.' I think if you get all the way through it, that becomes your entry point into Ruby, and you come out with a unique outlook.
00:01:42.399 This outlook is that you're going to write the most cryptic, most insane code you can, and it's going to be awesome, which is what I do. What's great about Wise's book is it talks a lot about metaprogramming.
00:01:54.000 I think there's a chapter devoted to it. He's got lots of great mnemonic ideas to teach you the basics, but he also has fantastic examples that you can follow along and use to learn the more interesting things.
00:02:06.439 Like, DWTH me’s array is one example, as well as an entire mini-site devoted to learning how to metaprogram your own mini RPG. For me, when I was in college trying to learn a real programming language for the first time, all I really had experience with was, like I said, the web and MUDs.
00:02:23.680 So doing this was really exciting and got into my head that Ruby was really powerful because it could rewrite itself on the fly. That's kind of how metaprogramming was presented when you read about it in Wikipedia and all that stuff.
00:02:35.080 These are four of the methods that Ruby gives us that expose the underlying implementation and let us do things that the Ruby implementers can do within our dynamic programs on the fly. Define method, of course, class, new, let's just create a new instance of a class.
00:02:48.159 We can pass it another class to be the superclass. 'Instance of all' lets us control the scope of a block or a string, and 'send' lets us send a message, which gets to the heart of Ruby's Smalltalk message dispatch system.
00:03:05.760 Here's an example of something that I hope to never see in a Rails app or some kind of production code, but it's really quite fun to do. We have a person class, and we grab the singleton, the meta-class, or the eigenclass, and we run through either a local variable or a method which is an array of arrays.
00:03:19.599 The first element is a name, and the second element is a proc or lambda. We add all these class methods on the fly to this class; there could be thousands in there, there could be tons, literally.
00:03:33.640 So this is really cool. There's a lot of power there. There are a couple of things going on: we have to send define method to get around the access controls because define method is a private method.
00:03:45.760 We have to grab this eigenclass Tom fery, which is probably a whole presentation in and of itself. But another great thing about Ruby is we can take this and make it look normal.
00:03:56.480 We can open up class, which is the blueprint for all instances of a class, such as person. We can add methods to it, which is something that Rails does extensively. Has many, belongs to, and all those are just class methods.
00:04:10.879 Then we get some Ruby that looks a lot nicer. It looks a lot less evil despite the fact that it still is. Ruby is very powerful for so many reasons, two of which are the amount of change you can inflict on the kind of environment at runtime and how much you can hide.
00:04:29.080 We just hid that tremendously; this almost looks normal, but it's really not. So this is one of the main reasons I love Ruby—these little side projects you can do for fun that are so far removed from web development or JavaScript.
00:04:40.960 I have this habit of trying to look for problems that aren't really that big of problems and solving them with metaprogramming. It's just something I'm into. One of these problems that wasn't really a problem was that during Rails development, I always have these rake tasks that I move around from app to app.
00:05:10.720 One was like DB version and db remigrate and stuff like that, which I could keep in their own subversion repository and do externals or have some bat script to install them or even a Ruby script that would constantly copy these rake tasks over from my existing Rails app.
00:05:16.759 But that was clunky, and I also made it harder to share these tasks with other developers, or to not share them. Maybe I didn't want to commit all my crazy rake tasks into the subversion tree because they were just for me.
00:05:30.680 Or I was too lazy to remove the hardcoded paths to my user, Chris, or what have you. So I came up with this idea for this project called Saki. It's the last effect I'm going to use, I promise, but I had to try out the new keynote.
00:05:47.919 So, it's like rake, except the first letter is different. What it is, is the idea of Ruby gems or any packaging system really, very lightweight for Saki. It's also really influenced by Git in that it's easy to use; there's no central location.
00:06:05.919 Every single Saki client is also a Saki server, so any file or any webpage which is plain text you can pull in rake tasks from. What I really wanted was to share my entire Saki file with anyone here.
00:06:18.680 There can be 100 Saki tasks in there, and I want you to be able to pick out just one. How do I do that? Well, there are a few different ways. Let’s take a look at this pasty patch I used to get back in the old days.
00:06:38.520 In open source, I would get lots of patches on Ruby Forge or wherever submitted as pastes. I had this automated workflow. I would pull in the paste, automatically apply it, run the test, look at it, and if it was good, I would commit it; otherwise, I would throw it out.
00:06:50.759 Now, that's actually all built into Git. This is one of the reasons I wanted to put this in there. So, you look at this and you know, how do we get just the body of this one task and identify it so that we can share it using Ruby?
00:07:02.240 We want to save it, we want to be able to install it, uninstall it, send it to someone else, or just send one task or a whole file of tasks. It looks pretty simple until you start looking at it.
00:07:14.440 The git format log is written in the curly brace style, and the one above it is all kinds of madness. It's simple, right? I'll just use regular expressions. It can't be that hard.
00:07:25.280 I'll find a bunch of rake tasks out there, get a set of regular expressions that handle every case, and I'll be done. But, of course, now I have two problems: regular expressions and the actual handling of them.
00:07:37.319 I was thinking about this for quite a while. I have another project called Cheet, which is another sort of fixing a really small problem in a really grand way.
00:07:48.560 It's a wiki where anyone can go and modify a plain text cheat sheet. They can add their own. There's one for subversion, one for Rails, one for TextMate, but it also has a command line client that you can use to pull in the cheat sheets from the website.
00:08:07.560 Because of that, it has an API. You can put it in TextMate or Vim. I have a little macro where I can pull in a migration cheat sheet into my Vim shell whenever I need it.
00:08:21.120 While I was working on that, I decided that it'd be cool to have a Saki website and be able to share these with other people. It's been in my head for a while.
00:08:36.240 One day I saw this presentation at a San Francisco Ruby meetup where a guy named Blaine Cook used a thing called Ruby to Ruby, and as soon as I saw that, I thought, I know what I'll do: I'll just ask Ruby what the method is.
00:08:53.599 I'll ask Ruby about that task, and it'll tell me, and I'll be able to do all the things I want to do on my own. It's funny because Ryan Davis is here, and I'm going to be talking about his stuff a lot, and I'm just going to try and pretend like he's not. So anyway, be nice.
00:09:07.920 Thank you, Ruby to Ruby is awesome, not just because Ryan's here, but because there's this really basic question which is really hard to answer: how do we ask Ruby for the method bodies or the bodies of blocks or procs or lambdas in this case?
00:09:54.720 I have a session here as 'forb' which equals proc blah blah blah. I want to get that self-referential kind of string into something I can use, maybe an array of this or that, or another string that I can re-evaluate.
00:10:01.880 So how do I do it? It's stupid simple: you just install the Ruby Ruby gem, and you call two Ruby on your block, and there it is.
00:10:14.680 So that's actually a Ruby string that we get of the method, the body of the block, and we can do with it whatever we want.
00:10:26.080 That's just one example of what we can do when we have access to this thing in Ruby, which we know as the Parry.
00:10:36.720 So the name of this talk is Forbidden Fruit. By the way, there's an apple; I also used the cool kind of remove alpha effect in keynote, which is really awesome to get that nice Apple gleam.
00:11:06.360 Moving on, Gstar Ruby to Ruby has a few dependencies, but the good thing is that once you install any of them, they pretty much all depend on each other, so you get it once you have to deal with two or three or four gems.
00:11:29.200 After that, it's a simple matter to install any one of the siblings. Ruby Ruby is good because it not only gives us the two Ruby method on blocks, but it also gives us a class method called translate, which we can feed into any class.
00:11:50.960 It provides the Ruby representation of that class. I saw Jil's presentation a couple of weeks ago at the Philly Emerging Tech Conference, which was really awesome.
00:12:02.720 There was about one table of people watching us talk, and it was all the other Ruby speakers, so I was paying very close attention.
00:12:16.280 What he did was he took an Active Record class, a subclass of Active Record, like a person class or a ticket class. He called has_many on it and then ran the class through Ruby to Ruby.
00:12:28.960 He was able to see all the crazy things Rails did to it—everything from 'has many tickets' to the options that it takes and where it goes with it.
00:12:43.000 It was really interesting to see these methods that you use every day, which you know because of the tests you write and the documentation you read in Ruby code, which I've never actually seen before.
00:12:59.520 So that was a really great use of Ruby to Ruby in my opinion, a cool way to just introspect code. He's not actually using it for anything, any kind of gem or whatnot yet, but it’s a good way to just see what's going on.
00:13:10.000 Back to Saki, I was going to do a little demo to show you guys what it is, but I don't think this is actually going to work. It worked so well in the tel because basically Saki lets you do -T just like rake.
00:13:22.880 It lets you do -h -T on any other file just like rake to see what tasks are in it. It lets you do -h -T on a webpage without caring about the difference and see the tasks in it.
00:13:43.560 It lets you do -d to install a single task, to install every task from a Saki file. -e actually prints out and examines the source of that task.
00:13:58.480 So let's say you have a list of tasks, maybe five or ten, and you want to see which version of 'git format log' is the best: 'git format log one' or 'git format log two.' You can just do -e git format log, and you'll see the code right there.
00:14:14.560 It's really cool because it just all works; everything that you would want to do if you were installing and executing arbitrary remote code, you can do. You can uninstall it easily, install it easily, and examine it.
00:14:30.680 It evaluates things over the wire with the safe level; it's just really great, really simple. And the best part is I wrote it in one night because everything is so clean and kind of just depended on other people to do the hard stuff for me.
00:15:02.120 To use Saki, this is what you write in a Saki file. Let's say this is what you and I see: task 'hello.' All of you should be familiar with this because it's basic rake.
00:15:15.679 But behind the scenes, what we're doing in order to grab this block of code and be able to treat it as data is storing this with our own DSL. So we're not actually using rake when we're running Saki and looking at this file with -T.
00:15:36.920 We're actually running our own Saki version of the rake DSL, where every task gets grabbed and put into our own task array the way that they do it with some extra metadata.
00:15:54.400 If we were to require Saki in IRB, we could do this: task equals new hello, where 'hello' is the task name, and feed it a body.
00:16:09.320 When we ran two Ruby on that task, this is what we'd get out: this would be a string, and while I'm printing it seems formatted nicely, it would be a string of the body.
00:16:16.040 What's interesting is that I didn't have parentheses in my version, but there are parentheses in this version. It's not actually saving the code you write; it's looking at something within Ruby, say the parse tree, and generating a string representation of that code, which is wicked awesome.
00:16:31.440 What we can also do now that we're building things on the fly is pass in some other information like dependencies and a description and get out a more advanced but very common rake task.
00:16:47.600 For example, there's a dependency on the environment task and description, and all that sort of great stuff. That's all I'm going to talk about for Saki right now. It's really great; you should install it.
00:17:02.479 If you haven't already, use it daily. There are a bunch of tasks for making Ruby development easier and using Git easier and whatnot.
00:17:18.480 But even though this is a Ruby conference, there's something that I learned recently. I've recently gotten into JavaScript at about the end of last year while I was working on this site, Spam for my other company.
00:17:37.680 I found jQuery, which Josh talked about earlier, and it's really awesome. It's just very concise, very terse, and very easy to learn.
00:17:53.200 You basically just learn a set of rules, and from those rules, you know everything. You know where to look for something, you know how to do anything, you know where to go in the documentation, and there are very few rules.
00:18:04.240 Everything is consistent. While I’m diving into JavaScript, I’m realizing, oh wow, this is actually a real programming language; it’s not just alerts and equals.
00:18:14.480 There's a difference between using a var in front of it and not. One of the things I learned along the way, which I never even imagined before, is that JavaScript has a toString function that's in every modern JavaScript implementation.
00:18:37.760 What it does is give you a string representation of the function. It doesn't work for things that are defined in C, like array size and whatnot, but if I define my own function, I can get back the string from it right there.
00:19:02.880 What you can do with this is the same thing you can do with Ruby to Ruby. For instance, Yehuda Katz, one of the Ember.js guys, has a JSpec library, which is a dead-simple BDD library for JavaScript.
00:19:11.920 What he does is print out all the statuses in the console of Firebug, which is pretty cool. He's able to print out the identity of the function you're calling and the name of the function you're calling by using toString and parsing the first line.
00:19:27.679 It's really cool. It gives you some insight into what you're doing, especially when you're trying to do kind of debug development or figuring out what's going on here stuff.
00:19:42.000 So Jim, and all Saki, that’s it. So, what else can we do with Ruby to Ruby? I mentioned it earlier, but Blaine Cook showed me something that was really cool and really opened my eyes.
00:19:53.160 There’s a gem that can turn Ruby code into Ruby code, and you're almost like, oh so what? Ryan Davis got drunk again and wrote something crazy that I'll never be able to use.
00:20:09.480 But really, it takes maybe one of his projects, one of Blaine's projects, or something real, something that’s actually being used in a project to see how really powerful it is.
00:20:25.560 This is one that Blaine did in about 30 lines of code. It's basically the map part of map reduce written in Ruby with Ruby to Ruby.
00:20:39.680 What you do is take a range, 1 to 100, and instead of calling map on it, you call dmap, which is this method that Blaine has authored.
00:20:54.640 What it will do is exactly what you expect: it will send this block to different servers that are running somewhere in the land. It'll ask them to compute it and get back the result.
00:21:07.920 At the end, you'll have a 100-element array with all your results served concurrently. The code is not the most beautiful thing to look at if you're not familiar with DRb and ring servers.
00:21:23.040 What Blaine has done here is two really cool things. He's forgone the sort of configuration you need to set up a little cluster of servers by using Ringy Dingy; it’s kind of like Bonjour for Ruby demons.
00:21:40.080 Servers can find themselves and clients can find them, so you can have as many as you want without needing to connect to this IP on this port or that IP on that port.
00:21:57.440 What Blaine does is connect to a Ringy Dingy server or instantiate one and looks for some other clients. This isn't using all the code, so I'm confusing myself.
00:22:10.000 The Ring server is a client. He attaches to the server and asks it to do something for him; he then collects the results and returns them as an array.
00:22:23.440 What he's asking the server to do is really interesting because he's saying, 'Here’s this block of Ruby code as a string. I'm going to send it to you, and I want you to eval it and send me back the results.'
00:22:41.600 This is over a very secure network, hopefully, so it’s not that big of a deal. The clients are identified by their PIDs, and it sends the Ruby execution element also serialized in the DRb fashion.
00:22:56.200 What you get back are the computed results, which is quite cool. Here’s the actual server end of it, and it just starts a Ring server.
00:23:12.200 What it does is take the strings off the wire, evals them, and passes in the element that was sent. If it’s 1 to 100, each time the block gets sent along with the element, 1, 2, 3, 4, and it sends back the answer.
00:23:27.480 It's really cool. It's just the map part of it. I'm sure no one’s using it, well maybe Twitter is using it, but I'm sure no one’s using it in production.
00:23:43.919 However, it's just an example of the neat things you can do with this sort of power. I put it up on GitHub last night because there is no reduced part of it, so it would be cool if someone wrote that.
00:23:57.960 I might do it later this week just to see if I actually understand what's going on. But there it is; it's grab-it octocat approved! What else can we do?
00:24:06.920 Well, it’s kind of switching gears here. What we're talking about is kind of beyond metaprogramming because metaprogramming isn't really that big of a deal or that distinct from Ruby.
00:24:23.680 Someone said that metaprogramming is just programming in Ruby, which is true. The methods that I showed earlier—the 'instance of all,' 'define method,' and those are well-documented.
00:24:36.960 Those are part of Ruby, so when you use those and you're coming from another language, they're magic. But once you start doing Ruby for a long time, they become something you kind of depend on in those edge cases.
00:24:55.440 There’s something that's always there; they're not special, they're just a part of Ruby. Ruby is just so dynamic that things are always changing, and you don't really even think about, 'Okay, now I need to switch into metaprogramming mode.'
00:25:09.200 However, there are limitations, and there are things that would be really cool to do, but you just can't; and what's really frustrating is that in other languages, some of these things are possible.
00:25:34.400 So, what am I talking about without using such abstract verbage? How can I make my SQL strings more expressive and prettier with syntax highlighting and whatnot?
00:25:50.720 The way to do it is to write it in Ruby. Here's one attempt; it's called the Conditions Builder and there is a plugin on the Agile Web Development plugin repository.
00:26:12.760 What it lets you do is spend time learning an entirely new API for the added benefit of some really weird syntax. But it's a cool attempt; it's writing your conditions in Ruby.
00:26:30.640 It's compositional, so you can take different condition objects that you've created and mash them together to get a new condition object. It’s probably very easy to mock and test, asserting that the SQL you're generating is the SQL actually you want it to generate.
00:26:46.560 However, the problems are obvious: you have to learn this whole new API, and it’s not that intuitive. This leads to the next statement on the list.
00:27:01.319 This is another earlier attempt, which is actually pretty popular. It's called Easy Wear, by Ezra and Fabian. The README file is really long; it can do a ton of stuff.
00:27:12.760 It lets you create your own Ruby DSL and enables you to create SQL conditions using it. Again, the advantages and disadvantages are obvious; it's cool and compositional.
00:27:30.080 It lets you do very complex things with Easy Wear, so you can pass in things like 'include' after the 'all' symbol to do your joins and whatnot.
00:27:49.488 But again, it's a whole new thing to learn; it's a really long read, it's very powerful, and the simplest solution I think all of these layered query generators are trying to do is something simple to write like this.
00:28:03.640 This is just Ruby—the way we would operate on a hash and array. In this case, it looks like an array of, let’s say, OpenStruct objects or person objects.
00:28:20.480 It would be really great if this is how we could write our SQL because, not in all cases, but in some cases, this is really all you need.
00:28:36.680 The username is this, the user login is this, the user password is this. I don't care at all about Active Record's find all conditions or find all by whatever API. I just want to write it in something that’s simple and instantly recognizable.
00:28:51.240 There are many benefits that go with this because there's a very slow learning curve. If this was the API for a number of different ORMs, it would be easy for you to dip your toe into a new one.
00:29:05.120 As soon as you're set up, you can start using it. Whereas now, it's all documented well, but there is a step of learning and reading the cheat sheets, which I personally find tedious.
00:29:20.880 This is, in my mind, the gold standard for simple queries. What's interesting is that this is something other languages already do. If you've ever used Erlang, they have this half cash, half relational database thing called Amnesia.
00:29:35.160 Erlang has built into the language list comprehension. These are not just technical-sounding words but represent backwards enumerable operations.
00:29:56.080 What they do is filter their arrays after the array has been declared in these conditional blocks. It's hard to explain, but once you see it, it makes sense.
00:30:09.240 They run a select and do filtering records through a very terse syntax. Since they already use that for lists, they could leverage that to query their database.
00:30:29.240 We can treat records and tables as lists, and we can write this query in this language we’re all familiar with.
00:30:40.080 What we can do behind the scenes is translate it into a more specific Amnesia query language. The important thing is, we could pull out every single user in the database and run them through this, saying, 'Oh, we’re done here.'
00:30:58.919 But that's not going to work for even small data sets. We need to look at what's going on here and make this into SQL. The way that I solved this problem is with this gem called Ambition.
00:31:16.200 This was kind of just noodling around, learning or laying off of the pragmatic book. They have their list comprehension kind of coding in natural Erlang; Amnesia walks the query language, which I think is a query language for Amnesia.
00:31:41.200 You walk the abstract syntax tree to create the query from that, so the code you write as part of the list comprehension never runs. That's exactly how to do it because that’s what you can do with Parry.
00:31:55.360 This is the Active Record find, a very simple one; it’s a lot of cru because it shouldn’t be an 'all', but there’s a lot going on for something so simple.
00:32:12.040 I want to find John, and it generates the SQL behind the scenes. This, I think, is much clearer to someone doing Ruby; it’s very explicit.
00:32:28.080 What we can do with it is generate a SQL string by giving the User class a bit of magical powers. Here are some of the things that Ambition can currently do.
00:32:48.080 We can do simple selects, passing an arbitrary array. We're asking, 'Is this user’s ID in this array?' This is very Ruby-like; even new Ruby programmers face the enumerable API early on because it’s amazing.
00:33:13.560 This translates to SQL exactly what you would expect. To do that in Active Record, it wouldn't be impossible.
00:33:30.640 You could even say something like 'User.name equals Chris,' but I didn't even want to think about it and write the example slide.
00:33:48.000 This is another example, and it’s also cool because it’s not just select. We want to use detect on top of select.
00:34:06.440 We can say like select.first. Detect has a very specific meaning because it returns nil or returns something.
00:34:23.440 I wanted to detect a user who has an idea titled 'new freezer' whose email matches the regular expression, PJ.
00:34:39.040 This is what that would translate to behind the scenes, with mountains of joins, going across both profiles and ideas, which are Active Record associations.
00:34:56.640 We're using Active Record; we can tell which database we're in, so we can do some database-specific stuff. In SQL, it would look all caps.
00:35:12.760 This is viewed as an expression that’s normal, so it’s cool. Because we call methods normally, it lets us work with Ruby directly.
00:35:24.000 The interesting part is that we're switching and returning correctly at the right time. So, why is this so hard? It’s simple; it's two very simple conditions in a block.
00:35:39.620 So why can't we have a crazy blank slate proxy object to collect what’s going on? After the block has some method called on it, do some issues, but you can’t.
00:35:56.820 There are a couple of things: the first is the double equals operator. If you leave it the way it is, you don’t get the result you expect.
00:36:08.500 That leads to syntax errors and frustrations, dealing with those lower-level commands. However, luckily for us, there is Parry and it lets us get away with the things our mom and dad told us not to do.
00:36:23.440 Like Ruby to Ruby, it’s crazy how simple it is. When you first install it, you take a block and call two S exp on it.
00:36:38.040 You get back this crazy-looking data structure, but luckily it's just a normal Ruby array with normal Ruby symbols and types in it.
00:36:53.280 You’re working with actual Ruby values, as in those are real nil, that’s a real integer one, and those are real symbols. We can focus on the meat and get that implementation detail out of there.
00:37:09.760 This is the parse tree from 1 +1. I'm not an expert on languages or abstract syntax trees, but I've read Wikipedia and been working on this for a while.
00:37:20.640 What this is showing is that Parry hooks into the ABX syntax tree, which Ruby generates when it parses your plain text file.
00:37:32.420 It takes this human-readable Ruby language and builds in memory a semantic representation of what's going on, using different ways to write the same code.
00:37:48.560 Chances are in the abstract syntax tree, they will be represented the same way because it's the same code regardless of whether you use parentheses in an affected spot.
00:38:17.240 This is the Ruby representation of the abstract syntax tree. There's also something called the concrete syntax tree which includes information about the parent; when you deal with grammars directly, there’s one available for Ruby called Treetop.
00:38:43.919 But we don’t care about that at all for what we're doing. Luckily, Parry either doesn’t see it or never sees it. To get a little more academic, this is the classic diagram for what is being represented in a parse tree.
00:39:04.080 It’s 1+1. It’s written in mostly a way representing any standard language. You get this array, and it's always in prefix notation.
00:39:18.160 Elements that go before other elements describe what happens to the nested ones. Here’s the representation, looking at a call that processes this behavior.
00:39:34.440 This is much about how we take a task and how we process it. There are lots of different qualities to handle too.
00:39:48.959 We built a SQL processor, a new class, and set up initializations, thinking back to how we’re handling those structures behind the scenes.
00:40:03.160 So remember that we're focusing on that pattern of the class and how to validate the right pieces for extending their capabilities but have to pass or process our strings.
00:40:18.840 We want to look at the mechanisms of how we get our templates built and understood better. I’ve seen it said that Parry is slow.
00:40:32.040 But you're an idiot and I've run benchmarks to confirm that it is not slow at all. It’s quick because it hooks into information already available. Parry can be used in production with no memory leaks, fast results, and a great experience.
00:41:00.200 You can use it in any situation you want—especially in MERB. In MERB, they have a Parry-dependent mechanism for getting arguments to line up with the parameters.
00:41:16.200 I've seen no problem arise from using the structure itself, and it is a cool gem. As this gem becomes more popular, the community is eager to take on more advanced Ruby features.
00:41:31.760 We can pass in those blocks and manage the translations as needed. However, we also rely on something special—a query object and the ability to build from it.
00:41:52.120 You can code against this class and Ambition will set it up for you. You can define some general command methods to maintain query methods and fire off the right queries when necessary.
00:42:07.360 The exciting part, to many users, is how you can consolidate your requirements and structure everything beautifully. It includes a separate process for any active records generated.
00:42:23.679 You can define the amounts of work needed without worrying how that SQL operates under the hood. That lets anyone understand this more quickly.
00:42:38.960 This library makes code simpler and quicker for many. You can perform fast data manipulation with tasks.
00:42:53.680 The final aspect I'll cover details how the backend helps retrieve your requirements—just to keep things flowing smoothly.
00:43:05.520 If you decide to roll your version of these adapters, you can and it is not too difficult. Simply define the structure and things can grow from your established foundation.
00:43:16.159 This leads us to that second part: Ruby to Ruby does a similar thing. It’s a lot more intense because it understands far more than just select.
00:43:28.480 It calls S exp on the Ruby code, processes the module formats and then spits out the string as needed for your applications.
00:43:41.680 You'll find that it processes robust and standards-based models and highlights distinct frameworks. You’ll also appreciate how it interfaces with regular expressions, something I have had to explore for my own projects.
00:44:04.440 These structures are designed to highlight the series of processes available in programming languages, showcasing their effectiveness.
00:44:16.160 These are just some of the hard capabilities of Parry. Consider the vital integration with JavaScript, C++, and other scripting languages we see in use today.
00:44:29.000 There's no shortage of opportunities here; there are even supporting languages such as Python and Lisp for what these structures can achieve.
00:44:45.080 So there it is, the power of the parse tree and the foundational capabilities of S exp structures. There’s no better time to push the underlying limits—we can process differently-built conditions on data efficiently.
00:45:00.000 This makes for a bright future as we move forward in understanding how to utilize these gems. It opens up our conversation, and I’m looking forward to sharing more with all of you.
00:45:20.720 Thank you for your attention today. I look forward to questions and the ongoing conversations. It’s a collaborative and bright path ahead.
00:45:36.880 Feel free to ask any questions you have. I appreciate the dialogue, and let's propel this conversation together!
00:45:49.480 Yes, thank you! It's great to share ideas. Just a note: make sure everyone in the Ruby community knows that there are limitations in the pars tree.
00:46:02.000 For instance, it does not work and will not work in Ruby 1.9 due to internals not being kept in memory or compiled accurately. It is further challenged in its Ruby 1.9 portrayal.
00:46:45.960 Moreover, other parsers help illustrate the nuances of these processes, ensuring we grow together as a community.
00:46:57.040 Is there anything else before we wrap up?
00:47:05.240 Yes, okay! To clarify, you are able to continue using the parse tree or code that depends on it as long as you’re on Reinius in the future.
00:47:19.560 Yes, that's correct! Thank you again, everyone. Enjoy your day!
Explore all talks recorded at GORUCO 2008
+5