创建一个有理数
(define (make-rat n d) (cons n d)) #定义一个分数
(define (number x) (car x)) #number获取一个分数的分子部分
(define (denom x) (cdr x)) #denom获取一个分数的分母部分
打印有理数
(define (print x)
(newline) #内置的基本过程,打印新的一行
(display (number x)) #打印分子部分
(display "/") #打印 /
(display (denom x)) #打印分母部分
#定义一个分数
(define one-half (make-rat 1 2))
one-half
(1 . 2)
(print one-half) #打印分数
1/2
可以执行加减乘除运算的 解释器
#lang racket (define (calc exp) (match exp ; 匹配表达式的两种情况 ((? number? x) x) ; 是数字,直接返回 (`(,op ,e1 ,e2) ; 匹配并且提取出操作符 op 和两个操作数 e1, e2 (let ((v1 (calc e1)) ; 递归调用 calc 自己,得到 e1 的值 (v2 (calc e2))) ; 递归调用 calc 自己,得到 e2 的值 (match op ; 分支:处理操作符 op 的 4 种情况 (`+ (+ v1 v2)) ; 如果是加号,输出结果为 (+ v1 v2) (`- (- v1 v2)) ; 如果是减号,乘号,除号,相似的处理 (`* (* v1 v2)) (`/ (/ v1 v2))) );end let );end (`(,op,e1,e2) );end match );end define ( calc '(+ ( + 1 2) ( + 3 4)) )
定义了calc这个函数,同时也使用到了模式匹配的功能
`(op,e1,e2) 表示当前的数据结构中有三个元素,所以匹配(op,e1,e2)这三个元素
let是赋值并执行一段内容
(let (v1 值) (v2 值) (....) (body 执行一段内容) )
这段的作用是如果匹配的是数字就返回,否则递归的求e1和e2的值,当求解完后将他们分别赋给e1和e2
最后还有一个match用于匹配op的,匹配到 加减乘法再做对应的运算
#lang racket (define env0 '()) ;; 扩展。对环境 env 进行扩展,把 x 映射到 v,得到一个新的环境 (define ext-env (lambda (x v env) (cons (cons x v) env))) ;; 查找。在环境中 env 中查找 x 的值 (define lookup (lambda (x env) (let ([p (assq x env)]) (cond [(not p) x] [else (cdr p)])))) ;; 闭包的数据结构定义,包含一个函数定义 f 和它定义时所在的环境 (struct Closure (f env)) ;; 解释器的递归定义(接受两个参数,表达式 exp 和环境 env) ;; 共 5 种情况(变量,函数,调用,数字,算术表达式) (define interp1 (lambda (exp env) (match exp ; 模式匹配 exp 的以下情况(分支) [(? symbol? x) (lookup x env)] ; 变量 [(? number? x) x] ; 数字 [`(lambda (,x) ,e) ; 函数 (Closure exp env)] [`(,e1 ,e2) ; 调用 (let ([v1 (interp1 e1 env)] [v2 (interp1 e2 env)]) (match v1 [(Closure `(lambda (,x) ,e) env1) (interp1 e (ext-env x v2 env1))]))] [`(,op ,e1 ,e2) ; 算术表达式 (let ([v1 (interp1 e1 env)] [v2 (interp1 e2 env)]) (match op [‘+ (+ v1 v2)] [‘- (- v1 v2)] [‘* (* v1 v2)] [‘/ (/ v1 v2)]))]))) (define (interp exp) (interp1 exp env0) ) (interp '(((lambda (x) (lambda (y) (* x y))) 2) 3))
下面表达式的计算过程
(interp '( (lambda(xx) (+ 1 xx)) 10 ) )
调用到match中的判断
(`(,e1 ,e2)
这里的e1是 (lambda (xx) (+ 1 xx))
e2是 10
(`(,e1 ,e2))中的递归计算
[v1 (interp1 e1 env)]
[v2 (interp1 e2 env)]
其中 [v1 (interp1 e1 env)]
会调用到match中的判断
(`(lambda (,x) ,e)
这里的x是 lambda函数的参数xx
e 是函数内的表达式 (+ 1 xx)
之后 [v2 (interp1 e2 env)]
会调用到
[(? number? x) x]
之后执行到mathc v1
(match v1
[(Closure `(lambda (,x) ,e) env1)
(interp1 e (ext-env x v2 env1))])
(interp1 e (ext-env x v2 env1))
这段的作用是计算表达式
e的值是 (+ 1 xx)
x的值是 函数的参数xx
v2的值是 10
env1的值是 ()
(ext-env x v2 env1)
这段的作用是将
lambda的参数x(传入的参数名叫xx),还有值v2(内容是10)加入到env1环境中
此时env1是() 空的,所以执行完后env1就是(xx 10)
(+ 1 xx) ext-env最后匹配到 [`(,op ,e1 ,e2)
op是+
e1是 1
e2是xx,然后匹配到表达式 [(? symbol? x) (lookup x env)]
返回xx的值也就是10
最后计算表达式(+ 1 10) 结果为11
------------------------------------------------------------------------------------------------------------
下面表达式的计算过程
(interp '(((lambda (x) (lambda (y) (* x y))) 2) 3))
首先[`(,e1 ,e2)被匹配上
(let ([v1 (interp1 e1 env)]
递归执行这里的e1是
((lambda (x) (lambda (y) (* x y))) 2)
[v2 (interp1 e2 env)]
这里的e2是数字 3
然后匹配到 [(? number? x) x] 直接返回数字3
[v1 (interp1 e1 env)会递归调用解释器函数,最后匹配到这里
['(lambda (,x) ,e)
(Closure exp env)]
Closure中的的exp为
'(lambda (x) (lambda (y) (* x y)))
env为 '()
match匹配v1然后
(interp1 e (ext-env x v2 env1))
这里的 e是
(lambda (y) (* x y))
x是lambda(y)中的参数y,这个表达式相当于
(interp1 '(lambda(y) (* x y)) ext-env)
这里的ext-env相当于 (x 2)
于是 (interp1 '(lambda(y) (* x y)) ext-env)
会继续递归,调用到[`(,e1 ,e2)
最后变成 (interp1 (* x y) ext-env)
这里的ext-env是((y 2) (x 3))
最后执行到 [`(,op ,e1 ,e2)
这里的op 是*
e1 是 x
e2 是 y
x和y是变量,也就是匹配到表达式
[(? symbol? x) (lookup x env)]
调用lookup函数查找key对应的value,结果x就是3,y就是2
而op匹配到 *,执行 (* 3 2)结果就是6