From: Logan Capaldo Date: 2006-05-17T05:44:18+09:00 Subject: Re: Enumerable#collect and #select best practices On May 16, 2006, at 2:48 PM, Daniel Schierbeck wrote: > Joe Bowers wrote: >> This looks like prime .inject territory >> enum.inject([]) do |l,obj| (l << obj.a_method) if >> obj.respond_to? :a_method >> end > > Wonderful! > > Now, what if I wanted to generalize it? That is, a method on > Enumerable that returns an array of the results of calling a a > given block with each item in the array, excluding the items that > do not respond to that method. > > This is what I've got: > > module Enumerable > # need a better name... > def collect_x > collect do |obj| > begin > yield obj > rescue NoMethodError > nil > end > end.compact > end > end > > Though it's still verbose... > I don't think you should use #compact. What if #a_method happens to return nil as a result? Also rescuing NoMethodError, is risky if you have a bug inside #a_method. I would write it: module Enumerable def selective_collect(msg_name, *args) inject([]) do |result_list, value| if value.respond_to? msg_name result_list << value.send(msg_name, *args) end result_list end end end x = [ ... ] x.selective_collect(:a_method) of x.selective_collect(:another_method, "hello")