Logo 是 Lisp 的另一种方言。它为教育用途而设计,所以 Logo 的许多设计决策是为了让语言对新手更加友好。例如,多数 Logo 过程以前缀形式调用(首先是过程名称,其次是参数),但是通用的算术运算符以普遍的中缀形式提供。Logo 的伟大之处,是它的简单亲切的语法仍旧为高级程序员提供了惊人的表现力。
Logo 的核心概念是,它的内建容器类型,也就是 Logo `sentence `(也叫作列表),可以轻易储存 Logo 源码,这也是它的强大表现力的来源。Logo 的程序可以编写和执行 Logo 表达式,作为求值过程的一部分。许多动态语言都支持代码生成,包括 Python,但是没有语言像 Logo 一样使代码生成如此有趣和易用。
你可能希望下来完整的 Logo 解释器来体验这个语言。标准的实现是 [Berkeley Logo](http://www.cs.berkeley.edu/~bh/logo.html)(也叫做 UCBLogo),由 Brian Harvey 和他的 Berkeley 学生开发。对于苹果用户,[ACSLogo](http://www.alancsmith.co.uk/logo/) 兼容 Mac OSX 的最新版本,并带有一份介绍 Logo 语言许多特性的[用户指南](http://www.alancsmith.co.uk/logo/LogoUserGuide151.pdf)。
Logo 语言使用了非标准的调用表达式语法,完全不带括号分隔符。上面,参数`5`转给了`print`,它打印了它的参数。描述 Logo 程序结构的术语有些不同于 Python。Logo 拥有过程而不是 Python 中等价的函数,而且过程输出值而不是返回值。和 python 类似,`print`过程总是输出`None`,但也打印出参数的字符串表示作为副作用。(过程的参数在 Logo 中也通常叫做输入,但是为了清晰期间,这篇文章中我们仍然称之为参数。)
Logo 中最常见的数据类型是单词,它是不带空格的字符串。单词用作可以表示数值、名称和布尔值的通用值。可以解释为数值或布尔值的记号,比如`5`,直接求值为单词。另一方面,类似`five`的名称解释为过程调用:
```logo
? 5
You do not say what to do with 5.
? five
I do not know how to five.
```
`5`和`five`以不同方式解释,Logo 的读取-求值循环也以不同方式报错。第一种情况的问题是,Logo 在顶层表达式不求值为 None 时报错。这里,我们看到了第一个 Logo 不同于计算器的结构;前者的接口是读取-解释循环,期待用户来打印结果。后者使用更加通用的读取-求值-打印循环,自动打印出返回值。Python 采取了混合的方式,非`None`的值使用`repr`强制转换为字符串并自动打印。
Logo 的行可以顺序包含多个表达式。解释器会一次求出每个表达式。如果行中任何顶层表达式不求值为`None`,解释器会报错。一旦发生错误,行中其余的表达式会被忽略。
```logo
? print 1 print 2
1
2
? 3 print 4
You do not say what to do with 3.
```
Logo 的调用表达式可以嵌套。在 Logo 的实现版本中,每个过程接受固定数量的参数。所以,Logo 解释器在嵌套调用表达式的操作数完整时能够唯一地判断。例如,考虑两个过程`sum`和`difference`,它们相应输出两个参数的和或差。
```logo
? print sum 10 difference 7 3
14
```
我们可以从这个嵌套的例子中看到,分隔调用表达式的圆括号和逗号不是必须的。在计算器解释器中,标点符号允许我们将表达式树构建为纯粹的句法操作,没有任何运算符名称的判断。在 Logo 中,我们必须使用我们关于每个过程接受多少参数的知识,来得出嵌套表达式的正确结构。下一节中,问题的细节会深入探讨。
Logo 也支持中缀运算符,例如`+`和`*`。这些运算符的优先级根据代数的标准规则来解析。乘法和触发优于加法和减法: