After watching Sean Cribb’s fascinating talk on the resources and WebMachine at RubyConf 2011, it got me thinking about the complexity of the state machine transitions involved in his diagram of an HTTP request. I decided to hack this together this morning just for fun. Disclaimer - I realize this isn’t the most effective way of doing, well, pretty much anything. Just a fun hack.
If2D (github) is a quick DSL for producing two dimensional if statements in an excessively readable format. You supply the columns, rows, and resulting values. Column and row headings are defined via lambda’s, which will be given the object to evaluate, and must return a truthy or falsy value.
Headers are evaluated left to right (for columns) and top to bottom (for rows). If multiple header lambdas return true, all the matching result values will be returned in an array.
A quick example of a weekend schedule with If2D:
schedule = If2D.new do
col l{|d| d.friday?}, l{|d| d.saturday?}, l{|d| d.sunday?}
row l{|d| d.morning?}, :snooze, :sleep_late, :church
row l{|d| d.noon?}, :pizza, :hot_dog, :brunch
row l{|d| d.night?}, :party, :trivia, :laundry
end
The l in front of those lambdas is just a proxy for the lambda keyword itself, for brevity’s sake.
Now, if we give schedule a Time object (monkey-patched to respond to the time of day checks), we get:
[1] pry(main)> t = Time.new # 12:24pm Sunday
=> 2012-01-01 12:24:57 -0500
[2] pry(main)> schedule.evaluate(t)
=> :brunch
If you’ve got a lot of columns and don’t feel like breaking out that horizontal scrollbar in your code editor, just repeat the col and row calls again - If2D will simply append further calls on to the existing structure as if it was all on a single line:
schedule = If2D.new do
col l{|d| d.monday?}, l{|d| d.tuesday?}, l{|d| d.wednesday?}, l{|d| d.thursday?}
row l{|d| d.morning?}, :run, :snooze, :late, :run_again
row l{|d| d.noon?}, :subway, :leftovers, :chipotle, :meeting
row l{|d| d.night?}, :tv, :volleyball, :sailing, :hacking
col l{|d| d.friday?}, l{|d| d.saturday?}, l{|d| d.sunday?}
row l{|d| d.morning?}, :late_again, :sleep_late, :church
row l{|d| d.noon?}, :pizza, :hot_dog, :brunch
row l{|d| d.night?}, :party, :trivia, :laundry
end
schedule.evaluate(Time.now) # midday Sunday
# => :brunch
If I’ve got more free time (ha), I may refactor to IfND: n-dimensional if statements!
Hey! If you like what you see, how about following me here or Twitter!