class Module
  def once_with_args(*methods)
    methods.each do |m|
      class_eval <<-"END_OF_EVAL"
        alias_method :__once_with_args__#{m.to_i}__, :#{m.to_s}
        private :__once_with_args__#{m.to_i}__

        def #{m.to_s}(*args, &block)
          fail "Object shoul be frozen" unless frozen?
          fail "Block handling is not yet implemented in once_with_args" if block_given?
          @@__once_with_args__ ||= {}
          @@__once_with_args__[#{m.to_i}] ||= {}
          @@__once_with_args__[#{m.to_i}][args] ||= __once_with_args__#{m.to_i}__(*args)
            # We should handle &block as parameter, since it might be different each time. I don't know how to do this...
        end
      END_OF_EVAL
    end
  end
end

class Foo
  def calc1(a,b,c)
    p [:org_calc1, [a, b, c]] # DEBUG
    1 #same complicated, time-consuming calculation...
  end

  def calc2(a,b)
    p [:org_calc2, [a, b]] # DEBUG
    2 #same complicated, time-consuming calculation...
  end

  once_with_args :calc1
  once_with_args :calc2
end