导航:
编程语言是怎么构造的(一 四则混合运算的实现)
编程语言是怎么构造的(二 变量的定义和调用)
编程语言是怎么构造的(三 函数的定义和调用)
编程语言是怎么构造的(四 将语法分析和执行分离)
三 函数的定义和使用
现在我们进入最难的部分,函数。这次我们要实现的是函数式编程要求里面的函数,而不是java这种只能接受和返回数据的函数。函数需要实现以下基本要求。
1 函数可以接受数据作为参数,并返回数据作为结果。
2 函数可以作为另一个函数的参数,函数的返回值也可以是一个函数。
3 函数里面可以定义函数,并使用外面函数的参数作为参数,并可以返回这个内部定义的函数。
上面的描述看上去有点啰嗦和拗口,一般来说不会这样定义。这个只是为了方便我们按照这个思路来实现功能。
基本的理论知识
一 环境
上一节我们实现了 变量,变量和值存放在一个叫框架的东西里面。当时实现的变量相当于全局变量。现在要实现函数,那么首先要解决函数里面的变量的范围问题。
一个函数内部是一个范围,函数外面是另外的一个范围,但是有可能这个函数的外面是另外一函数,也可能函数外面就是整个程序了。因此这个范围是一个递归的过程。根据上一节我们要找到变量的值,是在框架里面找的。那么现在在函数里面要找一个变量的值,就要首先在函数内部的范围查找,如果找不到就要到外面的范围查找。这个就是函数的环境。
![](https://img.haomeiwen.com/i8027914/7ed76e567d1dadc4.png)
环境的表示方式
![](https://img.haomeiwen.com/i8027914/6a599c98dcf54604.png)
上图就可以看出,我们可以用很多个框架放到一个表里面来表示一个函数的环境。这个表里面框架的顺序是从当前函数本身一直向外到最外面。
环境表示为一个框架的表,一个环境的外围环境就是这个表的cdr ,空环境用 '()表示。
外围环境:比如说一个函数里面有一个内部的环境(过程里面定义的变量都在这个环境里面),外部环境就是这个函数外面的那些变量的环境。一个函数的变量如果在内部环境找不到就要跑到外围环境去找。
![](https://img.haomeiwen.com/i8027914/2f846cf9de0dc235.png)
现在我们查找变量的方法也要修改了。
![](https://img.haomeiwen.com/i8027914/2008bdf18402642c.png)
二 lambda
函数其实就是一个变量,然后这个变量的值是一个lambda。
(define (add1 x) (+ 1 x)) 等效于(define add1 (lambda (x) (+ 1 x)))
而lambda本身就是一个列表 (lambda (x) (+ 1 x))
因此我们就要修改一下之前的define的求值的逻辑了,如果define表达式 后面的元素不是一个符号,那就说明是在定义一个函数,因此就要从define表达式里面抽取出函数名,参数 和 函数体,然后把函数名作为一个变量,吧参数和函数体构造为一个lambda。
![](https://img.haomeiwen.com/i8027914/a656f52e882b7371.png)
然后再对这个lambda表达式求值变成一个函数和函数的环境再存放到此函数的外层环境里面。
![](https://img.haomeiwen.com/i8027914/d362617c1af41f6e.png)
![](https://img.haomeiwen.com/i8027914/b002b0d2db0fa06e.png)
接下来要考虑这种情况:返回的函数表达式例如 ((rtf 2) 3) ,(rtf 2) 返回的是一个函数,这个就要先对(rtf 2) 求值后,再进行求值。这是一个递归过程。
![](https://img.haomeiwen.com/i8027914/4b88ecb439efa0fb.png)
接下来就是 自定义函数的简单的求值语法了 例如 (add1 x y)
![](https://img.haomeiwen.com/i8027914/c0a91424b261749f.png)
为了便于我们验证递归函数,我们把if语句的解释加上
![](https://img.haomeiwen.com/i8027914/f00ab06cadcfcc1d.png)
最后在m-eval函数里面吧上面的这些情况加上
![](https://img.haomeiwen.com/i8027914/6aac5870234d7528.png)
现在我们可以来验证一下效果了。最开始的函数的那几个要求都满足的。
![](https://img.haomeiwen.com/i8027914/4def09e8640b6006.png)
小结
这样我们就实现了 四则,变量和函数。
这一部分的代码请到此下载https://gitee.com/zxbyh/scip/blob/master/R4/four-mixed-operations-valuable-func.rkt,然后在自己电脑上运行。
现在回顾一下,我们只用到了很少的几个基础的知识点。基本的加减乘除,和列表的取第一个元素和取剩余元素的功能。不断的组合这些知识点就形成了一个强大的语言的解释器了,其实人类一开始也是只会简单的数学计算和对顺序数据的分布处理,然后人通过日常生活学习就不断的升级人脑的这个解释器,以至于我们可以处理眼睛,耳朵,鼻子,触觉,记忆这些分类里面的无穷多的语言。但是机器最大的问题是,只有通过程序员去帮忙实现和升级解释器的功能,然后解释器再对程序语言进行求值。解释器本生无法自我升级解释器。
如果有人能实现这样的解释器能自己升级的话,那就真是做出了AI了。
导航:
编程语言是怎么构造的(一 四则混合运算的实现)
编程语言是怎么构造的(二 变量的定义和调用)
编程语言是怎么构造的(三 函数的定义和调用)
编程语言是怎么构造的(四 将语法分析和执行分离)
网友评论