跨越边界: Lisp之美 - 编程入门网
表的总和>(defun total (x)
(if (null x)
0
(+ (first x) (total (rest x)))
)
)
TOTAL
>(total ''(1 5 1))
7
清单 9 中的 total 函数将列表当作单个的参数。第一个 if 语句在列表为空的情况下中断递归,返 回零值。否则,该函数将第一个元素添加到列表其余部分的总和。现在应该明白如此构建 first 和 rest 的原因。first 能够去除列表的第一个元素,rest 简化了将尾部递归 (清单 9 中的递归类型)应用于 列表其余部分的过程。 由于性能的原因,Java 语言中的递归是有限的。Lisp 提供一项称作尾部递归优化 的性能优化技术。 Lisp 编译器或解释器能够将特定形式的递归翻译为迭代,从而允许以一种更为简单明快的方式来使用递 归数据结构(如树结构)。 高阶函数 如果模糊了数据和代码之间的区别,Lisp 会更有意思。在本系列的前两篇文章中,介绍了 JavaScript 中的高阶函数 和 Ruby 中的闭包。这两项功能都将函数作为参数进行传递。在 Lisp 中,由 于函数和列表没有任何区别,高阶函数也就非常简单。 高阶函数的最常见用法或许是 lambda 表达式,这是闭包的 Lisp 版。lambda 函数是用于将高阶函数 传入 Lisp 函数的函数定义。例如,清单 10 中的 lambda 表达式计算了两个整数的和: 清单 10. Lambda 表达式 如果使用过高阶函数或闭包,那么可能更容易理解清单 10 中的代码。第一行代码定义了一个 lambda 表达式并将其和 total 符号绑定到一起。第二行代码仅显示了这个和 total 绑定到一起的 lambda 表达 式。最终,最后一个表达式对包含 (101 102) 的列表应用这个 lambda 表达式。 高阶函数提供比面向对象概念更高层次的抽象。可以用它们来更简洁清晰地表达想法。编程的至高境 界就是在不牺牲可读性或性能的前提下,用更少的代码提供更强大更灵活的功能。高阶函数能实现所有这 些要求。 Lisp 还有两种类型的高阶函数。其中功能最强大的可能是宏。宏为后面的执行定义 Lisp 对象。可以 将宏看作代码模板。请参考清单 11 中的示例: 清单 11. 宏 这个示例应该分为两个阶段进行阅读。第一次赋值定义了宏 times_two。在第二个阶段(称为宏扩展 )中,在对 a 求值之前,将 a 扩展为 (* 2 a)。该模板中这项延迟求值方式使宏的功能非常强大。Lisp 语言本身的许多功能都是基于宏的。 结束语 从年份上讲,Lisp 也许很陈旧,甚至语法也很陈旧。但如果稍作研究,就会发现该语言有着难以置信 的强大功能,它的高阶抽象一如既往地有效,并且生产力很高。许多更为现代的语言从 Lisp 中得到借鉴 ,但是其中大多数语言的功能无法与 Lisp 媲美。如果 Lisp 拥有 Java 或 .NET 的一部分市场,并且大 学中具备 lisp 知识的人也占有一定的比例,我们可能就会立即用它进行编码。 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |