问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

Meta Programming 主要解决什么了问题

发布网友 发布时间:2022-04-23 08:39

我来回答

2个回答

懂视网 时间:2022-05-11 06:44

没有接触过meta programming, 感觉"manipulate other programs (or themselves) as their data"这个说法有点虚, 能否给一些确切的例子说明其妙用之处?
另外, 为什么说LISP与Ruby在meta programming上比Python做得要好?

回复内容:

如果把元编程定义为对程序进行操作的编程,那么,似乎没有理由把eval排除于元编程之外。
至于到底是应该编译期还是运行期,我觉得还真是无所谓的。
元编程显然是多提供了一个抽象层次,相当于让你不仅可以通过一个层次去抽象问题,还能通过另一个层次对你的问题模型进行抽象。如果用的好,这似乎提供了巨大的能量。不过,这也似乎超出了大多数人的脑部运作规则,不太适合大面积推广。
至于monad,如果专注于它可以重定义;也就是定义运算序列的能力的话,也勉强可以算是元编程吧。
说个题外话:
上面有人提到REBOL,说它的元编程不好,我的感觉明显不同。由于REBOL采用最简语法作为它的form,这就导致了自定义dialect可以做到非常自然和直观,因而其元编程更自然,更漂亮。 Ruby元编程这本书的引言就讲的其实挺清楚的。
我到是建议你看完这本书,相信你能够理解的,里面例子还不错,这本书我还没看完。我现在手边就是。
顺便说说Lisp,大家都知道“代码及数据”这回事,其实就是这样子一回事。元编程的定义就是写出编写代码的代码,lisp里面quote可以阻止求值,到需要使用的时候用eval就行了。然后在运行的时候操作自己的代码也是他另一个含义。可以call 它叫动态元编程,以此区分代码生成器以及编译器方式的静态元编程。 批量生成各种代码(类,方法,测试等等),减少编程时的重复操作。各种DSL,code generator,scalfolding,project bootstraping都受益于meta programming。 编程(programming)是对于某类问题解决方法的抽象。
而元编程(meta programming)则是对于某类解决方法的抽象。
也就是说,元编程是对于编程的抽象。
至于说到DSL这部分我不敢苟同,诚然,ruby圈的DSL有泛滥的趋势,为了DSL而创造DSL、为了炫技而DSL,但是这些不是重点。DSL的出现是高度抽象的必然结果,脱离了抽象的DSL自然会死亡。
举几个栗子:
ORM
我有现在有N个实体类,我需要把这些实体类持久化储存。所以我写了N个DAO。后来发现,DAO这些东西好像很无聊嘛,无非就是那么几步,根据实体类名称创建表,根据属性创建数据库字段,然后增删改查。(ORM)
为了解决这些“相似的重复劳动”,我们需要某种机制,能够将我的一个"meta program"转化成具体的某个program。这就是抽象层次的差别。
ORM的基本步骤:根据实体类类名确定数据库表名,根据实体类属性确定数据库字段,统一的insertdeletefindupdate 方法,根据属性与数据库字段的对应关系完成数据恢复与保存。在java中,我们通过反射拿到类名和数据库字段,利用泛型+集成得到insertdeletefindupdate以及各种公共方法。结果就是你只需要简单继承一个父类,就可以完成DAO的操作。 (GitHub - satyan/sugar: Insanely easy way to work with Android Database. 这里有一个例子)
语法分析与词法分析
语法分析与词法也是一类具有很大相似性但是又有区别的事情。一个典型的例子就是lex&yacc(flex&bison), lex是一个词法分析器,yacc是一个语法的分析器(“分析器”的措辞可能有些不严谨)。对于词法/语法分析而言所以,lex接受一个.l文件,yacc接受一个.y文件,他们的结果是生成.c代码。通过DSL来生成代码,这是编译型语言做的事情(对于c++了解不多,尤其是c++新标准引入了许多新特性,据说可以达到动态语言一样的便捷程度)分析器的本质是一个有限状态机,状态机的核心工作应该是划分状态,通过meta programming,我们可以避免编写状态机的“重复劳动”(严格来讲应该是相似劳动)
《Ruby元编程》中的一个例子:擦屁股专员的重复代码
你是一个擦屁股专员,你接手一个老旧的设备信息系统,它维护者每台计算机的的设备信息与价格。这些数据来自一个古老的数据源(DataSource)。所以你有一堆类似:
ds=DataSource.new
ds.get_mouse_info(workstation_id)
ds.get_mouse_price(workstation_id)
ds.get_keyboard_info(workstation_id)
ds.get_keyboard_price(workstation_id)
这样的函数还有一打,计算机的每一个零部件都有这样的一个函数。
为了配合新的报表系统,你需要返回一个封装好的对象,这个对象针对每一个部件都有一个独立的方法返回一个包含描述和价格的字符串。很显而易见,如果不想想什么办法的,未来的很长一段时间你都在拷贝、粘贴代码的泥潭中挣扎。
每个方法都类似,每一个名为xxx的方法,首先通过ds.get_xxx_info获得信息,然后ds.get_xxx_price获得价格,然后拼接字符串...
解决方案:对于ruby,利用动态派发(send)动态创建方法,甚至我们可以通过获取内省来获取datasource有哪些方法,得知有哪些部件,然后为这些部件创建方法。作为回报,你根本无需去创建维护一个部件列表,如果有人在DS类中增加了一个新部件,你的Computer类将会自动的支持它。
---------------------------------------------------探讨------------------------------------------------------
对于javascript程序员而言 ,依旧可以采用同样的模式,内省+动态添加函数。
py这方面用的不多,就不说了,理论讲应该是类似的。
java比较麻烦的是你不能动态添加方法,所以只能退而求其次,提供一个部件列表和一个String get_info(String component)函数。通过反射来获取部件列表和调用函数。
c语言除了生成代码以外,似乎别无他路。

ActiveRecord
用过的人都说好。它里面的许多花样与魔法都是利用元编程实现的。 原则上说,目前能看到的 Meta Programming 有两种,第一种专注于重新构成语法,即 DSL,Lisp/Scheme 属于此类,这几年的新科状元 Ruby 也属于这一派,甚至还有走得更远但相对小众的 REBOL Language;第二种专注于在编译期进行计算和分派以达到针对特定场景的自动代码选择优化,C++ 的模板属于此类。C 的宏则兼有两者,但能力都比较弱。据我见过的情况,学院派的比较认可前一种,后一种则借 C++ 的东风用得更广泛。

问题引言里的那句话,我认为是在说 C++,因为它强调了 do part of the work at compile time。但 Python 的 Meta-programming,我闻所未闻。Python 1.2 开始用到现在,我确实没有听说 Python 有什么构建 DSL 的能力,更遑论所谓 Meta-programming。Python 社区的文化,也向来没有在语法上玩花样的传统。于是大略查了查,它说的是应该是第三项东西:类结构动态调整,本质来说,就是反射(reflection)。参照 DeveloperWorks 上的这一篇:Metaclass programming in Python,以及这一篇:Metaprogramming。不难看出,这两篇文章谈的是完全另一个话题。因此谈所谓 Lisp 和 Ruby 在 Meta-programming 上为什么比 Python 做得好,在我看来是一个伪命题,因为两者说的 Meta-programming 的内涵和外延都不一样。

在实际工作中,无论哪一种 Meta-programming,我都持否定态度。但理由和前面朋友的观点不同。我认为 Meta-programming 破坏了交流中的一项基本原则:同样的编程语言,应当有同样的交流习惯。过于随意地构造 DSL,让程序员之间的交流变得更加困难。这一方面的典型例子是 REBOL,几种 DSL 语法差异明显,重新学习的成本过高,也实际上助长了社区的分裂倾向。闲来无事,自己玩玩也就算了;放在工作里,害人害己。

至于 Lisp/Scheme 家族的 Meta Programming,与其说是做得更好,倒不如说是语法结构过于简单导致其怎么变换都是长得一个样子。关于这一点,不妨对比一下 REBOL,它构造出来的几个 DSL 语法上没有多少相似之处。不过,对我来说,Lisp/Scheme 这种语法简单其实才是我喜欢的 Scheme:编译器的设计者可以把更多的精力花在运行时和优化上。

还是那句话,我们写程序是为了解决问题。抽象和表达方式是手段,不是目的。汲汲于语法上的花头,是耍滑头。 我平时也不怎么用这个东西,主要是我喜欢的语言meta programming的能力也不大。为什么说LISP和Ruby的meta programming比Python好是因为,他们拥有“在编译时或者运行时重新读取自己的代码然后修改重新编译的能力”,譬如说LISP的宏,譬如说Ruby的DSL的写法,譬如说F#的computation expression,譬如说C#的linq和Expression,譬如说C++的模板(这个就比较牵强了),譬如说Haskell的monad。Python毛都没有。

不过我觉得这个功能用处不大,没事还是不要凑合了。 不清楚元编程要解决什么问题,但是可以说说Ruby元编程的应用:

1,Rails完全是成就于Ruby的元编程能力之上。
2,Ruby社区涌现出的各种优秀工具,无不借了元编程之力。
3,在Ruby中,元编程不特殊,它就是编程。
以上所说只是针对于说元编程没大用的那些答案。 Lisp的程序和数据都是基于List,所以只要能够生成list结构,就能相当于能够生成代码,而Lisp的真正强大的宏机制,就是运行时的代码展开与求值。
几乎任何一个稍微大一点的Lisp程序多少都会有一些用来定义宏或者用宏编写的代码。

Ruby的元编程继承自Lisp和Smalltalk,一方面可以通过eval来动态执行代码,另外可以通过构造的语言闭包来打开和关闭作用域。而且有非常简洁和内省/反射机制来对程序的运行时状态判断,进而辅助代码的生成。

C++的模板元编程的作用机制在于编译期,通过模板对类型和数据的计算来进行展开生成代码,所以才会有十分强大和通用的STL(标准模板库)的出现。

Python在某种程度上还是可以进行元编程的(修改元类/数据?),只是灵活程度不够高,所以少有人用,Python 的哲学态度决定了这个社区会尽量选择远离元编程这东西

确切的例子比如Ruby的ActiveRecord,参见Active Record Query Interface和rails/activerecord
绝大多数的Ruby DSL都应用了Metaprogramming技巧的,另有书籍:Ruby元编程

如果深入研究,元编程的作用还是很大的。抽象能力比之于简单的代码提升了不止一个层级。 这样来说吧:
工业时代初期,是这样的情况:
人生产机器,机器生产产品。

到了后期:
人生产机器,机器生产机器,机器生产产品。

显然,机器生产机器是一个了不起的进步,这大大的解放了劳动力。


元编程就类似于机器生产机器,简单说就是程序可以自己改变自己或者生成新的程序。这样的当然大大的解放了程序员。

当然,事实上在元编程之前,程序员就发明了大量的辅助工具来帮助自己编程,例如IDE什么的。只是后来程序员觉得IDE啥的还是太弱了,就能查找替换跳到引用套用模板啥的,要是程序可以自己生产自己该多好。

====================科普完毕,下面是不负责任的畅想=====================

事实上meta-programming一直都不是一个定义良好的概念,主要是meta(元)这个词本身的含义就很模糊。

元一般被理解为更基本的,更基础的。元编程就是比程序更基础的的编程,也就是程序生成程序。从这个角度上来说,无论是C++的模板、C的宏、.NET的Emit和Compiler Provider、JavaScript的字符串拼接和eval,甚至于什么动网代码生成器,都是程序生成程序。

但是一般而言,要称得上元编程还是要满足一定的条件,当然,由于元编程这个概念并非是定义良好,这些条件也只能算得上是什么共识。这个语言的特性被A当作是元编程,而B不这么认为是很正常的事情,下面列举的这些条件,仅仅只是站在我的角度认为的:

1、具备元编程能力的语言,必须是可以产生同一程序设计语言代码的语言,而不能是用一种语言产生另一种语言的程序。这就把代码生成器排除在外了。
2、具备元编程能力的语言,元编程产生的程序代码,必须能够通过词法分析。这一条把C的宏排除在外和JavaScript的eval排除在外了。
……

可以看出来,到底算得上元编程,采用不同的限制条件可以得到不同的结果。当我们讨论一个程序设计语言是不是可以元编程时,条件1基本是可以达成共识,条件2就各有各的看法。


话说元编程最初产生的时候,单纯只是为了减轻程序员的负担,C++的模板最初只是重载的一个延伸。由于强类型的缘故,C语言必须针对不同的类型编写一大堆重复的代码,重载解决了这些重复代码的名称污染,而泛型则开始解决这些代码的重复。但C++标委会那群家伙显然不会像Anders那样止步于泛型,高端大气上档次一直是C++努力不懈的追求,所以泛型就被搞成了模板,更进一步的,程序员也一起来Happy,就玩出了C++模板元编程。

先写到这里吧, 元编程就是写出可以产生代码的代码。有了这样一层抽象,会让你的程序更有扩展性,适应更多的未知的场合。java里的反射,c++里的STL的模板,还是ruby里各种神奇的转发代理,这些都是元编程的应用。rails的成功构建于ruby强大的元编程,这也是rails为什么没有选择其他语言的原因。

热心网友 时间:2022-05-11 03:52

原则上说,目前能看到的 Meta Programming 有两种,第一种专注于重新构成语法,即 DSL,Lisp/Scheme 属于此类,这几年的新科状元 Ruby 也属于这一派,甚至还有走得更远但相对小众的 REBOL Language;第二种专注于在编译期进行计算和分派以达到针对特定场景的自动代码选择优化,C++ 的模板属于此类。C 的宏则兼有两者,但能力都比较弱。据我见过的情况,学院派的比较认可前一种,后一种则借 C++ 的东风用得更广泛。

问题引言里的那句话,我认为是在说 C++,因为它强调了 do part of the work at compile time。但 Python 的 Meta-programming,我闻所未闻。Python 1.2 开始用到现在,我确实没有听说 Python 有什么构建 DSL 的能力,更遑论所谓 Meta-programming。Python 社区的文化,也向来没有在语法上玩花样的传统。于是大略查了查,它说的是应该是第三项东西:类结构动态调整,本质来说,就是反射(reflection)。参照 DeveloperWorks 上的这一篇:Metaclass programming in Python,以及这一篇:Metaprogramming。不难看出,这两篇文章谈的是完全另一个话题。因此谈所谓 Lisp 和 Ruby 在 Meta-programming 上为什么比 Python 做得好,在我看来是一个伪命题,因为两者说的 Meta-programming 的内涵和外延都不一样。

在实际工作中,无论哪一种 Meta-programming,我都持否定态度。但理由和前面朋友的观点不同。我认为 Meta-programming 破坏了交流中的一项基本原则:同样的编程语言,应当有同样的交流习惯。过于随意地构造 DSL,让程序员之间的交流变得更加困难。这一方面的典型例子是 REBOL,几种 DSL 语法差异明显,重新学习的成本过高,也实际上助长了社区的*倾向。闲来无事,自己玩玩也就算了;放在工作里,害人害己。

至于 Lisp/Scheme 家族的 Meta Programming,与其说是做得更好,倒不如说是语法结构过于简单导致其怎么变换都是长得一个样子。关于这一点,不妨对比一下 REBOL,它构造出来的几个 DSL 语法上没有多少相似之处。不过,对我来说,Lisp/Scheme 这种语法简单其实才是我喜欢的 Scheme:编译器的设计者可以把更多的精力花在运行时和优化上。

还是那句话,我们写程序是为了解决问题。抽象和表达方式是手段,不是目的。汲汲于语法上的花头,是耍滑头。
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
和面的和是什么读音? win10 应用打不开。全都打不开。 进入win10打不开软件 win10电脑软件都打不开是什么原因win10突然软件都打不开软件是怎么回事... 软件打不开怎么办win10电脑点不开软件最简单办法 请问下,离厦门市岛内的台湾路的国联大厦最近的建设银行和农业银行... 从巴黎都市到建设银行怎么坐公交车,最快需要多久 东莞万江官桥窖离建设银行哪路车最近? 建行七支分行有那些公交车经过 佛山哪里有飞越丛林拓展 python类实例化中,这个字符串参数是怎么回事 java中的反射机制是什么,有什么作用啊? python 变量能否反射? python list(range(6))[::2]啥意思? 用Python写镜面反射随机变化的螺旋线 Python中如果对基础类型进行反射,比如int、float 邮寄显卡要怎么包装 显卡的散装和盒装是什么意思? 显卡包装盒有什么用 在电脑门市组装了一台电脑,显卡就是个黄皮纸盒 新买来的显卡包装盒是透明塑料纸裹住密封的还是可以打开的? DIY电脑显卡为什么是拆封的 影驰1060显卡的全新包装里面有些什么 显卡 买了个索泰1060 6G 至尊 打开快递外包装后就里面的显卡包装是这样子 怎么辨别显卡真假? 请达人指教!笔记本电脑装服装CAD制图软件需要什么配置? 请达人指教!笔记本电脑装服装CAD制图软件需要什么配置? 显卡中A卡和N卡有什么区别?哪个玩游戏更好?怎么区分A和N卡? 跪求!!!谁有服装CAD的制图软件,给个网站也行!!!要免费的... 买的显卡包装只有盒子 感觉盒子外边是不是要有个塑料膜啊 为什么说 Python 是强类型语言 .NET Framework 是干什么的 耶鲁大学在美国的哪所城市? 要成为一名大数据开发工程师必备哪些技能? 耶鲁大学在哪个城市? 美国耶鲁大学是公立大学还是私立大学 java学到什么程度能出去工作? 耶鲁大学在美国哪个州? 大数据工程师好做吗 耶鲁大学(Yale)怎么样? 名高等学府耶鲁大学位于哪个国家 大数据工程师学习课程靠谱吗 美国耶鲁大学有哪些中国名人 怎么培养孩子的逻辑思维能力? 美国耶鲁大学都出过哪些名人? 美国耶鲁、哈佛、普林斯顿分别在美国的哪个州,哪个市? 美国耶鲁大学的地址具体在哪 ...我的WPS一打开就是修订模式,不能正常的打字,怎么撤销呀? 耶鲁大学简介 耶鲁大学是好大学吗