in Ruby

漫谈元编程

咬文嚼字

meta-programming(a.k.a.元编程) 中的这个 meta-词前缀源自希腊词,本意为“在…后,变换,以上”。经过几千年的演进,这个词前缀有了一种全新的意义:关于事物自身的事物。比如 meta-knowledge 就是“关于知识本身的知识”,meta-data 就是“关于数据的数据”,meta-language 就是“关于语言的语言”,而 meta-programming 也是由此而来,是“关于编程的编程”。

元编程

元编程算不上什么新鲜的概念,各种语言里早已有之:

  • C和Lisp系语言里的宏
  • C++里的模板
  • Java的注解
  • C#的属性和反射
  • 各种脚本语言(如javascript、python)的eval
  • ……

Matz 给元编程的定义是:

编写能在运行时操作语言构件的代码

So,元编程是“让代码写代码”,是“运行时操作语言”,知道这些,怎么利用?来看两个场景消化一下:

场景

考虑如下场景(以Ruby为例:

1) ORM

你设计了一个ORM框架,并将表实体(Table)的定义权交给了框架的使用者,并希望使用者定义表时能获得如下体验:

然后框架会根据表定义,来生成数据库的列以及相关实体操作功能……那么,这个Entity类该如何设计?

2) API Proxy

某著名SNS网站提供了一套 restful API,目前只提供了如下两组API:

  • GET /api/friend  POST /api/friend
  • POST /api/search

但是你知道,API将来一定会扩张的,而你现在却需要为它编写一个代理的库,那该如何最大程度的保障库的灵活性和兼容性呢?

解决

1) ORM

显然,表实体唯一的变数就是使用者定义的字段(方法),在Ruby中,我们可以通过给类安装钩子方法,在用户定制字段时得到回调:

确定了字段范围,剩下的事情也无非就是些遍历COLUMNS 的 routines(操作DB等)

2) API Proxy

代理并不需要实现任何API,本质上它只是一个转发器,左手拿着调用者请求的API方法,右手去请求上游(拿到结果后再反方向传递),这个代理库的骨架看起来是这样的:

  1. 会开一个http客户端,代为请求调用方的API调用
  2. method_missing 在类实例中出现未定义的方法时会被回调;action就是被请求的api名字,args中包含http method
  3. method_missing充当转发器,将请求以消息的形式发送给了http客户端,请求并返回结果

调用体验:

除了第一个GET参数的传递方式不够优雅,each和块的使用都很原味 🙂

小结

看了如上片断,是不是一头雾水:什么是元编程,怎么用?

其实回到它的定义就好,利用 “运行时操作语言构件” 这个特性,来

  • 简化模板代码
  • 将想象力扩展到运行时,让代码动起来

最后,借用《Ruby元编程》里禅师的话来做个告别:

根本没有什么元编程,从来只有编程而已。走吧,别再打扰我了

Matz

参考

  1. 怎么理解元编程?https://www.zhihu.com/question/23856985
  2. 元编程艺术,第 1 部分: 元编程简介: http://www.ibm.com/developerworks/cn/linux/l-metaprog1.html
  3. 松本行弘谈Lisp元编程:http://www.ituring.com.cn/article/117593
打赏作者
您的支持将激励我继续创作!

您的支持将鼓励我们继续创作!

[微信] 扫描二维码打赏

[支付宝] 扫描二维码打赏

Write a Comment

Comment