V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
yangff
V2EX  ›  Ruby

一个小玩具

  •  
  •   yangff · 2015-06-08 19:20:34 +08:00 · 3356 次点击
    这是一个创建于 3546 天前的主题,其中的信息可能已经有所发展或是发生改变。
    class Symbol
    def [](*args)
    a = [self, args, '[]']
    a.instance_eval('@_type_flag = \'[]\'')
    a
    end
    def <<(*ary)
    a = [self, ary.flatten, '<']
    a.instance_eval('@_type_flag = \'<\'')
    a
    end
    end
    class Array
    def < (*ary)
    raise NoMethodError, "undefined method `<' for Array:Class", caller(1) if @_type_flag.nil?
    a = [self, ary.flatten, '<']
    a.instance_eval('@_type_flag = \'<\'')
    a
    end
    alias old_ll <<
    def << (*args)
    return old_ll *args if @_type_flag.nil?
    return self < args
    end
    end
    def Def(name, &proc)
    name = name[] if (!name.is_a?(Array))
    raise TypeError, "wrong type of argument." if name[2] != '[]'
    name[0] = name[0].to_sym
    params = proc.parameters
    needArgs = (params.index {|x| x[0] == :opt || x[0] == :rest } || params.size - 1) + 1
    hasRest = !(params.index {|x| x[0] == :rest}).nil?
    hasBlock = !(params.index {|x| x[0] == :block}).nil?
    if (name.is_a?(Array) and name.size == 3)
    time = Time.now
    method_name = "_#{name[0]}__bind_#{time.to_i}_#{time.usec}"
    define_method(method_name, &proc)
    define_method(name[0]) do |*args, &newproc|
    raise ArgumentError, "wrong number of arguments (#{args.size} for #{needArgs})", caller(1) if (args.size < needArgs || (!hasRest and args.size > needArgs.size))
    for n in 0...[name[1].size,args.size].min
    needType = name[1][n].is_a?(Array) ? name[1][n] : [name[1][n]]
    needType = needType.map {|x|
    if x.is_a?(Class)
    x
    else
    if (self.class.respond_to?(:_template_list))
    raise TypeError, "", caller(0) if (self.class._template_list[x].nil?)
    self.class._template_list[x]
    else
    raise TypeError, "", caller(0)
    end
    end
    }.flatten
    raise TypeError, "wrong type of argument #{params[n][1]} (#{args[n].class.name} for #{needType})", caller(3) unless (needType.any? {|x| args[n].kind_of?(x)})
    end
    if (hasBlock) then method(method_name).call(*args, &newproc) else method(method_name).call(*args) end
    end
    end
    end
    class Object
    def is_klass?
    return false
    end
    end
    Def :Class[[Symbol, String, Array]] do |name = {}, &_proc|
    parents = []
    _template = []
    if (name.is_a?(Array))
    raise TypeError, 'wrong type of argument' if name.size != 3
    if (name[2] == '<')
    parents = name[1]
    name = name[0]
    end
    if (name[2] == '[]')
    _template = name[1]
    name = name[0]
    end
    end
    name = name.to_sym
    parents.uniq!
    o = if self.respond_to?(:const_set) then self else Object end
    parents.map! {|x| if x.is_a?(Symbol) then o.const_get(x) else x end }
    mkClass = proc do |template_matchs = []|
    _template_list = {}
    _template.each_index{|x| _template_list[_template[x]] = template_matchs[x]}
    myklass = Class.new do
    @_parents_flat = []
    @_template_list = _template_list
    def self._parents_flat
    return @_parents_flat
    end
    def self._template_list
    return @_template_list
    end
    parents = parents.map { |p|
    [p, p.klass_parents_flat] if (p.is_klass?)
    }.flatten.uniq
    parents.each { |p|
    unless (@_parents_flat.include? p)
    @_parents_flat << p
    raise TypeError, "Class is required", caller(3) if (!p.is_klass?)
    @_template_list.merge! p.klass_templte_list
    instance_eval &p.klass_init_proc
    end
    }
    instance_eval &_proc
    def is_a?(type)
    org = super(type)
    return true if org
    self.class._parents_flat.any? {|x| x == type}
    end
    end
    myklass.define_singleton_method(:is_klass?) {true}
    myklass.define_singleton_method(:klass_init_proc) { _proc }
    myklass.define_singleton_method(:klass_templte_list) { @_template_list }
    myklass.define_singleton_method(:klass_parents_flat) { @_parents_flat }
    myklass
    end
    if (_template.size == 0)
    klass = mkClass.call()
    o.const_set(name, klass)
    else
    o.const_set(name, Class.new do
    def initialize(mkClass, needTemplate = 0)
    @needTemplate = needTemplate
    @mkClass = mkClass
    @doneClass = {}
    end
    def [](*args)
    _template = args
    raise ArgumentError if (_template.size != @needTemplate)
    @doneClass[_template] = @mkClass.call(_template) if @doneClass[_template].nil?
    @doneClass[_template]
    end
    end.new(mkClass, _template.size))
    end
    end
    module WoW
    Class :Aaa do
    Def :hello do
    puts 'xy'
    end
    end
    Class :BBB << :Aaa do
    Def :fuck do
    puts 'xy'
    end
    end
    Class :MyClass[:T] < [:Aaa, :BBB] do
    alias_method :aloha, :hello
    Def :hello[[String,Integer], :T] {|a,b, *z,&c|
    print a,b,*z
    aloha()
    c.call()
    }
    end
    end
    klass = WoW::MyClass[[String,Integer]].new
    klass.hello(1,"a","3","4","5") {puts 'x'}
    klass.fuck()
    print klass.is_a?(Float).to_s + "\n"
    print klass.is_a?(WoW::MyClass[String]).to_s + "\n"
    print klass.is_a?(WoW::MyClass[Integer]).to_s + "\n"
    print klass.is_a?(WoW::BBB).to_s + "\n"
    print klass.is_a?(Object).to_s + "\n"
    view raw strong.rb hosted with ❤ by GitHub


    :)
    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2741 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 18ms · UTC 13:06 · PVG 21:06 · LAX 05:06 · JFK 08:06
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.