查看: 4083|回复: 8

[RMVA发布] 脚本渣でもaliasがしたくない! 2014.12.16 更新

[复制链接]

…あたしは天

梦石
0
星屑
2308
在线时间
4033 小时
注册时间
2010-10-4
回帖
10548

开拓者贵宾

发表于 2014-1-26 18:47:57 | 显示全部楼层 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有账号?注册会员

×
本帖最后由 taroxd 于 2014-12-16 17:45 编辑

曾经看到有人吐槽说,要是ruby有个关键字 def+ 之类的,可以直接在方法后面加东西就不用alias了。
于是闲着蛋疼写了类似的东西=。=
如果有什么bug的话求回复~

[pre lang="ruby" line="1"]
=begin

作者:Taroxd
-------------------------------------------------------
2014/2/14 更新
修改了def系列的实现方式,不会污染名称空间
def系列会同步方法的访问限制
修改了一些方法名

2014/2/15 更新
可以使用return,并支持block参数。

2014/2/18 更新
添加def_chain,彻底抛弃alias。
def_chain可以完全替代以前的alias

2014/4/6 更新
添加了singleton_def系列,可以用来重定义类方法等

2014/8/27 更新
def_before 与 def_after 添加了 hook 参数
对顶层环境添加了 def 系列的支持

2014/10/08 更新
对 def_with 与 def_chain 同样添加了 hook 参数

2014/12/16 更新
重构代码,使之更加易于扩展。
增加了 def_after!, def_and, def_or, def_if, def_unless
-------------------------------------------------------

使用示例可以参考 https://rpg.blue/forum.php?mod=forumdisplay&action=list&fid=539#groupnav
里面有大量的使用示例

------------------------------------------------------
=end

module Taroxd end

module Taroxd::Def

  # 导入
  Singleton = Module.new { Object.send :include, self }
  Module.send :include, self

  # 获取方法的访问限制
  def get_access_control(sym)
    return :public    if public_method_defined?    sym
    return :protected if protected_method_defined? sym
    return :private   if private_method_defined?   sym
    nil
  end

  template = lambda do |singleton|
    if singleton
      klass = 'singleton_class'
      get_method = 'method'
      define = 'define_singleton_method'
    else
      klass = 'self'
      get_method = 'instance_method'
      define = 'define_method'
    end
    %(
      def <name>(sym, hook = nil, &b)
        access = #{klass}.get_access_control sym
        old = #{get_method} sym
        if b
          #{define} sym, &b
          hook = #{get_method} sym
        end
        if hook.respond_to? :to_sym
          hook = hook.to_sym
          #{define} sym do |*args, &block|
            <pattern_sym>
          end
        elsif hook.respond_to? :call
          #{define} sym do |*args, &block|
            <pattern_call>
          end
        elsif hook.kind_of? UnboundMethod
          #{define} sym do |*args, &block|
            <pattern_unbound>
          end
        end
        #{klass}.send access, sym
        sym
      end
    )
  end

  # 保存模板和替换 'hook(' 字符串的字符
  template = {false => template.call(false), true => template.call(true)}

  # 替换掉 pattern 中的语法
  gsub_pattern = lambda do |pattern, singleton|
    old = singleton ? 'old' : 'old.bind(self)'
    pattern.gsub('*', '*args, &block')
           .gsub(/old(\()?/) { $1 ? "#{old}.call(" : old }
  end

  # 存入代替 "hook(" 的字符串
  template['sym']     = '__send__(hook, '
  template['call']    = 'hook.call('
  template['unbound'] = 'hook.bind(self).call('

  # 获取定义方法内容的字符串
  code = lambda do |name, pattern, singleton|
    pattern = gsub_pattern.call(pattern, singleton)
    template[singleton]
      .sub('<name>', name)
      .gsub(/<pattern_(\w+?)>/) { pattern.gsub('hook(', template[$1]) }
  end

  main = TOPLEVEL_BINDING.eval('self')

  # 定义 def_ 系列方法的方法
  define_singleton_method :def_ do |name, pattern|
    name = "#{__method__}#{name}"
    module_eval code.call(name, pattern, false)
    Singleton.module_eval code.call("singleton_#{name}", pattern, true)
    main.define_singleton_method name, &Kernel.method(name)
  end

  # 实际定义 def_ 系列的方法
  def_ :after,  'ret = old(*); hook(*); ret'
  def_ :after!, 'old(*); hook(*)'
  def_ :before, 'hook(*); old(*)'
  def_ :with,   'hook(old(*), *)'
  def_ :chain,  'hook(old, *)'
  def_ :and,    'old(*) && hook(*)'
  def_ :or,     'old(*) || hook(*)'
  def_ :if,     'hook(*) && old(*)'
  def_ :unless, '!hook(*) && old(*)'
end
[/pre]

评分

参与人数 5星屑 +126 收起 理由
VIPArcher + 60
satgo1546 + 36
余烬之中 + 10
晴兰 + 10
无脑之人 + 10 精品文章

查看全部评分

梦石
0
星屑
122
在线时间
552 小时
注册时间
2012-8-18
回帖
1392
发表于 2014-1-27 18:34:34 | 显示全部楼层
ruby如果有宏就好了- -可以做很多死0 0+

点评

语法糖不就是。。。  发表于 2014-1-27 21:10
我要填坑!我要背单词!我要学日语!我要每天锻炼!
好吧呵呵= =
回复

使用道具 举报

○赛

梦石
0
星屑
1254
在线时间
1276 小时
注册时间
2013-1-22
回帖
2078

贵宾

发表于 2014-1-31 00:17:58 | 显示全部楼层
看了半天愣是没看懂用法……
回复

使用道具 举报

百合控

梦石
0
星屑
6548
在线时间
1275 小时
注册时间
2013-8-21
回帖
3522

开拓者

发表于 2014-1-31 08:13:49 | 显示全部楼层
实际上我不觉得这东西有很大实用性……当做练习题吧

点评

自己就很常用啊  发表于 2014-1-31 09:42
萌新瑟瑟发抖
看到我请叫我去干活
回复

使用道具 举报

…あたしは天

梦石
0
星屑
2308
在线时间
4033 小时
注册时间
2010-10-4
回帖
10548

开拓者贵宾

 楼主| 发表于 2014-2-14 16:12:20 | 显示全部楼层
本帖最后由 taroxd 于 2014-2-15 19:19 编辑

2014/2/14 更新
修改了def系列的实现方式,不会污染名称空间
def系列会同步方法的访问限制
修改了一些方法名

2014/2/15 更新
可以使用return,并支持block参数。
感谢http://rpg.blue/thread-350420-1-1.html提供灵感
回复

使用道具 举报

…あたしは天

梦石
0
星屑
2308
在线时间
4033 小时
注册时间
2010-10-4
回帖
10548

开拓者贵宾

 楼主| 发表于 2014-2-18 13:15:04 | 显示全部楼层
2014/2/18
更新添加def_chain,彻底抛弃alias。def_chain可以完全替代以前的alias
回复

使用道具 举报

…あたしは天

梦石
0
星屑
2308
在线时间
4033 小时
注册时间
2010-10-4
回帖
10548

开拓者贵宾

 楼主| 发表于 2014-8-27 17:08:56 | 显示全部楼层
2014/8/27 更新
def_before 与 def_after 添加了 hook 参数
对顶层环境添加了 def 系列的支持
回复

使用道具 举报

无限の剣制

梦石
0
星屑
10445
在线时间
5019 小时
注册时间
2013-2-28
回帖
4942

开拓者贵宾

发表于 2014-10-8 12:51:15 | 显示全部楼层
啊,写alias写得好烦啊。(old_xxx这种别名什么的最恶心了
于是我也要开始用这个脚本了

点评

挖的一手好坟···快一年的帖子你怎么找到的···  发表于 2014-10-8 23:45
跟!  发表于 2014-10-8 17:57
回复

使用道具 举报

…あたしは天

梦石
0
星屑
2308
在线时间
4033 小时
注册时间
2010-10-4
回帖
10548

开拓者贵宾

 楼主| 发表于 2014-12-16 17:47:44 | 显示全部楼层
更新,自顶
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部