The Artima Developer Community
Sponsored Link

Ruby Buzz Forum
A Block Costume

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Red Handed

Posts: 1158
Nickname: redhanded
Registered: Dec, 2004

Red Handed is a Ruby-focused group blog.
A Block Costume Posted: Dec 23, 2005 11:42 AM
Reply to this message Reply

This post originated from an RSS feed registered with Ruby Buzz by Red Handed.
Original Post: A Block Costume
Feed Title: RedHanded
Feed URL: http://redhanded.hobix.com/index.xml
Feed Description: sneaking Ruby through the system
Latest Ruby Buzz Posts
Latest Ruby Buzz Posts by Red Handed
Latest Posts From RedHanded

Advertisement

We follow Block, who goes into a cloak room and emerges with a change of fashion. A black hat for its dark magic, a dagger for its villianous theft of an instance’s binding, and a glimmering red ring for its metaprogramming fu.

Hey, would you look at that? Blocks actually look pretty good as unbound eigenmethods!

The Cloaker

Let’s say we have an HTML class for building HTML. Here’s the short dressing method:

 class HTML
   def cloaker &blk
     (class << self; self; end).class_eval do
       define_method :cloaker_, &blk
       meth = instance_method( :cloaker_ )
       remove_method :cloaker_
       meth
     end
   end
 end

Giving Parents to the Kids

You’re probably used to seeing code by now, in Rails and Builder and other meta-heavy libs, which passes a single class into a block for tooling with.

For example, in Builder, you’ll make an XML file like this:

 xml = Builder::XmlMarkup.new :indent => 2
 xml.person do |b| 
   b.name("Jim")
   b.phone("555-1234")
 end

As you get deeper in the XML file, you pass down each element to its kids using a block variable. In the above example: b.

Now, I ask, what is self in the above example? Well, it’s set to whatever instance is self in the encompassing scope.

Self Theft

Let’s use a cloak so our block can steal the soul of self.

 class HTML
   TAGS = [:html, :head, :title, :body, :h1, :h2, :h3, :div]
   def initialize &blk; html &blk end

   def method_missing tag, text = nil, &blk
     raise NoMethodError, "No tag `#{tag}'" unless TAGS.include? tag
     print "<#{tag}>#{text}" 
     if blk
         cloaker(&blk).bind(self).call
     end
     print "" 
   end
 end

Now when we attach the block, you’ll be able to run methods freely inside the block, as if you were inside a singleton instance method.

 title = "My Love is Like a LaserJet Set at 300 DPI" 
 sub = "Poetry Selections from Kinko's Employees" 
 HTML.new do
   head do
     title title
   end
   body do
     h1 title
     h2 sub
     div "Oh, Toner! How it doth trickle down the arms!" 
   end
 end

The evil part is how the namespaces wash together. Check out that fifth line. The title method and title var cozy up just fine. A huge problem with this code is that methods in the block’s scope still take precedence. (Try adding: def title; end right before the first line.)

You can use self explicitly in those cases. Anyway, the full test script is here. (Hack inspired by override_method.)

Read: A Block Costume

Topic: Thesis finished Previous Topic   Next Topic Topic: Productivity Arbitrage

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use