Ruby: Introducing Super-Each

October 28th, 2006

Eine möglicherweise halbwegs sinnvolle Anwendung für den Proxy den ich hier vorgestellt habe.

Es wurmt mich manchmal, für das Aufrufen einer einzigen Methode in einem Enumerable dieses hässliche Klammerkonstrukt bemühen zu müssen:

Array#each{ |o| o.method }

Das geplante Symbol#to_proc sieht auch nicht viel besser aus:

%w[dsf fgdg fg].map(&:capitalize)  # =>  ["Dsf", "Fgdg", "Fg"]

Die Lösung:


    module Eachable

      class EachWrapper
        instance_methods.each do |m|  
          undef_method m unless m =~ /(^__|^nil\?|^send)/  
        end

        def initialize(args)  
          @target = args  
        end

        def method_missing (method, *args, &block)  
          @target.each do |elem|
            elem.send(method, *args, &block)
          end
        end

      end

      def supereach (*args, &block)
        if block_given?
          self.each(*args, &block)
        else
          return EachWrapper.new(self)
        end
      end

    end

    class Array
      include Eachable
    end

    chars = %w(a b c d)
    chars.supereach.upcase!
    puts chars.inspect   # => ["A", "B", "C", "D"]
 

Viel schöner.
Problem: das sollte nicht supereach, sondern each heissen. Das wird im moment noch verhindert:

  1. die Implementierung verwendet selbst each
  2. die Art wie Ruby das include Eachable verarbeitet, verhindert dass Array#each überschrieben wird.

Morgen, wenn meine Augen nicht mehr so schmerzen, finde ich eine Lösung.

Leave a comment