Scheme
Scheme Built-In Procedure Reference
函数式。
在编程语言的语境中的“函数”含义与数学中的函数有区别,比如返回值可以是 void,大部分时候程序中的函数是要实现一些功能的。在 OOP 中这就直接叫做 method 而非 function 了。
值得注意的是 scheme 中的 define
是不含 return
的,只要列出一个值就是其结果,不存在“返回值”的概念。因此函数式更强调的是数学中的函数。scheme 中描述序列的 list
也不是像数组一样对内存的操作,而是基于 Pair
建立的类似于括号序列的结构。
Eval / Apply
Eval 是分析表达式(evaluate?),Apply 是实现函数。
对于一段表达式,编译器先调用 Eval,分析其 operator(操作,即对应的函数)与 operand(即参数),之后 Eval 调用 Apply。在 Apply 运行过程中,需要分析 operand,这会调用 Eval。因此它们相互调用,一轮相当于解开一次括号,就是编译器的逻辑。
这有点像自然语言的谓语宾语,嵌套就相当于从句。还有一个重要的概念是环境,即 python 中的 frame 或者作用域 scope 等,环境按调用的从属关系组成树状结构。有 Lexical / Dynamic Scope 的区别,略。
形式化描述大致如下:
1 | def Eval(expression, environment): |
1 | def Apply(operator, expression): |
Lab 11
Q4 要求实现 define
的一部分功能。由于 define
的内容有数据、运算和之前 define 的表达式等,需要递归把 pair 展开再分别 calc_eval
。要时刻明确 Eval 的对象是表达式,数据、运算、Pair 等都需要考虑应不应该 Eval。
Eval 的实现上,要充分利用 python 的函数,如果参数是运算符,返回就应该是函数,以保持功能一致。其实完形填空题不这样写大概率是过不了的,如果自作主张不 Eval 运算直接 Apply 就寄了。
list
的实现比较抽象,需要特别处理 nil
。
这部分内容还是有点难度,然后课程给的实现也很奇怪,可能到 project 才能解锁完全体吧。