Nik*_*nko 6 lisp macros common-lisp
我最近和一位同事谈过,并试着告诉他(Common)Lisp的美丽.我试图以某种方式解释宏,因为我认为宏是Lisp的杀手特性之一,但我失败了 - 我无法找到一个简单易懂的简单易懂的例子("凡人"程序员(十年的Java经验,一个聪明的家伙,但很少有"高阶"语言的经验).
如果你不得不如何通过例子解释Lisp宏?
根据我的经验,宏在人们看到它如何帮助生成代码时会给人留下最好的印象,这些代码无法通过程序或其他结构来实现.这些事情经常被描述为:
<common code>
<specific code>
<other common code>
Run Code Online (Sandbox Code Playgroud)
哪里<common code>总是一样的.以下是此类架构的一些示例:
1. time宏.没有宏的语言中的代码看起来像这样:
int startTime = getCurrentTime();
<actual code>
int endTime = getCurrentTime();
int runningTime = endTime - startTime;
Run Code Online (Sandbox Code Playgroud)
你不能将所有常用代码都放到过程中,因为它包含了实际的代码.(好吧,你可以创建一个过程并在lambda函数中传递实际代码,如果语言支持它,但它并不总是方便).
而且,正如您最有可能知道的那样,在Lisp中您只需创建time宏并将实际代码传递给它:
(time
<actual code>)
Run Code Online (Sandbox Code Playgroud)
2.交易.问Java的程序员编写方法简单SELECT使用JDBC -这将需要14-17行,包括代码来打开连接和事务,将其关闭,几个嵌套的try-catch-finally语句,只有1或2的唯一代码行.
在Lisp中,您只需编写with-connection宏并将代码减少到2-3行.
3.同步.好的,Java,C#和大多数现代语言已经有了它的语句,但是如果你的语言没有这样的结构怎么办?或者,如果您想引入新的同步,如基于STM的交易?同样,您应该为此任务编写单独的类并手动使用它,即在要同步的每个语句周围放置公共代码.
这只是少数几个例子.你可以提到"不容忘记"的宏,如with-open系列,清理环境,保护你免受资源泄漏,新的构造宏cond而不是多个ifs,当然,不要忘记像懒惰的结构if,or和and,不评估他们的论点(与程序申请相反).
有些程序员可能会主张,他们的语言有一个技术处理这样或那样的情况下(ORM,AOP,等等),但问他们,就需要所有这些技术,如果存在的宏?
所以,完全接受并回答关于如何解释宏的原始问题.使用Java中广泛使用的代码(C#,C++等),将其转换为Lisp,然后将其重写为宏.
新的WHILE声明
您的语言设计师忘记了WHILE语句.你已经多次邮寄过他了.没有成功.你已经从语言版本2.5,2.6等待3.0.没啥事儿...
在Lisp中:
(defmacro虽然......在这里插入你的实施......)
完成.
使用LOOP的简单实现需要一分钟.
从规范生成代码
然后,您可能想要解析呼叫详细记录(CDR).您有包含字段描述的记录名称.现在我可以为每个人编写类和方法.我还可以发明一些配置格式,解析配置文件并创建类.在Lisp中,我会编写一个从紧凑描述中生成代码的宏.
请参阅Lisp中的Domain Specific Languages,这是一个截屏视图,显示了从工作草图到基于宏的简单泛化的典型开发周期.
代码重写
想象一下,您必须使用getter函数访问对象的插槽.现在假设您需要在某些代码区域中多次访问某些对象.由于某种原因使用临时变量是没有解决方案.
...
... (database-last-user database) ...
...
Run Code Online (Sandbox Code Playgroud)
现在你可以写一个宏WITH-GETTER,它引入了一个getter表达式的符号.
(with-getters (database (last-user database-last-user))
...
... last-user
...)
Run Code Online (Sandbox Code Playgroud)
宏将重写封闭块内的源,并用getter表达式替换所有指定的符号.