跳转到内容

Scheme 编程/什么是 Scheme?

来自 Wikibooks,开放的书籍,开放的世界
Scheme 编程
 ← 为什么选择 Scheme 而不是 Java、Python 或其他高级语言? 什么是 Scheme? 关于 R5RS 的说明 → 

每当我们阅读有关 Scheme 的内容时,我们经常会听到“函数式编程”这个词;这是真的。Scheme 是最早有效支持这种范式的语言之一。函数式编程意味着,当我们用 Scheme 编程时,我们尽量避免“副作用”;我们不会像分配变量时那样频繁地改变变量的值。实际上,所有执行此操作的 Scheme 部分都以“!”结尾(称为感叹号),这已经暗示了你做错了,除非你知道你在做什么。然而,Scheme 并不是“纯函数式”的,因为它确实“允许”副作用,只是不鼓励它们。在 Scheme 中,所有东西都是表达式;Scheme 程序最好被视为一个长而复杂的表达式;我们之前看到的词法 `let` 块是一个表达式,因为它会计算出一个值。例如,我们可以将整个块用作 `if` 表达式的条件,这比一些人预期的要常见。

函数式编程的另一个共同特征是,当然,函数和过程比大多数其他编译语言中的功能更强大。在 Scheme 中,过程是一级对象;你可以对它们执行与对 C 中的整数相同的操作。你可以将它们传递给过程、从过程返回它们、将它们存储在变量中,或者在运行时将它们计算为表达式的结果。

Scheme 也像大多数语言一样,具有词法作用域。这意味着过程在代码中的定义位置决定了它们的行为方式,而不是它们被调用的位置。这似乎显而易见,因为如今所有语言都具有词法作用域,但这一点很重要,因为 Scheme 是最早强调词法作用域重要性的语言之一,这催生了闭包,如今它们在许多解释语言中得到了广泛实施。

Scheme _没有_ `while` 循环或 `for` 循环。在 Scheme 中,通过简单地让过程调用自身就可以实现类似的效果。“这不是效率低下吗?”有些人会问,答案是“不!”因为 Scheme 还以 _适当的尾递归_ 的使用为特征,并开创了这一使用方式:每当过程以这样的方式调用自身,即相同的效果可以通过循环或迭代来实现时,Scheme 保证编译器会将它重写为机器码级别的循环,因此你永远不会用完堆栈空间,也不需要浪费时间调用过程,因为你尝试做的事情可以重写为循环。

我们已经在上一节中看到,Scheme 可以扩展自己的语法。这是因为 Scheme 像任何 Lisp 变体一样,具有一个非常重要的属性:语言是同像的;程序本身与其操纵的数据之间没有本质区别。我们已经讨论了 Scheme 源代码中大量括号的问题。这是有充分理由的:Scheme 中的主要数据结构称为 _列表_(因此得名:LISt 处理器),Scheme 源代码本身也只是一个非常复杂的列表。列表可以包含其他列表,并且由于数据可以重新排序,Scheme 可以轻松地在编译时和运行时重写自己的源代码和指令,这就是语法扩展的实现方式。

但是,如果 Scheme 是第一个做这么多重要事情的语言,那么 Scheme _老_ 吗?是的,它很老;它是现今仍在使用的最古老的语言之一,这既可以被看作是它已经过时了,也可以被看作是它已经证明了自己的价值。

华夏公益教科书