Berger, Daniel wrote:
There must be a way to ditch that '&' somehow. I'd prefer this:
[1,2,3].all?(:positive?)
What you are suggesting is basically an expansion of something that was
suggested in RCR50 and rejected.
(RCRS)
I like the idea too. It would be even better if you could also pass
parameters along.
Here are a few more examples:
[1,2,3].any?(:>, 4)
[1,2,3].map(:*, 4) #-> [4,8,12]
people.collect(:name)
people.select(:retired?)
people.sort_by(:age)
favorite_numbers.select(:between?, 100,200)
people.each(:give_compensation, 50)
Here's the implementation:
# enumerable-rcr50.rb
class Array
enumerable_methods = [:each,:select, :find_all, :map, :collect,
:any?, :all?,
:sort_by, :reject, :detect, :find, :find_all]
# max_by, min_by, partition_by can be added in
Ruby 1.9
for method_name in enumerable_methods
old_method_name = "old_" + method_name.to_s
module_eval %Q{
alias_method :#{old_method_name}, :#{method_name}
def #{method_name}(message = nil, *args, &block)
block ||= Proc.new { |e| e.send(message, *args) }
if message or block_given?
#{old_method_name}(&block)
else # method was called without passing any
parameters, nor a block
#{old_method_name}
end
end
}
end
alias_method(:do, :each)
alias_method(:in_order_of, :sort)
end
Basically, if the callers passes a block, the original method is called.
If he specifies a message and some arguements, they are converted into a
block and passed to the original method. If he gives both, the block is
used and the message is ignored. If neither is given (as in:
[1,2,3].map), the original method is called with no parameters.
Take note that :detect (and its alias :find) accept an additional
parameter (representing what should be returned if nothing is found), so
changing them WILL break existing code.
Now, I need help. As you may notice - the above only extends Array. If
you change "class Array" to "module Enumerable" in the above code, it
turns out that Ruby (1.8.4) refuses to let you override methods such as
map, while at the same time, "any?" and "all?" work fine. Anyone got a
clue as to how I could fix this?
P.S. for other approaches to this problem, see the Higher Order
Messaging in Ruby articles by Nat Pyrce
(http://nat.truemesh.com/archives/000535.html\), the Junction library,
and Ruby Facets.
···
--
Posted via http://www.ruby-forum.com/\.