Syntax & Parentheses.

Part A 深入的介绍了 ML —— 一个优美的 static typed functional language. 接下来的 Part B 我们将会引入一个 dynamic typed functional language,Racket;在很早之前我就听说过这个语言独特的括号语法。

这一节的一个很重要的主题应该是比较 versus。我们将学习编程语言中几个很重要的 comparisons:

  • compiler v.s. interpreter.
  • ML v.s. Racket.
  • static typing (与重要的 static checking 机制) v.s. dynamic typing.

Part B 的内容比较多,于是分为 Part B-1 与 Part B-2 进行记录。第一部分将会介绍 Racket 语言基础与各种 idioms,而第二部分专注于 static 与 dynamic typing 的比较。

Racket 脱胎于 Scheme,而 Scheme 是 LISP 的一个著名的 programming dialect。LISP 语系都采用独特的完全用圆括号的前缀符号表示法,这一优美的语法使得其被称之为“上帝的编程语言”。

Racket 中的语素仅仅有两种:

  • atom: 例如 #t, #f, 34, "hi", null 等等。一种特别重要的 atom 被称为 identifier,它可能是:
    • variable: 例如 xsomething-like-this!.
    • special form: define, lambda, if 等等。(类比关键字)
  • A sequence of things in parentheses (t1 t2 ... tn).

在一个括号序列中,第一个 atom 决定了其余元素的含义。

  • 第一个 atom 是某种 special form。举例来说,(define ...) means we have a variable definition or a sugared version of function definitions.
  • 第一个 atom 不是任何 special form。此时括号序列是一个 function call。

对 Racket 的每一条语句,我们可以轻松的解析 parsing 并建立对应的语法树。sequence 则代表一颗颗子树,子树的根为 sequence 的第一个 atom。可以看出语法树的前序遍历对应的就是 Racket 的程序结构。这样的结构使得 Racket 的语法是 unambiguous 的,不用考虑优先级问题。

In Racket, parentheses change the meaning of your program. You cannot add or remove them because you feel like it. They are NEVER optional or meaningless.

与其他语言不同,Racket 中的括号有举足轻重的地位,不能随便增删。举例来说,(e) means evaluate e and call the resulting function with 0 arguments. 所以 (42) 将会导致 run-time error。