Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Exploring #to_proc

Exploring #to_proc

A look at how some "odd syntax" introduced in Rails 1.1 and then added to Ruby itself might not solely be for the sake of convenience but hint at a more powerful idea seen in other programming languages. Presented at the March 2015 London Ruby User Group.

Paul Mucur

March 09, 2015
Tweet

More Decks by Paul Mucur

Other Decks in Technology

Transcript

  1. result  =  []   [1,  2,  3].each  do  |number|  

       result  <<  number.to_s   end
  2. “When you say names.map(&xxx), you’re telling Ruby to pass the

    Proc object in xxx to the map method as a block. If xxx isn’t already a Proc object, Ruby tries to coerce it into one by sending it a to_proc message.” — Dave Thomas, “Programming Ruby”
  3. class  Symbol      def  to_proc        

     Proc.new  {  |obj|  obj.send(self)  }      end   end
  4. (def  person  {:name  "Bob",  :age  42})   ! (person  :name)

      ;;=>  "Bob"   ! (person  :height)  
  5. (def  person  {:name  "Bob",  :age  42})   ! (person  :name)

      ;;=>  "Bob"   ! (person  :height)   ;;=>  nil
  6. person  =  {  name:  "Bob",  age:  42  }   !

    name,  age  =  [:name,  :age].map(&person)  
  7. person  =  {  name:  "Bob",  age:  42  }   !

    name,  age  =  [:name,  :age].map(&person)   #=>  ["Bob",  42]
  8. [:yes,  :yes,  :no,  :yes].map(&{yes:  1,  no:  0})   #=>  [1,

     1,  0,  1] http://blog.japila.pl/2011/01/maps-as-data-structures-in-clojure-are-functions-of-their-keys-a-nifty-use-case/
  9. class  Hash      def  to_proc        

     Proc.new  {  |key|  self[key]  }      end   end
  10. class  Hash      def  to_proc        

     proc  {  |key|  self[key]  }!    end   end
  11. class  Hash      def  to_proc        

     method(:[]).to_proc      end   end
  12. class  Array      def  to_proc        

     method(:[]).to_proc      end   end
  13. (def  banned  #{"Steve"  "Michael"})   (def  guest-­‐list  ["Brian"  "Josh"  "Steve"])

      ! ! http://blog.jayfields.com/2010/08/clojure-using-sets-and-maps-as.html
  14. (def  banned  #{"Steve"  "Michael"})   (def  guest-­‐list  ["Brian"  "Josh"  "Steve"])

      ! (remove  banned  guest-­‐list)   http://blog.jayfields.com/2010/08/clojure-using-sets-and-maps-as.html
  15. (def  banned  #{"Steve"  "Michael"})   (def  guest-­‐list  ["Brian"  "Josh"  "Steve"])

      ! (remove  banned  guest-­‐list)   ;;=>  ("Brian"  "Josh") http://blog.jayfields.com/2010/08/clojure-using-sets-and-maps-as.html
  16. banned  =  Set["Steve",  "Michael"]   guest_list  =  ["Brian",  "Josh",  "Steve"]

      ! guest_list.reject(&banned)   #=>  ["Brian",  "Josh"]
  17. class  Set      def  to_proc        

     proc  {  |element|  element  if  member?(element)  }      end   end
  18. http://blog.jayfields.com/2010/08/clojure-using-sets-and-maps-as.html old_orders  =  {  1  =>  44,  2  =>  33

     }   new_orders  =  {  1  =>  55,  2  =>  33  }   ! ! ! ! ! ! ! ! ! !
  19. http://blog.jayfields.com/2010/08/clojure-using-sets-and-maps-as.html old_orders  =  {  1  =>  44,  2  =>  33

     }   new_orders  =  {  1  =>  55,  2  =>  33  }   ! require  'active_support/core_ext/hash/diff'   old_orders.diff(new_orders).keys   #=>  [1]   ! ! ! ! ! !
  20. http://blog.jayfields.com/2010/08/clojure-using-sets-and-maps-as.html old_orders  =  {  1  =>  44,  2  =>  33

     }   new_orders  =  {  1  =>  55,  2  =>  33  }   ! old_orders.dup.      delete_if  {  |k,  v|  new_orders[k]  ==  v  }.      merge!(new_orders.dup.delete_if  {  |k,  v|  old_orders.has_key?(k)  }).keys   #=>  [1]   ! ! ! ! !
  21. http://blog.jayfields.com/2010/08/clojure-using-sets-and-maps-as.html old_orders  =  {  1  =>  44,  2  =>  33

     }   new_orders  =  {  1  =>  55,  2  =>  33  }   ! order_differences  =  old_orders.merge(new_orders)  {  |_key,  oldval,  newval|      oldval  !=  newval   }   #=>  {1=>true,  2=>false}   ! ! ! ! !
  22. http://blog.jayfields.com/2010/08/clojure-using-sets-and-maps-as.html old_orders  =  {  1  =>  44,  2  =>  33

     }   new_orders  =  {  1  =>  55,  2  =>  33  }   ! order_differences  =  old_orders.merge(new_orders)  {  |_key,  oldval,  newval|      oldval  !=  newval   }   #=>  {1=>true,  2=>false}   ! order_ids  =  new_orders.keys   #=>  [1,  2]   ! !
  23. http://blog.jayfields.com/2010/08/clojure-using-sets-and-maps-as.html old_orders  =  {  1  =>  44,  2  =>  33

     }   new_orders  =  {  1  =>  55,  2  =>  33  }   ! order_differences  =  old_orders.merge(new_orders)  {  |_key,  oldval,  newval|      oldval  !=  newval   }   #=>  {1=>true,  2=>false}   ! order_ids  =  new_orders.keys   #=>  [1,  2]   ! order_ids.select(&order_differences)   #=>  [1]
  24. http://blog.jayfields.com/2010/08/clojure-using-sets-and-maps-as.html old_orders  =  {  1  =>  44,  2  =>  33

     }   new_orders  =  {  1  =>  55,  2  =>  33  }   ! Hash[new_orders.to_a  -­‐  old_orders.to_a].keys   #=>  [1]   ! ! ! ! ! ! !