The Artima Developer Community
Sponsored Link

Ruby Buzz Forum
Counting At The Cloak 'N' Bind

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.
Counting At The Cloak 'N' Bind Posted: Jun 27, 2006 7:39 PM
Reply to this message Reply

This post originated from an RSS feed registered with Ruby Buzz by Red Handed.
Original Post: Counting At The Cloak 'N' Bind
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

So Method#to_proc is basically totally bankrupt. It is now the most severely mocked typecast in the book. From RailsConf:

 [10, 20, 30].map &4.method(:+)
 ary.each &(hsh={}).method(:store)
 def initialize(hsh)
 hsh.each &method(:instance_variable_set)
 end

Clearly, fun stuff. But, you know, bankrupt.

If you don’t mind drawing a bit more blood, did you know you can use this stuff to kill (\w+)_with_index?

 %w[joe tim francis].map &with_index { |x| [x, index] }
 #=> [["joe", 0], ["tim", 1], ["francis", 2]]

Here’s how it works: the index accessor is added to the Proc. And each time we loop, the accessor is incremented.

It takes some glue, though. Proc#bind (from Rails, originally cloaker) is used to turn the block into a method of itself! Then with_index adds an incrementing wrapper over it. The Method#to_proc happens when you amp it into each.

 # from activesupport
 class Proc
 def bind(object)
 block, time = self, Time.now
 (class << object; self end).class_eval do
 method_name = "__bind_#{time.to_i}_#{time.usec}" 
 define_method(method_name, &block)
 method = instance_method(method_name)
 remove_method(method_name)
 method
 end.bind(object)
 end
 end
 # there are three interesting variables here:
 # blk:: the block you've passed in.
 # bound:: the same block, but now a method of itself.
 # wrap:: the wrapper proc which does the counting.
 def with_index(&blk)
 class << blk
 attr_reader :index
 def even; @index % 2 0 end
 def odd; @index % 2 1 end
 end
 i = 0
 bound = blk.bind(blk)
 wrap = proc do |a|
 blk.instance_variable_set(’@index’, i)
 x = bound[a]
 i += 1
 x
 end
 wrap
 end

Now, for some exercises:

 >> %w[joe tim francis].map &with_index { |x| [x, index] }
 => [["joe", 0], ["tim", 1], ["francis", 2]]
 >> %w[badger goat mule eagle shark].select &with_index { even }
 => ["badger", "mule", "shark"]

However, 1.9’s Enumerator#with_index is definitely less boggling and sloppy. If you have instance variables inside the block, they’ll be lookin in the block object for a home.

Read: Counting At The Cloak 'N' Bind

Topic: RailsConf and Rails 1.2 Previous Topic   Next Topic Topic: The Power of the Marginal

Sponsored Links



Google
  Web Artima.com   

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