Last active
August 29, 2015 14:23
-
-
Save domgetter/c4b75994a0c3e4dfd65e to your computer and use it in GitHub Desktop.
Hash#compose
This file contains 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
# Since a key-value store is a finite, discrete function, and functions | |
# can be composed, then Hashes can be composed. | |
# | |
# The syntactic sugar for calling lambdas, accessing array values, and | |
# other objects which have a #[] method allow composition of Hashes | |
# with all sorts of objects and contexts with the same implementation. | |
# | |
# Play with it at https://eval.in/388458 | |
# | |
class Hash | |
def compose_with(hash, other) | |
each_with_object(hash) {|(k,v), h| h[k]=other[self[k]]} | |
end | |
def compose(other) | |
compose_with({}, other) | |
end | |
def compose!(other) | |
compose_with(self, other) | |
end | |
end | |
# A few examples | |
a = {:name => 2, :email => 7} | |
b = {7 => "[email protected]", 2 => "John"} | |
a.compose(b) | |
#=> {:name => "John", :email => "[email protected]"} | |
a.compose([*"d".."k"]) | |
#=> {:name=>"f", :email=>"k"} | |
a = {name: 0, email: 1} | |
b = ->(i) { i == 0 ? "John" : "[email protected]" } | |
a.compose(b) | |
#=> {:name=>"John", :email=>"[email protected]"} | |
a = {name: 0, email: 1} | |
b = "ab" | |
a.compose(b) | |
#=> {:name=>"a", :email=>"b"} | |
a = {name: :a, email: :b} | |
b = Thread.new do | |
Thread.current[:a] = "John" | |
Thread.current[:b] = "[email protected]" | |
sleep | |
end | |
sleep 0.1 | |
a.compose(b) | |
#=> {:name=>"John", :email=>"[email protected]"} | |
b.kill | |
# Now for some fun | |
class Hash | |
def *(other) #idea taken from: http://jhchabran.com/blog/2012/12/09/fun-with-to-proc-and-compositions/ | |
compose(other) | |
end | |
end | |
{:name => 0, :email => 1} * ["name_url", "email_url"] * {"name_url" => "John", "email_url" => "[email protected]"} | |
#=> {:name=>"John", :email=>"[email protected]"} | |
upcase = ->(str) {str.upcase} | |
{:name => "John"} * upcase | |
#=> {:name => "JOHN"} | |
# Use cases? No idea, but in that lambda example, you could make the lambda hit a database. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment