Answers:
Lisp宏结合了一些独特的属性:
最好的应用程序会利用所有这些方面。也许最著名的示例是Common Lisp中的(循环…),如果没有这些功能之一,它的效用就无法接近。没有源作为输入,在循环内定义动作将很麻烦。如果没有编译时扩展,那就太慢了;如果没有代码生成,它将无法执行。
另一个很好的例子是《实践通用Lisp: 实践:解析二进制文件》中的二进制序列化一章。
实现类似于LINQ的查询宏可能是另一个很好的应用程序。但是它将丢失使LINQ保持其良好状态的自动完成功能。如今,几乎所有由具有XML输入的专用代码生成器(例如XAML)解决的问题都可以使用Lisp宏来实现。
我想在通用Lisp中考虑宏的方式是,它们是返回要求值的代码的函数,但是在返回该代码之前“不”求值它们的参数。函数也返回一些东西,但是它们在评估其主体之前先评估每个参数。宏不。
Paul Graham在“ On Lisp”中提供了(IMHO)关于宏和函数之间差异的最佳描述之一,并讨论了它们的重叠和唯一性。可以将许多代码写为函数或宏,但是在某些情况下,只有宏才能工作。一旦您解决了这个问题,我认为您已经掌握了宏的要旨。
作为一个宏,其中的函数将不起作用的示例,请查看“ aif”(隐式的if)。只是几行代码,而我对从何处开始的建议。
如果要利用故意变量捕获的优势,请参考Common Lisp的照应版本。Scheme的自动卫生版本不是IMO的“真正协议”。变量捕获是Lisp宏学的重要组成部分,某些更强大,更有用的宏肯定会利用它。