Monday, February 4, 2013

My Work Clock and Functional Programming

Programming in Scala has made me a better Ruby programmer.  Thank you Scala!


Functional Iterators

I appreciate Functional Iterators much better now.

Given a list of items:

  • If you want to return a single value, after iterating through the list, use reduce.
  • If you want to return a subset of the values, use filter.
  • If you want to return a new list, where each item as likely been transformed, use map.



Example of Using Reduce

Below, is an example of iterating through my list of billable hours in a week to arrive at a single value -- then total number of hours I worked that week for that client.

I use a simple app, My Work Clock, on my phone to track my billable hours.




I simply "Punch In" when I start working and "Punch Out" when I'm done.

It produces a report that I can email to myself in CSV format, which I then open in Libre Office (like MS Excel).




I copy/paste the hours into a Ruby console and run in through a functional programming one-liner to determine my weekly billable hours:


~ $ irb
irb(main):001:0> s =<<TEXT
irb(main):002:0" 8.02
irb(main):003:0" 13.72
irb(main):004:0" 15.87
irb(main):005:0" 10.87
irb(main):006:0" 8.13
irb(main):007:0" TEXT
=> "8.02\n13.72\n15.87\n10.87\n8.13\n"

irb(main):008:0> s.split.reduce(0){|sum, value| sum.to_f + value.to_f}

=> 56.61


Example of Using a Filter

The select function takes two arguments:

  • The list:  ["8.02", "13.72", "15.87", "10.87", "8.13"]
  • Function to apply on each item value; Return only those greater than 10:  number.to_f > 10


# Daily work hours greater than 10 hours

["8.02", "13.72", "15.87", "10.87", "8.13"].select {|number| number.to_f > 10}

=> ["13.72", "15.87", "10.87"]


Example of Using a Map

The map function will return an Array composed of results from the block operation.

The map function takes two arguments:
  • The list of days:  days = %w{ 2013-01-18 2013-01-17 2013-01-16 2013-01-15 2013-01-14 }
  • Function to apply on each item value:  day_hours_hash[d]
Here's the hash:
day_hours_hash = {"2013-01-18" => "8.02", "2013-01-17" => "13.72", "2013-01-16" => "15.87", "2013-01-15" => "10.87","2013-01-14" =>"8.13"}


Return the number of hours worked for each day

days.map {|d| day_hours_hash[d]}

=> ["8.02", "13.72", "15.87", "10.87", "8.13"]



References 


http://ruby-doc.org/core-1.9.3/Enumerable.html
http://railspikes.com/2008/8/11/understanding-map-and-reduce



Sponsor Ads



No comments:

Post a Comment