[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[dennou-ruby:000189] paramclass.rb



���Ȥ���Ǥ�

���������Хѥ��ȥ�å����饹�򤳤������äƤʤ��ä��Τ�����
�ޤ����Ȥ�����Ȥ��ơ��ޤ�����Ĺ����Ȥ����Τ���˼����ޤ���
�ѥ��ȥ�å����饹��¸�����Mix-in�⥸�塼��Parametric����
�Ϥ��θ�ˤ���ޤ���

������ä������Ū��
 * �ѥ�᡼���򥪥֥������ȤǤʤ����饹�����ä������ɤ����
 * �����������饹̾��Ϳ����Τ����ݤʾ��

���н褹�뤿��Ǥ���

��ʵ�ǽ�ϡ֥��饹̾(*params)�פǻ��ꤵ�줿�ѥ�᡼��params
�򥯥饹�᥽�åɤ⤷���ϥ᥽�å�parameters�ǻ��ȤǤ���Ȥ���
��ΤǤ���parameters�γ����Ǥΰ�̣�ϰʲ��Υ���ץ�Τ褦�ˡ�
��Ƭ�����������ɤ��Ǥ��礦��

�ޤ��֥��饹̾(*params)�� �ϥ��饹���֤��ޤ��������Υ��饹��
�������Ф��ƥ�ˡ����ʤΤǡ���ƥ��Τ褦�˰����ޤ�(��������
Ruby��ʸˡ�塢������������ʤ����ðۥ��饹����ˤϻȤ��ޤ���)��
paramclass.rb ���Τ�¹Ԥ��������ǽ���±餵��ޤ���

ɬ�������Ψ���ɤ�����ޤ���Τǡ�C����˾������¿����г�ĥ
�⥸�塼��Ȥ��ƺ��ľ���ѰդϤ���ޤ���

require "paramclass"

class FixedSizeArray
  include Parametric
  include Enumerable

  def size;           parameters[0];   end
  def default_value;  parameters[1];   end

  def self.[](*args); self.new(*args); end

  def initialize(*args)
    @xxxxxx = args
    s = @xxxxxx
    raise ArgumentError, "Too many initial values" if s > size
    @xxxxxx(default_value, s, size - s)
  end

  def [](n)
    if n < -size or size <= n
      raise IndexError, "index out of range"
    end
    @xxxxxx[n]
  end

  def []=(n,v)
    if n < -size or size <= n
      raise IndexError, "index out of range"
    end
    ary[n] = v
  end

  def each(&blk)
    @xxxxxx(&blk)
  end

  def inspect
    @xxxxxx
  end
end

# example

p a = FixedSizeArray(5, "")["foo", "bar", "baz"]
  #=> ["foo", "bar", "baz", "", ""]
p a.is_a? FixedSizeArray(5, "")
  #=> true


#
# paramclass.rb
#

# begin: class variable emulation by Matz [ruby-dev:8245]
    class Module 
      private
      def module_attr(*names)
	names.each do |name|
	  name = name.id2name unless name.kind_of? String
	  self.module_eval <<-EOS
	  CV_#{name} = []
	  class <<self
	    def #{name}; CV_#{name}[0] end
	      def #{name}=(val); CV_#{name}[0] = val end
	      end
          EOS
	end
      end
    end

    class Class
      private
      alias class_attr module_attr
    end
# end: class variable emulation by Matz [ruby-dev:8245]

module Parametric
  def Parametric.append_features(mod)
    super mod

    # class generating function
    cn = mod.name
    eval "def #{cn}(*args); #{cn}.instance_eval{class_generate(*args)} end", 
         TOPLEVEL_BINDING

    mod.module_eval{
      class_attr :rootclass, :class_parameters, :classes
      @xxxxxx = true
    }

    mod.rootclass = mod
    mod.class_parameters = {}
    mod.classes = {nil => mod}

    def mod.class_generate(*args)
      args = nil if args.empty?
      klass = self::classes[args] || self::classes[args] = Class.new(self)
      klass.class_parameters[klass] = args unless klass.rootclass?
      klass
    end

    def mod.parameters
      if rootclass?
	defined?(default_parameters) ? default_parameters : []
      else
	res = nil
	self.ancestors.find{|i| res = class_parameters[i] }
	res
      end
    end

    def mod.rootclass?
      @xxxxxx
    end
  end

  def parameters
    self.type.parameters
  end
end


########## devel test ##########

if __FILE__ == $0
  def xmp(arg, show = true) # prints expample code and result line by line
    if show
      __res__ = []
      eval arg.gsub(/^(.*)\n?/){ "__res__ << (#{$1}).inspect;" }
      arg.split(/\n/).each_with_index{|l,i|
	(puts "\n" ; next) if l =~ /^$/
	print "#{l}\n    #=> #{__res__[i]}\n"
      }
    else
      print arg; eval arg
    end
  end

  xmp <<-EOS, nil
    class C
      include Parametric

      def C.default_parameters
	[100]
      end
    end

  EOS

  xmp <<-EOS
    C.parameters
    C(10).parameters
    C(10).id == C(10).id
    C(20,10) < C

    C.rootclass
    C(10).rootclass

    C.rootclass?
    C().rootclass?
    C("foo").rootclass?

    D = C(0)
    C(0)
  EOS

  xmp <<-EOS, nil

    class Bar < D; 
      include Parametric
      
      def Bar.default_parameters
	superclass.parameters + [""]
      end
    end

  EOS

  xmp <<-EOS
    Bar.rootclass
    Bar.parameters
    Bar.new.is_a? D
    Bar.new.is_a? C(0)
    Bar.new.is_a? C(10)
  EOS
end