Follow Slashdot stories on Twitter

 



Forgot your password?
typodupeerror
×
Image

Metaprogramming Ruby 84

scottl writes "Metaprogramming Ruby is the first book to give an in-depth and readable explanation of how dynamic programming works in Ruby. It is both readable and accurate and will be a valuable resource to intermediate and probably advanced Ruby programmers for some time to come." Keep reading for the rest of scottl's review.
Metaprogramming Ruby
author Paolo Perrotta
pages 261
publisher Pragmatic Bookshelf
rating 9
reviewer scottl
ISBN 978-1-93435-647-0
summary Metaprogramming Ruby is an excellent introduction to dynamic and metaprogramming using Ruby. It will be useful to intermediate and advanced users of Ruby and potentially even to beginners with some programming experience.
Metaprogramming Ruby is not a book for programmers new to Ruby, but would make an excellent follow on book to either Programming Ruby by Dave Thomas, Chad Fowler, and Andy Hunt or The Ruby Way by Hal Fulton. Both of the above books have chapters on or at least mention metaprogramming, but this is the first full length exposition of it. The book itself is broken into two sections and four appendices. In the first section, you (the reader) is paired with a more experienced programmer for a week, a chapter for each day, and as the week progresses you cover different topics in metaprogramming after being given tasks by your boss. The second section has two chapters on the design and implementation of ActiveRecord from Rails as well as a chapter on safe metaprogramming. Finally, there are three very useful appendices and a bibliography. One other note is that the book has the concept of "spells". Each concept as it is discussed in the book will have a spell associated with it. There will be a note in the sidebar with the name of the spell and the third appendix has the spells listed in alphabetical order, a short example of the spell, and a page number linking back to the extended discussion of the spell.

The first chapters are an informal introduction to metaprogramming where the reader, just starting a new job, is paired with Bill, an experienced developer, for a week. Each day is a chapter and each chapter covers a specific topic. The topics, as might be expected, increase in complexity as the week goes on. This more informal style actually works quite well. I had expected to be a bit irritated with the "schtick", but it turns out that Perrotta does not use it to excess. The topics covered here are Monday: The Object Model, Tuesday: Methods, Wednesday: Blocks, Thursday: Class Definitions, and Friday: Code That Writes Code.

Chapter 1 on Monday starts out with you meeting Bill, your experienced pair programmer, on a Monday morning and then goes straight into the Ruby object model. It discusses reopening classes to add additional methods including predefined Ruby classes such as String. It follows up with Monkey Patching (opening an existing class and redefining an existing method) and the pitfalls therein.

In Chapter 2, methods are examined. Perrotta goes over a problem with duplicated code and how to reduce this code by generating and calling code dynamically. He then moves to showing the same example using method_missing(), followed by adding a change to respond_to? to make sure the methods show up.

Wednesday's topic in Chapter 3 covers blocks, lambdas, and procs all of which are really just "callable objects". The chapter starts with a review of blocks. This is followed by a discussion of scopes and how to carry variables through scopes using blocks as closures. Perratto shows how to use instance_eval() to receive blocks and then use them to manipulate scopes. Next, converting blocks into "callable objects", lambdas and Procs, and then calling them later is covered. Finally, there's a short introduction to domain specific languages (DSL) using the the techniques from this chapter.

Chapter 4 or Thursday covers class definitions. A discussion of self and the current class open the chapter. There's also a section on singleton methods and eigenclasses. There are class instance variables, variables that belong to the class and not to a particular object. Examples of class macros, such as attr_reader, attr_writer, and attr_accessor, and how to write them are shown. Finally he covers around aliases where method names can be renamed and then redefined but the original is still available.

The final day of the week, Friday, Chapter 5, goes deep into Ruby metaprogramming with code that writes code. In this chapter, Perrotta shows how to implement an "attr_checked" attribute in a few different ways starting with a kernel method using eval and moving on to passing the validation attributes in a block. Then this gets moved to a class macro (from Chapter 4), and finally moving on to using a module with hooks. This last is a pattern that's seen in many Ruby projects including Rails and two I'm familiar with, Sequel and Ramaze.

The second section, Metaprogramming in Rails, consists of two chapters on ActiveRecord and a final chapter on metaprogramming safely. In the first two chapters, Perrotta takes a tour through

ActiveRecord, the Rails object relational mapper (ORM) and shows how ActiveRecord uses the tips and techniques from the previous chapters. The final chapter on safe metaprogramming discusses how to test metaprogramming and working around and with to make sure that monkey patching doesn't cause problems.

Finally, there are three appendices. The first shows common Ruby idioms that are seen pretty much in all Ruby code. They provide a good review, but I'm not sure how useful they really are for the audience that this book is aimed at. The second appendix is one DSLs. This is also a nice to have, but there's probably not enough to let you program a DSL if you don't have additional help from somewhere. The final appendix really is almost worth the price of the book. It contains a list of metaprogramming "spells". Each of the spells contains a short programming example as well as the page number with the longer explanation. This is incredibly useful when looking at code from any of the major frameworks (some mentioned above) and you don't understand a piece of it. Just by scanning through the spells you can often find a simple version of what you're looking at and then read a longer explanation.

All in all, this is one of the better, more readable programming books that I've read in a long while. Perrotta keeps it to around 250 pages including the appendices and it's packed full of useful information. As I noted above, this book is highly recommended as a second Ruby book. The presentation of metaprogramming is both enjoyable and useful and the book itself is well written.

You can purchase Metaprogramming Ruby from amazon.com. Slashdot welcomes readers' book reviews -- to see your own review here, read the book review guidelines, then visit the submission page.

*

This discussion has been archived. No new comments can be posted.

Metaprogramming Ruby

Comments Filter:
  • Hmm (Score:1, Informative)

    by Anonymous Coward

    I don't think most people give a crap about Ruby in general. Why not just use a programming language that does it right?

    • "Why not just use a programming language that does it right?"

      Unfortunately, most people *don't* program in Factor.

    • Methinks I smell a Python aficianado.

      (Whitespace? Really? Are you kidding?)

      All I have to say is: being the fastest-growing programming language right now, Ruby must have something going for it.
  • by TheCycoONE ( 913189 ) on Monday March 22, 2010 @01:33PM (#31572944)

    The summary mentions dynamic programming; but this book contains nothing about dynamic programming. (A particular method suitable to problems with optimal substructure that can be used in a subset of cases where recursion can be used and typically generates results very quickly.)

    The author, who I've seen speak, instead writes about "metaprogramming" which in my personal opinion is a silly catch phrase to sell talks and books when actually he's just talking about using some of the advanced functionality present in Ruby (and also JavaScript) to do things that would be done with macros or can't be done at all in traditional object oriented and procedural languages.

    If you're buying this book thinking it contains some new breakthrough paradigm, and you're already familiar with the ins and outs of Ruby prepare to be disappointed. If your background is Java or C++ and you've just learned enough to get by until now it'll probably be an eye-opener.

    • by Lunix Nutcase ( 1092239 ) on Monday March 22, 2010 @01:42PM (#31573076)

      When the author said dynamic, he was using it to refer to the dynamic language [wikipedia.org] features of Ruby, not dynamic programming.

    • If it's at all like Higher-Order Perl [plover.com], it certainly isn't some new breakthrough paradigm. It's LISP re-invented. I hope the author understands LISP (or better yet, Scheme) so he doesn't re-invent it poorly.
    • by thms ( 1339227 )

      The summary mentions dynamic programming; but this book contains nothing about dynamic programming. (A particular method suitable to problems with optimal substructure that can be used in a subset of cases where recursion can be used and typically generates results very quickly.)

      Yes, "calling code dynamically" is not the classic dynamic programming approach: Think of Pascal's triangle [wikipedia.org], each field is the sum of it's two predecessor in the previous row. You could calculate such a field by calling a recursive function, as parent suggests, but that is very inefficient: Consider the first two calls, to the top-left and top-right. These then do another call, and they overlap (rhombus-like): The top-right of the left with the top-left of the right. Here you could re-use the result if you

    • Re: (Score:3, Insightful)

      The author, who I've seen speak, instead writes about "metaprogramming" which in my personal opinion is a silly catch phrase to sell talks and books when actually he's just talking about using some of the advanced functionality present in Ruby (and also JavaScript) to do things that would be done with macros or can't be done at all in traditional object oriented and procedural languages.

      "Metaprogramming" [wikipedia.org] is an old term with a well-established definition, and if simplified to C/C++ audience, that definition would by and large look like "things that are done with macros". So I'm not sure what your problem is. So far as I can see, he is using the term correctly.

    • Re: (Score:2, Informative)

      by JanneM ( 7445 )

      "dynamic programming" is an overloaded term in the English language. All natural languages have many such terms. Sometimes the meanings are related, sometimes they are completely different. When you have learned a meaning of a term, do not assume that is the sole correct meaning. You risk sounding like a pedant or a fool as a result.

    • The 'programming' in dynamic programming does not refer to writing computer programs, it is a branch of mathematics that grew out of the original convex optimization problems. Dantzig was a military 'programmer' in the 40s, the simplex algorithm was developed as a solution to problems that could be posed as a linear objective function with linear constraints. Programming in this sense was a word used by the military to describe how operations would be organised. Dynamic programming is an extension of linear

  • by Lord Ender ( 156273 ) on Monday March 22, 2010 @01:35PM (#31572962) Homepage

    valuable resource ... for some time to come.

    These are some carefully-chosen words. Ruby is evolving faster than any other language, it seems. You blink your eyes and the XML parser you were using is out-of-favor; everyone has switched to the new one which really is much improved. This can be frustrating in that you must work to keep up with the Ruby world, but all these changes really to seem to be bringing the best of the best ideas to the surface.

    Combine this rapid change with Ruby's metaprogramming ability and you see a programming language ecosystem in which evolution is sure to favor that little OO language from Japan...

    • Ruby's ecosystem evolves very quickly, sure, but the underlying language doesn't. Ruby written 10 years ago isn't significantly different to that written now. It's the libraries that are being used that have changed, but Perl has become susceptible to that in the last few years too (consider Perl5i and all the Perl 6-isms that are entering Perl 5).

  • by tweek ( 18111 )

    Pragprog has an AWESOME book coming out that I can't wait to see reviewed called "SQL Antipatterns". Check out the sample chapter on selecting a random row from the database. Freaking brilliant stuff.

  • <% 4.times do %>Ruby, <% end %> Aa aaaaaaaaaaaaah

  • by Anonymous Coward on Monday March 22, 2010 @02:21PM (#31573714)

    I develop in Ruby more than I'd like now and here's what I've seen as a past and present programmer who's used Java, C#, PHP, Perl, Smalltalk, LISP, C++, C, Python, Lua, and Visual Basic amongst others on real projects. Generally, I prefer Ruby to most languages, but only because it reminds me of other languages I'd yet still rather work with instead of Ruby ironically.

    It's good to see Ruby improve and gain popularity, but like so many other languages lately (C#, Java, etc.), it seems to want to imitate Smalltalk poorly. Rather I'd like to see Ruby library authors, language devs, and framework zealots pay a little more attention to what is already out there. It reminds me of high school when you hang out with that friend who thinks whenever they discover something for the first time, they must have invented it. Ruby on Rails unfortunately gives the language a lot of bad press and needs to turn down the idiot volume.

    Ruby also seems to have some diarrhea of the programming language where it wants to mix paradigms from so many other languages. It is like the kid who can't make up its mind. Even when it tries to emulate, it does it poorly, for example with hashes as hacks on named parameters in Obj C and Smalltalk (and .NET 4 now). This leads to wildly inconsistent libraries, methodologies, etc. Are you Perl? Are you Python? Are you CL or Haskell? I love a lot of things from all the languages I work with, but at some point you need focus, direction, and a firm point of view. This is one reason I love Smalltalk and Common Lisp. The two are wildly different in many ways, but share a strong stance of what is acceptable and useful in the language. In other words, these languages are well designed and have a good crap filter.

    Ruby comes off amateurish at best in comparison and makes me feel like I'm working with the new web 3.0 PHP crowd. It's really sad because I love a good language or two, but it's just dumb to try to accomplish such lofty tasks without proper knowledge, leadership, and vision. When you think about it, you have to be kind of an asshole to want to create a new language with all that we have out there. It'd be one thing if it was so radically different as that would represent revolution, but Ruby is so derivative that I often wonder what value added. I tell myself when people do something like this, it must be curiosity + the inner nerd, but that still does not make it ok in my mind. What I wouldn't give if those same people would learn to actually understand and grasp more established languages in Smalltalk and Lisp, or hell even C++. It's not that I fear change, it's just that there's something to be said for experience and well tested languages that have gone through the growing pains already for better or worse. If there was something truly different, that made even functional programming seem trite, then I'd definitely hop on it to learn if nothing else, but Ruby isn't like that.

    Finally, I have a problem in the fact that Ruby is not defined in itself. There's a lot of discussion about this if you google so I won't go into it, but historically, strong languages are able to do this because the internal mechanisms are fast enough and adequately expressive to allow for this. It is definitely a strength of a language if it can be built from the ground up in itself due to elegant design. Smalltalk is probably the best example of this, but owes a lot to earlier effort. Why can't Ruby do the same (too late)?

    Generally, I am rather happy people are discovering Ruby. It allows me to keep certain languages like Lisp and Smalltalk largely my secret. While people build glorified Microsoft Access apps and then later are let down by scalability, performance, inconsistencies, lack of proper internationalization support, deployment tools, stability, etc., I'm happily being 10x more productive in my languages of choice. Unfortunately the world is a cruel place and employers love jumping on the bandwagon. I had the pleasure of seeing this with Java, where everyone thought

    • by cowdung ( 702933 )

      Very true. Smalltalk is a better Ruby than Ruby.. Ruby is still clunky by comparison.

      What we need is to create a new language called.. hmm.. Diamond.. that works like this:

      object.message

      (instead of ST's: object message)

      then you can pass parameters like so:

      object.message(key1:value, key2:value)
      (instead of ST's: object key1:value key2:value)

      etc..

      Ie.. just redefine the syntax so nobody can tell that its just ST (because people fear ST).

      The problem w/ST was that it was ahead of its time. In some respects it is

      • by abigor ( 540274 )

        then you can pass parameters like so:

        object.message(key1:value, key2:value)

        This exists already - it is called Python.

        Smalltalk never caught on largely because of fragmentation in its various implemented versions, and because it's not file-based. Rather, you modify an image, which is too weird and unwieldy for most people.

        • then you can pass parameters like so:

          object.message(key1:value, key2:value)

          This exists already - it is called Python.

          And Ada.

    • -1 Troll

      Writing a wall of text doesn't

      • Re: (Score:1, Interesting)

        by Anonymous Coward

        Care to elaborate? I don't even understand what your comment means.

        I use Ruby every single day. I can't think of another language that for instance forces me to write C extensions to makeup for broken or slow parts of the language. I can't think of a language used at this level that can't support internationalization properly in this day and age. It's threading model is to put it lightly, abysmal. There are no great editors or deployment tools. The language itself cannot even fully support any sort of intel

      • I think you a word out
    • Ruby also seems to have some diarrhea of the programming language where it wants to mix paradigms from so many other languages.

      You make it sound like that's a bad thing.

      I prefer multi-paradigm languages because they let me pick the paradigm that best suits the problem.

    • Re: (Score:1, Interesting)

      by Anonymous Coward

      Ruby wasn't intended to be an "enterprise ready" language or anything like taking over the world and become popular whatsoever (the Rails guys are solely responsible for Ruby notoriety). Ruby is about the fun in programming, a hobby. Ruby supports all of the programming paradigms it can because it makes it more fun, nothing more, nothing less. You can write extremely perl-ish code in Ruby, you can write purely procedural code too even if the underlying mechanism is OO, you can write Smalltalk-ish code using

    • Re: (Score:3, Insightful)

      by Endymion ( 12816 )

      Ruby has its (serious) faults, but the multi-paradigm nature of it is not one of them. It's probably the main reason I like the language. Yes, it's not perfect in any given programming style, but the mix of styles is a huge convenience. It's nice to be able to use LISP-like features at times, but still be able to bank out quick, traditional imperative-style code when it's appropriate.

      This isn't to say they shouldn't take more from Smalltalk and LISP. Those rough edges are just slightly bad enough to bet in

      • What's particularly nice about Ruby, over the theoretically nicer LISP/Smalltalk/etc, is that Ruby is actually used fairly often...

        Every move-to-column you make
        Every gdb-point you break
        Every file you save
        Every font-lock-keyword you say
        I'll be ru-u-unning you

        From the Song of Emacs

    • As someone who is not an experienced programmer in all those languages, merely someone who has dabbled in a handful of them and read about programming much more than he's actually done it... Well, in the abstract, your argument is enticing, convincing even. However there is one glaring counterargument which stands out to even a peon like me, which you have apparently not addressed. It's this:

      When you think about it, you have to be kind of an asshole to want to create a new language with all that we have out there. It'd be one thing if it was so radically different as that would represent revolution, but Ruby is so derivative that I often wonder what value added.

      If Smalltalk Already Did It (Better)®, and Smalltalk has been around for x decades, then how come Ruby has come

You will lose an important tape file.

Working...