Created
June 28, 2011 03:53
-
-
Save jonaphin/1050452 to your computer and use it in GitHub Desktop.
Fun with Hashes and to_proc implementation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
### Jonathan Lancar - https://github.com/jonaphin ### | |
######################### | |
## Simple Hash Example ## | |
######################### | |
class Hash | |
# if argument passed to the hash is a key of it, | |
# call the hash's value (at key) as a method that acts on said key | |
def to_proc | |
proc { |arg| self.has_key?(arg) ? self[arg].to_proc.call(arg) : arg } | |
end | |
end | |
## USE-CASE ## | |
a_hash = {"name" => :upcase, :id => :to_s} | |
params = ["name", :id, 3, 4] | |
params.map &a_hash | |
# => ["NAME", "id", 3, 4] | |
################################ | |
## A More Interesting Example ## | |
################################ | |
=begin *** REASONING *** | |
Hashes are great at data representation. The versatility of the key-value pair scheme is just enough organization | |
for defining any kind of data structure. | |
As a proc, it may feel natural, in a theoritical environment, to boost the Hash's status to dare become the structure it normally represents. | |
Along this line of thinking, I went ahead and made Hash#to_proc transform key-value to Class#method / Class#method(arg) | |
This implementation does not cover all cases, but may serve as a basis for future work in the direction it takes | |
=end | |
class Hash | |
# Processes arg through a method or a series of methods according to arg's type | |
# This implementation matches arg's type to its ancestors as well | |
# Hash can be formed as follows | |
# { | |
# class_type => :method, | |
# class_type => [:first_method, second_method], | |
# class_type => {:method, :argument} | |
# } | |
def to_proc | |
proc { |arg| | |
_type = arg.class | |
if self.has_key_of_type?(_type) | |
_type = key_for_type(_type) | |
if self[_type].is_a?(Hash) | |
arg.send(self[_type].first[0].to_sym, self[_type].first[1]) | |
else | |
self[_type].to_proc.call(arg) | |
end | |
else | |
arg | |
end | |
} | |
end | |
def has_key_of_type?(a_key) | |
self.each_key{|key| return true if a_key < key } | |
false | |
end | |
def key_for_type(a_key) | |
return nil unless has_key_of_type?(a_key) | |
self.each_key{|key| return key if a_key < key } | |
end | |
end | |
## Our example requires the following implementation Array#to_proc ## | |
class Array | |
# Calls each element on arg iteratively | |
# Returns the last iteration (the 'arg' for which all methods have been applied) | |
def to_proc | |
proc { |arg| self.map { |idx| arg = idx.to_proc.call(arg) }.last } | |
end | |
def to_leet | |
tmp = LeetArray.new | |
self.each{|x| tmp.push(x) } | |
tmp | |
end | |
end | |
# Let's also create LeetArray for the sake of testing | |
# if inherited classes also benefit from our proc-ed Hash | |
class LeetArray < Array | |
end | |
## USE-CASE ## | |
a_hash = {String => :downcase, Fixnum => :to_s, Symbol => [:to_s, :upcase], Array => {:join => " "} } | |
params = ["Hello", 3, :world, ["how", "are", "you?"].to_leet] | |
p params.map &a_hash | |
# => ["hello", "3", "WORLD", "how are you?"] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment