编程语言:Racket
- 使用括号来表示一个运算,括号内的运算一般不影响括号外
- 括号内是运算符前置的,也就是说第一个操作符一定被视为运算符,除非括号前加 ‘
变量binding
- (define x expression)
创建函数
(define cube
(lambda (x)
(* x x x)))
//语法糖
(define (cube3 x)
(* x x x))
- if语句
- (if e1 e2 e3)
- e1为判断语句,为假(#f)则执行e3,否则执行e3
- 惰性计算
- cons
- immutable
(cons 2 (cons 3 null))
或者(list 2 3)
- 列表实际上是以null结尾的pair
- car相当于SML中的head
- cdr相当于SML中的tail
- null? 判断是否为空
- null 空列表(不能用() 表示)
- cond语句
- 应用于多重判断
- []中的第一个是判断,若为真执行后一语句
- 最后一个判断必须为#t
(cond [(null? xs) 0]
[(number? (car xs)) (+ (car xs) (sum (cdr xs)))]
[#t (+ (sum (car xs)) (sum (cdr xs)))]))
- local binding
- let\let*\letrec 三种形式
- 可用define代替
- let\let*\letrec 三种形式
(let ([x1 e1]
[x2 e2]
...
[xn en])
e)
//let和let*区别
(define (silly-double x)
(let ([x (+ x 3)]
[y (+ x 2)])//此时x不变
(+ x y -5)))
////////////
(define (silly-double x)
(let* ([x (+ x 3)]
[y (+ x 2)])//此时x为x+3
(+ x y -8)))
//letrec类似于SML中的相互递归
(define (triple x)
(letrec ([y (+ x 2)]
[f (lambda (z) (+ z y w x))]
[w (+ x 7)])
(f -9)))
//这里是应用了函数的惰性求值的性质,非函数不可在定义中应用未定义的变量
- 修改binding
- (set! x e)
- 相当于改变了指针指向的数据,对原数据无影响
- (set! x e)
(define b 3)
(define c (+ b 4))
(set! b 5)
(define w c) //w值为7而不是9
mcons
- mutable cons
- 相对应的,有 mcar, mcdr, mpair?
- set-mcar!, set-mcdr! 用来改变cons中的值
惰性求值
- 使用
(lambda () e)
和 (e) 构造和使用
- 上述方法适用于大概率不会被选择的分支,否则的话每一次调用都要计算一次,反而增大了开销
- 使用delay和force解决上述问题
- 应用: 无限数组,例如stream流
- 使用
(define nats
(letrec ([f (lambda (x) (cons x (lambda () (f (+ x 1)))))])
(lambda () (f 1))))
// 1,2,3,4,5...
- 执行多条语句
- (begin (e1) (e2) …)
- 宏
- 宏中的变量的定义是由定义宏时决定的,相当于closure,不随后边let改变定义而改变
(define-syntax name
(syntax-rules (x y) //新的关键字
[(e1) (e2)] //e1是自定义的语句,e2是原语句