The Methodphitamine 23

Posted by Jay Phillips Sun, 05 Aug 2007 01:30:00 GMT

What amazes me most about Ruby is the emergence of hidden, powerful subtleties that lie under its surface just waiting to be discovered. A few months ago I discovered this useless, albeit cute snippet of Ruby’s fringe English-like qualities and, despite tens of thousands of people using Ruby, it wasn’t until just last year that the Symbol#to_proc hack was discovered that happily changed the way we refine and iterate our collections.

Well, ladies and gentlemen, I think I’ve developed a way that trumps Symbol#to_proc. Observe a few examples:

(1..100).select &it % 2 == 0
File.read("/etc/passwd").split.sort_by &it.split(":")[2]
User.find(:all).map &its.contacts.map(&its.last_name.capitalize)

I call it The Methodphitamine. That’s Method ph it amine, a drug for Ruby addicts to code faster. Unlike Symbol#to_proc...

  • arguments can be given to the method
  • it’s not limited to just one method. Tail on as many as you like.
  • it’s more English-like with the intuitive use of it or its
  • even a method with its own block can be given to it

Let’s take the last of the examples above and convert this into its equivalent pure-Ruby and Symbol#to_proc way.

First, the pure-Ruby way:

User.find(:all).map{|x| x.contacts.map{|y| y.last_name.capitalize }}

And now with Symbol#to_proc:

User.find(:all).map{|x|x.contacts.map(&:last_name).map(&:capitalize)}

And now with the Methodphitamine once more:

User.find(:all).map &its.contacts.map(&its.last_name.capitalize)

Notice how even with Symbol#to_proc a block literal is still necessary because it simply can’t do nested arguments. The Methodphitamine fixes this by preserving all arguments and being more readable to boot.

So now, without further ado, here’s The Methodphitamine’s code, weighing in at just over 20 lines.

module Kernel
  protected
  def it() It.new end
  alias its it
end

class It

  undef_method(*(instance_methods - %w*__id__ __send__*))

  def initialize
    @methods = []
  end

  def method_missing(*args, &block)
    @methods << [args, block] unless args == [:respond_to?, :to_proc]
    self
  end

  def to_proc
    lambda do |obj|
      @methods.inject(obj) do |current,(args,block)|
        current.send(*args, &block)
      end
    end
  end
end

So how does The Methodphitamine work?

The it() and its() protected methods are added to Kernel so it can be called from anywhere in a Ruby script but not on any particular Object instance. They each simply return a new It instance.

The It class has all instance methods stripped from it (except the ones Ruby complains about) to ensure method_missing() catches everything. In the example [1,"2",3].map &its.class.name, the It object first receives the class() method with no arguments via method_missing(). This gets enqueued in the @methods Array and it returns itself to receive any more methods. It then receives the next method, namely name(), and enqueues that alongside the previous method. When no more methods exist, Ruby determines if the It instance has a to_proc() method by calling respond_to?(:to_proc) so this has to be ignored and self suffices as a Ruby true boolean.

Then the magic happens. Because map() takes a block (essentially a Proc argument), this can be substituted with a variable or method that returns a block as long as an ampersand prepends it to let the Ruby interpreter know to call to_proc() on it. The It#to_proc() method is invoked, building a custom, dynamic Proc. Because these enumerations yield a variable, the dynamic Proc is executed for each item in the collection and obj consequentially becomes a reference to the current item in the collection. We then run through the enqueued methods with inject(), passing along the return value of executing each method in the order received with arguments intact. When inject() is done, it simply returns the grand product which becomes the return value of the Proc itself. Simple, right? :)

I chose to define both it() and its() since methods in Ruby can semantically either mean “the result of this action” or the possessive “this attribute.” For example, it.to_s and it.sort_by are both conceptual actions and its.class.name and its.last are both conceptual attributes.

The idea of an it implied block argument comes from the Groovy guys. For example, this is valid Groovy:

[1,2,3,4].each { println it }

From the Groovy documentation on closures, “A closure always has at least one argument, which will be available within the body of the closure via the implicit parameter it if no explicit parameters are defined. The developer never has to declare the it variable – like the this parameter within objects, it is implicitly available.”

It’s about time for Ruby be on the receiving end of language beauty cross-pollination among the current generation of scripting languages.

I released this code in the public domain on RubyForge as the methodphitamine gem. To use, simply do

  • gem install methodphitamine
  • require 'methodphitamine'

When I wrote the Methodphitamine’s RSpec specifications, I noticed that RSpec’s own it() method gets undefined within the scope of each assertion’s block, allowing The Methodphitamine to behave normally even in specs. Very cool, RSpec!

If you discover any issues or have any improvement suggestions, feel free to post on The Methodphitamine Google Group.

It’s now standard in Adhearsion v0.8.0 among many other metaprogramming goodies. :)

Trackbacks

Use the following link to trackback from your own site:
http://jicksta.com/articles/trackback/36

  1. machines ice shaved
  2. Lil Pussy Kim
  3. Young Girls Raped
  4. Women Midget Nude
  5. Free Pics Dickgirl
  6. Rican Puerto Girls
  7. asp From
    asp
  8. Little Girl Very
  9. Panties Shot Anime
  10. pussy dildo
  11. BLOWJOB From
    BLOWJOB
  12. breast adult
  13. Nude Japanese Women
  14. real world nude
  15. pornstar blowjob
  16. george clooney nude
  17. sounds orgasm
  18. transmitted of pictures sexually diseases
  19. upskirt free pictures
  20. XXX Dragonball
  21. Submissive Training
  22. Clit Large From
    Clit Large
  23. free gangbang pics
  24. Skimpy Lingerie Galleries
  25. Naked Batgirl Comics
  26. transexual free
  27. sailor hentai
  28. Naked Hot Nurses
  29. hentai tina
  30. fucking lanasfantasies
  31. cimshots rate
  32. porn pivtures
  33. cock assist fist
  34. underage hentia porn
  35. teen puussy
  36. candy teens
  37. spears/ pussy briyney
  38. analintus From
    analintus
  39. sesy girl From
    sesy girl
  40. squirterss From
    squirterss
  41. ass tteens From
    ass tteens
  42. henti ganes
  43. sexy 0lder women
  44. oiled up girls
  45. ograsm girl sound
  46. free nude beach thumbs
  47. olderwomen.com charlotte
  48. fuck firls school
  49. teenage esx
  50. atinasex From
    atinasex
  51. fuck clips From
    fuck clips
  52. aeris sexy girl
  53. iphone downloads From free iphone downloads
    thanks to this blog for helping us finding the latest iphone downloads, if you have an iphone...
  54. home online jobs From free home online typing jobs
    free home online jobs
  55. Excellent post. Keep it up!
  56. Excellent post. Keep it up!
  57. Sound Of A Girl Moaning While Sex Free
  58. Pre Teen Girls Modeling Swimsuits
  59. Kristen Bell Pictures
  60. Girls Boarding School Premier Spanking Video
  61. Fla Convicted Sex Offenders Database
  62. Porn Bloopers Jameson
  63. White Girls Getting Fucked By Black Dicks
  64. Jutine Film Porno
  65. Diwnloadable Asian Porn Movie For Free
  66. Female Masurbaton Pic
  67. The Best Free Porn Site
  68. Collette Bangbus
  69. Picture Boylove
  70. Erotic Sex Clips
  71. Xxx Hard Sex
  72. American Sex Phito
  73. Sharon Stone Masturbation
  74. girls in the nude free pics
  75. 3d babes wallpaper
  76. misty nude picture pokemon
  77. younggirl sexcom
  78. lyrics to dirty
  79. teen titans sex starfire robin sex
  80. free hentai flash game with toys
  81. plyaboy swim
  82. celebs male nude pix
  83. hot gay boy have sex with penie
Comments

Leave a response

  1. Shadowfiend about 20 hours later:

    Wow, this is totally fantastic, and remarkably simple. Props.

  2. Andreas 1 day later:

    Awesome hack! I just played around with it for a bit, and it’s like Symbol#to_proc on steroids—well done!

  3. Jason L Perry 1 day later:

    That’s so sexy. I’ve wanted to be able to do this since day one. Again, NICE.

  4. 7rans 1 day later:

    Some cool meta programming, for sure.

    One possible improvement: I think you can add respond_to? to the undef_method line, and then get rid of the condition in method missing.

    One thing I should point out though, as of 1.9 it may be easier just to define “it” in Enumerator. Than we’d have a fluent (ie. magic-dot) interface:

    User.find(:all).map.its.contacts.map.its.last_name.capitalize

    Make you want alias #its as #his, #her and #their too ;-)

  5. beppu 2 days later:

    I like this technique. Good job.

  6. Avdi 6 days later:

    Addendum: Nat also posted about an updated syntax for higher-order messages here: http://nat.truemesh.com/archives/000538.html

  7. Wayne 6 days later:

    Neat. I like it, more understandable than symbol to_proc.

    Premature optimization and all that, but seems to be about the same speed as symbol to proc, albeit both are quite a bit slower than the good old fashioned blocks…

    
    >> Benchmark.bm do |b|
    ?>   b.report('normal') { n.times { (1..100).select { |i| i.size } } }
    >>   b.report('method') { n.times { (1..100).select &it.size } }
    >>   b.report('toproc') { n.times { (1..100).select(&:size)  }  }
    >> end
          user     system      total        real
    normal  0.090000   0.000000   0.090000 (  0.093936)
    method  0.490000   0.000000   0.490000 (  0.499792)
    toproc  0.460000   0.000000   0.460000 (  0.474050)
    
  8. Neil Wilson 7 days later:

    Great technique, but does it run like a dog as Symbol#to_proc does?

  9. Anders Engström 7 days later:

    I’ve been thinking about the same problem as well. But my approach was to attack the “chained method calls” instead – as described at: http://www.gnejs.net/2007/04/18/arrayto_proc-nested-properties-for-to_proc-hack/

    The example above would be implemented as: User.find(:all).map(&[:last_name, :capitalize])

    Your variant is more dynamic and more readable though smile.

  10. Stephen Touset 7 days later:

    I posted a slight improvement to Methodphitamine on my blog. Long story short, I add respond_to? to the list of methods to keep around, which lets you take out the hack in method_missing to detect it being called.

    It should be marginally faster, too, since it avoids one more call to method_missing.

    Otherwise, a great hack!

  11. lester bangs 8 days later:

    Dude, you combined two of my favorite things: speed and Ruby.

    Seriously, I love speed. Dextros, rits, adderall, and yes the old standbys coke and meth. Not so much meth though, that shit can get ugly.

    Anyway, like speed, I just can’t get Ruby*. Meaning, I like to talk about it as my favorite language and how it it so much better than the others and what have you, and I bought all the books: Pickaxe, AWDROR, (goddammit I can’t tell you how many time’s I’ve written that abbreviation. mostly from copying the pdf of the book from computer to computer in the hopes that it would actually be used—negative.), Everyday Scripting with Ruby, etc, but when it comes down to it, i realize that if you add up all the time i actually spend sitting down and doing some REAL FUCKING WORK with it, it probably would equal, I don’t know, 2 hours in the past 4 years.

    What is my problem? Is it that I don’t have an actual use for Ruby in Real Life? That’s bullshit. I could think of 15 things right now I could be using Ruby for. Am I holding out for another programming language? Don’t think so… Like I said it’s been 4 years and I am still holding onto Ruby as my language of choice even though I have not written A SINGLE FUCKING RUBY PROGRAM OF MY OWN. Not one—they all come from the canned examples of Messrs. Thomas, et al.

    I know the answer, and you probably do too after reading this. It’s that I have no attention span. Zero. I get enamored with a project and go full-throttle, balls-out for, I don’t know 23 SECONDS and then find a new, cooler, shinier thing to play with.

    You want to talk about text editors? I swear to Christ, one day I had one giant boner after another during a “OK, this will decide which text editor I will use from now until forever” moment. Typing “text editor” into Google was a bad idea—bad like when I decided to do lines of coke before a family reunion. One editor was based on wxWidgets, which required me to download the wxWidgets library and oooh, Ruby has wxWidgets bindings! Hold that though while I go try to make a BLANK CANVAS WITH A TITLEBAR THAT SAYS HELLO WORLD, WONT THAT BE THE BALLS. But wait, WTF am I going to use to input this awesome as fuck application? I need a cool as ass text editor to do it! Also, I heard on some mailing list that Ruby-GTK is the wave of the future, so fuck this wxWidgets shit and bring me the head honcho of that department! Hmmm, GTK, that sounds like Linux. Maybe I should just install Linux if I am going to fuck around with graphics toolkits. Ubuntu looks like pretty easy but I’ll be shit if SuSE didn’t have a kick-assier theme. Wait a minute, Cygwin, you can run UNIX on Windows? That is so awesome I want to have babies with it. Oooooh, Emacs? Should I learn the beast? I saw a screencast with some guy doing things with Rails projects in Emacs that make the TextMate guys lower their heads in shame. Ruby-Vim, though, look at it, it’s like the fucking editor was made for the language. You and the language become one, the binding energy of your fantastical thought process will balance the cosmos with beautiful code AND it will take less keystrokes.

    Beautiful code? Oh you must mean HAML. That shit is so baller that I want to kiss that Hampton Camptown races guy for creating the Haiku shit. The name of the language is like his name! I WANT VERITABLE HAIKU. I HAVE NO IDEA WHAT THAT MEANS BUT I WANT IT. But what about DRYML? That Hobo guy is no slouch either. He is, like, British and shit. And I went through the screencasts—all of them—and was impressed beyond belief. Then the AjaxScaffold project finds its way into my browser and it is all over. Fucking Ajax. I want to make the boxes appear out of nowhere. I want to flash the screen, without Flash. I want. I WANT. WHERE THE FUCK DO I START. Where will it end? It won’t.

    Do you see what kind of person you are all dealing with here? I am spilling out my heart and soul about the epic internal struggle I am having because I SAW A WORD THAT LOOKS LIKE A DRUG I LIKE. I am a passionate person. I have passion. I also have an addictive personality, and I am also excitable. Those don’t mix well. Excitable is a loud bang and then a whimper. Drugs is the same.

    I have no discipline. None. How I got where I am being the way I am is a complete, albeit fortunate, mystery. So I guess for some things, these personality-lifestyle choices don’t have to be mutually exclusive. I have a good job which I excel at, nice place, mostly non-skeevy friends. I think I might have to let this Ruby thing go and realize I was not cut out for such things.

    Anyway, thanks for listening everyone. Good luck with the library or module or whatever the hell they call it in Ruby land. Don’t even get me started about a Proc. I sat down one day after reading about how Proc will make me more productive, streamline my code, save starving children, and cure Polio. It ended up being a COMPLETE AND UTTER MINDFUCK. I could not wrap my brain around this concept, no matter how hard I tried. I firmly believe that I tried so hard to learn this that a singularity developed in my brain that began collapsing in on itself. Had I not found something else to distract me, you all may have not been here to read this due to the black hole that was created as a result, destroying the universe and more importantly me still not knowing what the fuck a Proc is. You’re welcome.

    • By “can’t get” in the context of speed, I mean I can’t acquire it very easily, which is a good thing since I probably would be dead right now if it were easy.
  12. Sylvain 8 days later:

    Simple and efficient, the Ruby way. Great !

  13. Ben Smith 9 days later:

    If you think your way is more readable than the usual Ruby way, you’re insane.

  14. Tuxie 11 days later:

    lester bangs: LOL! That was the funniest junkie gibberish I’ve read in a while.

  15. Sur 13 days later:

    Simply Awesome !!

  16. dominiek 15 days later:

    w000t!!!

  17. robl 15 days later:

    lester bangs deserves their own show, seriously

  18. Logan Koester 21 days later:

    This is the guy we should have writing Ruby books.

  19. schwabsauce 21 days later:

    it was pretty annoying that symbol#to_proc didn’t support any arguments or anything. and it’s quite cool that this word choice doesn’t hurt rspec’s feelings. i still think logic is a more appropriate culprit than magic. the one thing is if its that much of a performance hit, be careful with adhearsion because that library is going to be used billions of times.

  20. Lawrence Pit 3 months later:

    Using Dr. Nic’s map_by_method gem I think this is prettier:

    User.find(:all).map_by_contacts.map_by_last_name.map_by_capitalize

  21. Andres Lambert 4 months later:

    technochemical spied effusive superacknowledgment vadimony heartedness myosarcoma jimpricute http://www.vocabula.com/ >The Vocabula Review (TVR) http://www.pcpafriends.com/

  22. Last Poster 5 months later:

    lester bangs is a genius and should become president of the state of the union. Or should I say America.its.Iraq.its.People.its.Congress.its.Nation.its.Terror.

  23. Mollie Martin 6 months later:

    sarcoline glassfish posthabit jeremian nitrify laggin piazzian controverter http://25x.kzonheh.net/ >Cute Hair Style http://1jk.algcrdeid.net/ http://do.nfwesj.net/ >Adware Remove Spyware http://2an.younhk.net/ http://1ed.marhuv.net/ >Washington Dc Car Accident Attorney http://s2.algcrdeid.net/

Comments