如果Python有一个类似于Lisp/Scheme的宏设施(比如MetaPython),你会如何使用它?
如果你是一个Lisp/Scheme程序员,你会使用什么样的宏(除了在Python中有明确的语法并行的东西,比如while循环)?
我相信宏与Python的文化背道而驰.Lisp中的宏允许大球接近泥 ; 您可以重新定义语言,使其更适合您的问题域.相反,Pythonic代码使用Python最自然的内置功能来解决问题,而不是以一种在不同语言中更自然的方式解决问题.
宏本质上是unpythonic.
这是一个稍晚的答案,但MacroPy是我的一个新项目,它将宏带入Python.我们有一个非常重要的演示列表,所有这些都是需要宏来实现的用例,例如提供一种非常简洁的方式来声明类:
@case class Point(x, y) p = Point(1, 2) print p.x # 1 print p # Point(1, 2)
MacroPy已被用于实现以下功能:
案例类,Scala中易于使用的代数数据类型
功能编程世界中的模式匹配
尾调优化
Quasiquotes,一种操纵程序片段的快速方法
字符串插值,许多语言的常见功能,以及Pyxl.
跟踪和智能断言
PINQ到SQLAlchemy,来自C#的LINQ to SQL的克隆
来自Scala和Groovy的Quick Lambdas,
Parser Combinators,受到Scala的启发.
查看链接页面以了解更多信息; 我想我可以自信地说,我们展示的用例远远超过了迄今为止在这个主题= D上的任何建议
lisp宏的一些示例:
ITERATE是一个有趣且可扩展的循环工具
CL-YACC/FUCC是在编译时生成解析器的解析器生成器
CL-WHO允许使用静态和动态部分指定html文档
Parenscript是一个javascript代码生成器
各种简单的代码包装器,例如错误处理程序(我有一个执行代码并显示GtkMessageDialog,如果发生未处理的错误的with-gtk-error-message-handler),执行程序(例如,给定代码,在不同的线程中执行它; I有一个主内线程宏,它在不同的线程中执行代码; PCall库使用宏来包装要同时执行的代码)
具有宏的GUI构建器(例如,指定窗口小部件层次结构和窗口小部件的属性,并具有用于创建所有窗口小部件的宏生成代码)
在编译期间使用外部资源的代码生成器.例如,处理C头并生成FFI代码的宏或基于数据库模式生成类定义的宏
声明性FFI.例如,指定外部结构,函数,它们的参数类型和具有宏来生成相应的lisp结构,具有类型映射和编组代码的函数
基于Continuations的Common Lisp Web框架使用宏将代码转换为CPS(延续传递样式)形式.
这是我遇到的一个真实世界的例子,它可以通过宏或真正的元编程支持来实现,但由于Python中缺少两者,因此必须使用CPython字节码操作:
http://www.aminus.net/dejavu/chrome/common/doc/2.0a/html/intro.html#cpython
这是使用常规宏和读取宏的组合在Common Lisp中解决问题的方法,以扩展语法(可以在没有后者的情况下完成,但不是前者):
http://clsql.b9.com/manual/csql-find.html
使用闭包和元编程在Smalltalk中解决了同样的问题(Smalltalk是少数实际上正确传递消息的单调度OO语言之一):
http://people.csail.mit.edu/gregs/ll1-discuss-archive-html/msg02096.html
在这里,我尝试在Common Lisp中实现Smalltalk方法,这很好地说明了元编程如何在后者中得到很好的支持:
http://carcaddar.blogspot.com/2009/04/closure-oriented-metaprogramming-via.html
简而言之,宏只是抽象思想的另一种方法。
这是用clojure编写的不完整的光线跟踪器的示例:
(defmacro per-pixel "Macro. Excecutes body for every pixel. Binds i and j to the current pixel coord." [i j & body] `(dotimes [~i @width] (dotimes [~j @height] ~@body)))
如果您想对坐标为(i,j)的每个像素做某事,例如,如果我是偶数,则绘制一个黑色像素,则可以这样写:
(per-pixel i,j (if (even? i) (draw-black i,j)))
如果没有宏,这是不可能的,因为@body可以表示内部的任何内容(每像素ij @body)
像这样的东西在python中也是可能的。您需要使用装饰器。您不能使用lisp宏做所有事情,但是它们非常强大
Check out this decorator tutorial: http://www.artima.com/weblogs/viewpost.jsp?thread=240808