Higher Order Messaging in Ruby

Having played around with Ruby for some six months now, I feel confident enough to make my first post on the subject. It’s going be about Higher Order Messaging, and it’s more of an expansion on an excellent description by Nat Pryce. I’m writing this post partly because I feel my implementation is a tad better (less cumbersome, as one need not define a class for each new method), and partly because it feels like his post has gone largely unnoticed.

First of all, let’s talk about blocks. Anyone familiar with Ruby will have some knowledge of blocks. Blocks in Ruby is a way to pass a chunk of code as argument to a function; blocks are also full closures, so they may reference any variables that exist in the scope in which they were declared. An example of block usage:

[0,1,2,3,4].select { |val| val.nonzero? }
=> [1,2,3,4]

As you may know, Enumerable#select loops through a collection and returns a new collection containing those elements for which the block evaluates to true. So, the example above produces the array [1,2,3,4], since Numeric#nonzero? will return false for the first element in the array and true for the others.

I expect this is nothing new for most people. Often however, as in the above example, this syntax seems a little verbose.

Using Symbols

You may have come across a little method in the Ruby Extensions project named Symbol#to_proc. In fact, it seems like this hack soon will be an official part of Ruby. Now to achieve the same results as the example above, we can use,

[0,1,2,3,4].select(&:nonzero?)
=> [1,2,3,4]

which is, if nothing else, more compact. Don’t get me wrong, I love this hack. But some object that this syntax is a bit ugly, and I agree partly, so we want to do this some other way, if possible. By understanding how calling methods works in Ruby, we can construct an alternate syntax.

Using Higher Order Messaging

Higher order messaging consists of the idea that method calls (messages), can be passed as arguments. I’ll spoil the surprise and show right away how our new syntax will look:

[0,1,2,3,4].where.nonzero?
=> [1,2,3,4]

Looks good, doesn’t it? It looks like the method where takes a method call (nonzero?) as its argument, forwards it to each element and collects those for which it returns true. That is kind of what happens, but in a much more complicated way. Most of the magic lies in the where method; it returns an object that responds to nonzero?. The object that is returned from where is an instance of HigherOrderMessage:

class HigherOrderMessage
  instance_methods.each { |method| undef_method(method) unless method =~ /__(.+)__/ }

  def initialize(&proc)
    @proc = proc
  end

  def method_missing(id, *args)
    @proc.call(id, *args)
  end
end

It might look a bit confusing, but it’s actually very simple. First note that all functions that aren’t vital (such as __send__) are unlinked, so they may not be called. Second, when constructing a HigherOrderMessage, a block must be supplied, which is stored in the object. Finally, method_missing is defined. This method is a bit special, because it’s called whenever another method doesn’t exist. The first parameter is the name of the method that was attempted; the second parameter is its arguments.

So far, this code does nothing. It’s a mere skeleton to build some functionality from. This is done by in the implemention of Enumerable#where:

module Enumerable
  def where
    HigherOrderMessage.new do |id, *args|
      select { |x| x.__send__(id, *args) }
    end
  end
end

[0,1,2,3,4].where.nonzero?
=> [1,2,3,4]

Let’s dissect the example above; first where is called. What happens is that a new HigherOrderMessage object is created and returned (for brevity, this object will henceforth be referred to as hom). Furthermore, this object has one instance variable—@proc—that contains the code block that was passed to it.

Then, we’re trying to call hom.nonzero?. Since this method doesn’t exist, hom.method_missing(:nonzero?) is called instead. method_missing forwards the method id and its parameters to the block that is stored in @proc. This block consists of a call to select, which in our example evaluates to { |x| x.__send__(:nonzero?) }, equivalent to { |x| x.nonzero? }. Finally, the array that’s generated is returned.

Now you may realize why all defaults methods (those inherited from Object) were undefined: it’s simply so that all methods are forwarded to method_missing. Otherwise, some_array.where.frozen?, for example, wouldn’t work, because it would check whether the HigherOrderMessage object is frozen or not.

Some Other Methods

Let’s construct some other useful methods: do_each, do_collect and do_inject.

module Enumerable
 def do_each
    HigherOrderMessage.new do |id, *args|
      each { |x| x.__send__(id, *args) }
    end
  end

  def do_collect
    HigherOrderMessage.new do |id, *args|
      collect { |x| x.__send__(id, *args) }
    end
  end

  # Requires Enumerable#inject
  def do_inject(start_value)
    HigherOrderMessage.new do |id, *args|
      inject(start_value) { |a,x| a.__send__(id, x, *args) }
    end
  end
end

a, b = [0,1], [1,2]
[a,b].do_each << 3
[a,b]
=> [[0, 1, 3], [1, 2, 3]]
[0,1,2,3,4].do_inject(0).+
=> 10
[0,1,2,3,4].do_collect * 2
=> [0,2,4,6,8] 

The first line adds a new element, 3, to the array. The second like computes and returns the sum of the given array: 10. The third maps the message *(2) to all elements in the array. All examples demonstrate something that would have been impossible to do with Enumerable#to_symbol: when passing a method call you pass both the method name and its arguments, but when you pass a symbol that’s converted to a proc you can’t pass any arguments. Thus, you could never do [a,b].each(&:<<(3)).

Of course, even more complex stuff can be done. Here’s an example of a method that, seemingly, takes two methods as parameters.

module Enumerable
  def having
    HigherOrderMessage.new do |id, *args|
      HigherOrderMessage.new do |secid, *secargs|
        select { |x| x.__send__(id, *args).__send__(secid, *secargs) }
      end
    end
  end
end

[0,1,2,3,4].having.succ < 3
=> [0,1]

The having method, apart from being very useful, demonstrates something interesting about higher order messaging: it can be chained. Not only does having return a HigherOrderMessage instance, even the block in @proc returns one! That means that [0,1,2,3,4].having.succ returns a HigherOrderMessage object that takes yet another function (in our case, <), applies succ to each element and checks it against <(3). Note that this is different than [0,1,2,3,4].succ.where < 3, which would return an array of successors rather than objects from the original array.

A warning: while operators like <, >, ==, and so on may be used in these functions, != mustn’t. From my understanding this is due to a != b being a short form of !(a == b). (E.g., [0,1,2,3,4].succ.where != 3 would expand to !([0,1,2,3,4].do_collect.succ.where == 3), which is false.

Final Words

This is not meant as a replacement for blocks in collection manipulation, but maybe a replacement for Symbol#to_proc. Higher order messaging has, in my opinion, the following advantages:

  • The syntax less wordy than using a block.
  • It’s more flexible than using Symbol#to_proc since you’re effectively forwarding a method call rather than just a method.

It’s not without its problems though. First of all, I’d like to see a version where we can drop the “do_” part of the methods that already exist in Enumerable, and instead have a general function that can either take a block and work like normal, or not take one and behave like a higher order message. And secondly, the implementation itself: right now, this is more of a hack than anything else. It’s probably slower than using a block. And it’s not really tested. At all.

Source code.

91 Responses to “Higher Order Messaging in Ruby”

  1. Bartek Says:

    Sir, this post has left me humbled and afraid. And a little peckish.

  2. Daniel Berger Says:

    Here’s an idea - let’s just modify the methods in Enumerable to accept arguments instead of adding extra syntax that does nothing more than shift the block to the left.

    - Dan

  3. Mike Zillion Says:

    This is so lovely. I’ve never much liked Ruby’s block messaging syntax, despite being impressed by its power. I am very anxious to see how the community responds as this approach matures.

  4. Mike Meng Says:

    Thanks! You teach me a lot.

    Inspired by your work, I think it may be more natrual to keep ’select’ as the HOM name.

    class Array
    alias :old_select :select
    def select(&p)
    if block_given? # conventional call, followed by a block
    old_select(&p)
    else
    HigherOrderMessage.new do |id, *args|
    old_select { |x| x.__send__(id, *args)
    end
    end
    end

    So that we can say:
    (1..100).to_a.select.odd?

  5. Mike Meng Says:

    HTML support?

    class Array
    alias :old_select :select
    def select(&p)
    if block_given? # conventional call, followed by a block
    old_select(&p)
    else
    HigherOrderMessage.new do |id, *args|
    old_select { |x| x.__send__(id, *args)
    end
    end
    end

  6. Istarius Says:

    Thanks for the comments.

    Daniel Berger:

    I see what you mean. While the methods I wrote here were more meant to demonstrate what HOM is and what it can do, it’s true that blocks fills the same functionality and more. It’s still an interesting design pattern, if you ask me. So to clarify: using these specific methods in code for a real project is not something I advise, but learning what HOM is, that can be useful.

    Mike Meng:

    It might be a good idea; however, I’ve got something against overriding methods. So for this example I decided to make new methods instead. Oh, and by the way, I’m pretty much running default Wordpress, so markup in comments are a bit lacking (in fact, I don’t think any kind of markup is allowed). Sorry about that.

  7. Mike Meng Says:

    Thanks. I agree your consideration. Since do_each, do_collect, do_inject and (if ‘do_select’ is used instead of ‘where’) do_select share almost same code, I suggest :

    class Array
    instance_methods.select {|m| [:select, :each, :collect, :inject].include? m.to_sym}.each {|m|
    module_eval

  8. Mike Meng Says:

    Hi Istarius, I’m not complaining, but your comment template system is REALLY broken!

    Try paste my code again:
    class Array
    instance_methods.select {|meth| [:select, :each, :collect, :inject].include? meth.to_sym}.each do |meth|
    module_eval

  9. Mike Meng Says:

    Faint, I give up.

  10. Istarius Says:

    It’s the default system, I guess I should try to find something else that works. And that’s only one of the little quirks I dislike about WP, I might be looking to move on to something else soon…

    Anyway, I see what you’re getting at (I believe), and that’s an excellent idea.

  11. Dopey Says:

    Check out Dr. Nic’s recent work on map_by_method.

  12. Nat Says:

    Cool! That’s a really nice redesign, much better than the way I wrote it originally.

    Do you want to contribute that into the Homer project on RubyForge?

  13. 17 Says:

    Cheap 17…

    Site 17…

  14. 4 Says:

    Read 4…

    You 4…

  15. Ftop Says:

    About ftop…

    Site ftop…

  16. Italy Says:

    My italy…

    Read italy…

  17. Topnado Says:

    Blog topnado…

    My topnado…

  18. Top Says:

    Popular top…

    Cheap top…

  19. Alexvtgoi Says:

    Hello, my name is Alex, i’m a newbie here. I really do like your resource and really interested in things you discuss here, also would like to enter your community, hope it is possible:-) Cya around, best regards, Alex!

  20. BlackBox : My Groovy HOM Says:

    […] A friend of mine sent me this link a while back on Higher Order Messaging in Ruby, which tracks back to this original post on HOM in Ruby and eventually tracks back to a presentation given on HOM in Objective-C. […]

  21. ivagyn Says:

    Hi My Name Is ivatnn.

  22. fajna piosenka Says:

    ABC24…

    chuj w dupe policji…

  23. lijxwobtbz Says:

    Hello! Good Site! Thanks you! zmhfuhyztiajew

  24. suzuki chicago Says:

    suzuki chicago…

    ka-ka-sh-ka 4036326 Value information about suzuki chicago…

  25. interface ipod renault Says:

    2007 jeep tj…

    mazda miata roll bar…

  26. tabkaeevtf Says:

    wrizk

  27. yhfnnvbyym Says:

    cvqvoi

  28. chat latin yahoo Says:

    chat latin yahoo…

    ka-ka-sh-ka 4036326 Advantages of chat latin yahoo….

  29. mature ebony nude Says:

    mature ebony nude…

    ka-ka-sh-ka 4036326 Aggregator of mature ebony nude sites…

  30. nn amateur teen Says:

    nn amateur teen…

    ka-ka-sh-ka 4036326 nn amateur teen moves…

  31. Free XXX Video Says:

    Porno Tie…

    Free Newest XXX Video…

  32. nude asian porn Says:

    nude asian porn…

    Features of nude asian porn….

  33. free nude indian models Says:

    free nude indian models…

    Fresh news on free nude indian models….

  34. Web 2.0 Announcer Says:

    Higher Order Messaging in Ruby…

    […]Higher order messaging is a pattern that allows a more object-oriented approach of manipulating objects, by accepting a method call as a parameter to another method. A rough version of this can easily be implemented in Ruby.[…]…

  35. Zmajrfc Says:

    http://3.kikysexx.info x

  36. cya Says:

    grassrootsyouth…

    grassrootsyouth…

  37. Timati Says:

    http://www.clubsguide.com.au/forum/viewtopic.php?t=1967

  38. car insurance esure Says:

    esure car insurance car insurance esure

  39. Jenifer Marks Says:

    hi
    enj90i3ljsv42yoa
    good luck

  40. Leann Holder Says:

    hi
    enj90i3ljsv42yoa
    good luck

  41. yamaha service manual Says:

    Interesting article, i have bookmarked your site for future referrence :)

  42. Natalia Says:

    Super artykul, dzieki!

  43. Power Says:

    ciekawy artykuł, polecam uwadze, warto

  44. melony Says:

    kqIVYR http://cgE8hcmk9Vvqlosr5wcBa6nk.com

  45. Mqoxvzfe Says:

    Very Good Site nonnude tween model 8-(( switerland teen models lcnxnm teen models depraved stnam teen potsdam model xkqtzc model boys tgp >:DDD

  46. Ivodoexv Says:

    It’s funny goodluck Theadulttube
    6703 Porntoshare
    7561 Dipvid
    559616 Pornwondervids
    78234 Pussism
    :-[[ Pontuvideox
    8-)) Barely18xxx
    8-OO Sexvidia
    :O Videhoe
    ypdgl Deepworx
    6777

  47. air max 92 Says:

    This might be a actually very good read for me, Ought to confess that you simply???¨º?¨¨re among the quite best bloggers I in fact noticed.Thanks for posting this informative article.

  48. L-Lysine Side Effects %0B Says:

    ,*. I am really thankful to this topic because it really gives up to date information *.~

  49. hornMoicaLoarienogreen Says:

    watch the green hornet movie [url=http://www.rhrealitycheck.org/user/downloadthegreenhornet2011]green hornet trailer[/url] download 2011 3D

  50. buy Keflex Says:

    Good luck getting people behind this one. Though you make some VERY fascinating points, youre going to have to do more than bring up a few things that may be different than what weve already heard. What are trying to say here? What do you want us to think? It seems like you cant really get behind a unique thought. Anyway, thats just my opinion.

  51. Movie Trailers Review Says:

    I wonder if some of this content may have been duplicated from elsewhere, it’s all over the net and various peoples websites, unless you’re the content’s creator?

  52. squash Poznan Says:

    That is the appropriate blog for anybody who wants to find out about this topic. You realize so much its nearly exhausting to argue with you (not that I truly would need…HaHa). You positively put a new spin on a subject thats been written about for years. Nice stuff, simply great!

  53. chipewyan Says:

    we must definitely you need to be pleased for that mothers and fathers as an alternative to pondering the item

  54. juleefir Says:

    The original online “no prescription necessary” pharmacy and prescription medication information site. - How much dosing - Buy cheap viagra .? pharmacology exam questions grayston company medical?..

  55. naprawa sterownika abs cadilac Says:

    Make sure you excuse my my English speak, i am just schooling. I significantly like your site greatly, I find it quite attention-grabbing and that i saved a bookmark in my personal internet.

  56. Swerpopydroge Says:

    Buy cheap Adobe Premiere CS5 Pro Oem Software Version
    Buy cheap Acronis Disk Director Suite 10 Oem Software Version
    Buy cheap Atomic Time Synchronizer 4.5 Oem Software Version
    Buy cheap ConceptDraw MINDMAP for Projects 6.2.2.0 Oem Software Version
    Buy cheap Systweak Advanced System Optimizer 3.0 Oem Software Version

    buying online Utilities in Port St. Lucie

  57. bygg stockholm Says:

    Intressant inlägg och tack för att dela. Vissa saker här inne har jag inte tänkt på before.Thanks

  58. nudesexy Says:

    Have you ever thought about adding a little bit more than just your articles? I mean, what you say is important and all. However think of if you added some great images or videos to give your posts more, “pop”! Your content is excellent but with pics and clips, this site could definitely be one of the greatest in its niche. Superb blog!

  59. Loraine Anderson Says:

    At times i ponder about why modern society has become just like this. It really is just depressing :(. I’m going to go consume a beer and relax now! sorry if i got everyone down.

  60. alexa traffic booster Says:

    I am curious to find out what blog system you happen to be using? I’m experiencing some minor security issues with my latest website and I would like to find something more risk-free. Do you have any solutions?

  61. Extended Auto Warranties Says:

    Auto Warranty …

    […]below you’ll find the links to some web sites that we believe you should see[…]…

  62. du hoc nhat ban Says:

    I like this article. I search it from google. Can I copy to my facebok? . Regards

  63. Donny Boyer Says:

    Between me and my husband we’ve owned more MP3 players over the years than I can count, including Sansas, iRivers, iPods (classic & touch), the Ibiza Rhapsody, etc. But, the last few years I’ve settled down to one line of players. Why? Because I was happy to discover how well-designed and fun to use the underappreciated (and widely mocked) Zunes are.

  64. rock bottom blueprint Says:

    You can never tell your good intentions when you just read and observe from the viewers point of view, that is unless you give a good comment such as this one! Great job mate.

  65. Antoine Rhoan Says:

    Very good publish, I identified this just in time. I’m gonna hold this web site bookmarked for future reseach. cheers Mate.

  66. tv weather girls Says:

    Thanks sharing this kind of useful blog in order to people.I’ve been recently stopping by for some time now, i would like to inform you!

  67. Donetta Hillesland Says:

    Would you be concerned with exchanging links?

  68. Shawana Madhavan Says:

    The actual posting could share what it needs to convey to your scaners. It has been a very effective technique which resulted to some successful expenditure for anyone who have been lucky enough to find the item!

  69. Bpjgytey Says:

    Why did you come to ? sexy preteens
    =[[[

  70. Xilcsaqe Says:

    I sing in a choir nn pre models movies nud
    15107

  71. Vsjozphz Says:

    I’d like to open an account www nude lolitas com 02407

  72. payday loans canada Says:

    Jag var imponerad av hur du uttryckte dina tankar om I, Istarius » Blog Archive » Higher Order Messaging in Ruby. Jag kan inte tror att någon kan skriva en fantastisk historia som Thet om jag älskar I, Istarius » Blog Archive » Higher Order Messaging in Ruby.

  73. transport car Says:

    Howdy! Do you use Twitter? I’d like to follow you if that would be okay. I’m undoubtedly enjoying your blog and look forward to new updates.

  74. nrjbrpcjvu Says:

    ixofjmfhbdzpguifnpc, http://www.ygaxbkvbxe.com kjjumuwpqe

  75. Mvaqincb Says:

    How long are you planning to stay here? Nn Child Models Galleries 8985

  76. Tguvqkuj Says:

    I’d like to send this letter by Teenie Toplist 132

  77. Al Johnson Says:

    You have a terrific blog here! would you like to make some invite posts on my blog?

  78. Deana Slechta Says:

    I have not checked in here for some time as I thought it was getting boring, but the last several posts are great quality so I guess I’ll add you back to my daily bloglist. You deserve it my friend

  79. Zvfkgalg Says:

    We were at school together Nn Lolita Model
    267

  80. Inteligentny Dom Says:

    Needed to send you that very little remark in order to say thank you the moment again for the incredible knowledge you’ve shared on this site. It’s really shockingly open-handed with people like you to supply easily exactly what a number of people might have sold for an e-book in order to make some profit for their own end, specifically considering the fact that you could have tried it if you desired. Those tricks also acted to become fantastic way to realize that other people online have similar passion the same as my own to figure out very much more in respect of this matter. I believe there are a lot more enjoyable opportunities in the future for folks who examine your blog post.

  81. Bupxrpuu Says:

    How much is a First Class stamp? Preteen Models
    =-((

  82. Renetta Kobylski Says:

    Thank you, I’ve just been searching for information about this topic for a whilst and yours is the greatest I’ve discovered till now. But, what in regards towards the conclusion? Are you sure concerning the supply?

  83. Arcelia Rm Says:

    May His come bring you peace and blessings this Christmas !

  84. Irmgard Jayes Says:

    What would most of us do devoid of the magnificent thoughts you share on this website? Who comes with the tolerance to deal with essential topics in the interest of common readers like me? My spouse and i and my pals are very fortunate to have your website among the ones we often visit. Hopefully you know how much we enjoy your efforts! Best wishes from us all.

  85. Johnson Brannick Says:

    Hey very cool website!! Man .. Beautiful .. Amazing .. I’ll bookmark your web site and take the feeds also¡KI am happy to find so many useful info here in the post, we need develop more strategies in this regard, thanks for sharing. . . . . .

  86. abercrombie & fitch homme Says:

    “The generals, who took power after the 18-day uprising that pushed Mubarak out, were clearly hoping their successful shepherding of election would deflate the wave of protests against them that erupted 10 days ago.

  87. % Says:

    That is truly brilliant news flash. I appreciate you for sharing the item with us all!

  88. glycolic peel Says:

    I was thinking if I could get this information in my site. I will provide a link to your website, can I?

  89. Buy iPhone 4S Says:

    I just subscribed to your website for much more great information, please do so!

  90. Kassandra Koeneman Says:

    There are incredibly lots of details like this take into consideration. That’s a great point out talk about. I offer the thoughts above as general inspiration but clearly you’ll discover questions such as 1 you bring up the place that the most crucial thing will probably be inside the honest excellent faith. I don?t know if guidelines have emerged about such items as that, but I am positive that your job is clearly known as a fair game. Both boys and girls have the impact of basically a moment’s pleasure, for the rest of their lives.

  91. Valery Allston Says:

    of course like your web-site but you have to check the spelling on several of your posts. A number of them are rife with spelling problems and I find it very troublesome to tell the truth nevertheless I will surely come back again.

Leave a Reply