programming language part B 学习笔记

编程语言: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 ([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)
      • 相当于改变了指针指向的数据,对原数据无影响
(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是原语句  

猜你喜欢

转载自blog.csdn.net/winter_wu_1998/article/details/79414519