• 【Scheme】Scheme 编程学习 (五) —— 引述


    【Scheme】Scheme 编程学习 (五) —— 引述


    原视频地址:https://www.bilibili.com/video/BV1Kt411R7Wf?p=5

    Quoting in Scheme, powerful way to building code, using code。
    在 Scheme 中的引述,是一种强大的方式,用于构建代码,使用代码。

    • Data made from code 从代码中创建数据
    • Treating data as code 如何以代码的方式处理数据
    • Example: generic type safety 举例:以一种通用的方式来使用类型安全
      (type-safe code in a generic way)

    1. Data made from code

    (list "a" "b" "c")
    ;("a" "b" "c")
    
    • 1
    • 2

    获得三个字符串组成的表

    如果不创建三个字符串的表,而创建三个符号(symbol)的表呢?

    (list a b c)
    ; reference to undefined identifier: a
    
    • 1
    • 2

    失败,由于 a,b, c 为未定义的标识符,需要定义 a,b, c 。

    那么如何使用储符号,而不是它们所代表的值 (not what they refer to),需要使用引述(quoting)

    在 scheme 中引述,只需要使用单引号,如下:

    (list 'a 'b 'c)
    ;(a, b, c)
    
    • 1
    • 2

    我们如何嵌套这些东西 (How we can do to nest this stuff)?

    (list 'a (list 'b1 'b2) 'c)
    ; (a (b1 b2) c)
    
    • 1
    • 2

    在整个列表开始处加上单引号,也能将整个列表当作符号来处理。此种表达方式与前者等价。

    '(a (b1 b2) c)
    ;(a (b1 b2) c)
    
    • 1
    • 2

    使用引述就是告诉编译器,对这个符号什么都不要做,不去查找(look up), 只存储这个符号。

    'a
    ;a
    a
    ; reference to undefined indentifier: a
    
    • 1
    • 2
    • 3
    • 4

    empty list 空表

    > ()
    ; missing procedure expression
    
    • 1
    • 2

    执行空表失败,因为需要表中至少有一项内容。

    > (list)
    ; ()
    > '()
    ;()
    
    • 1
    • 2
    • 3
    • 4

    donnot execute this thing just hang out. 不执行这条语句,只是挂出来。

    > null
    ; ()
    > 'null
    ; null; we get back the symbol null
    
    • 1
    • 2
    • 3
    • 4

    make data that looks like code
    how we can query data

    (define z 1)
    (symbol? 'z)
    ; #t
    (symbol? z)
    ; #f ; in this case z will be evaluated, be replaced with the value 1, and 1 is not a symbol so false
    (number? 'z)
    ; #f
    (number? z)
    ; #t
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2. Treating data as code

    将数据视为代码

    (define forty-two '(* 6 9))
    > forty-two
    ; (* 6 9) ;forty-two is a list
    > (eval forty-two)
    ; evaluate take a list and execute for it
    ; 54
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3. Example: generic type safety

    通用类型的安全性,scheme 为弱类型语言,所以需要类型检查。示例:
    检查整数

    (define (safe-sum x y)
    	(if (and (integer? x) (integer? y))
    		(+ x y)
    		"INCORRECT TYPES"))
    
    • 1
    • 2
    • 3
    • 4

    定义一个过程,如果 x 和 y 都为整数,则输出执行 (+ x y) 的结果,否则输出 “INCORRECT TYPES”,示例:

    > (safe-sum 1 2)
    ;3
    > (safe-sum 1.1 2.4)
    ;"INCORRECT TYPES"
    
    • 1
    • 2
    • 3
    • 4

    检查浮点数

    (define (nonint? x)
    	(and (real? x) (not (integer? x))))
    ; 返回 x 是否为 real 和 非integer 的与结果
    
    (define (safe-sum x y)
    	(if (and (nonint? x) (nonint? y))
    		(+ x y)
    		"INCORRECT TYPES"))
    ; 如果 x y 都符合 nonint? 则返回 (+ x y) 的执行结果,否则返回"INCORRECT TYPES"
     		
    > (safe-sum 1 2)
    ; "INCORRECT TYPES"
    > (safe-sum 1.1 2.4)
    ;3.5
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    (define (replace lst find repl)
    	(if (pair? lst)
    		(cons
    			(replace (car lst) find repl)
    			(replace (cdr lst) find repl))
    		(if (equal? find lst)
    			repl
    			lst)))			
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    此函数定义,乍看起来很难,好像又是关键字又是什么的,
    其实是定义了一个函数,函数名为 replace 有三个参数,lst, find, repl,
    lst - 表,
    find - 期望查找的内容,
    repl - 期望替换为的内容

    如果表为点对则创建一个点对 cons,replace car, replace cdr 递归调用。

    主干内容为,如果在 lst 中找到了 find,则返回为 repl,否则返回整个表。

    使用举例

    > (replace '(1 2 3) '2 "XXX")
    ; (1 "XXX" 3)
    
    • 1
    • 2

    将表 '(1 2 3) 中的 '2 符号替换为 “XXX”

    > (replace '(a (b1 b2) c) 'b1 'BOO)
    ; (a (BOO b2) c)
    
    • 1
    • 2

    将表 '(a (b1 b2) c) 中的 'b1 符号替换为 'BOO 符号

    前面定义了两种类型安全的和计算 safe-sum
    这里我们可以定义一个通用类型的函数

    (define generic-safe-sum
    	; an quoted expression
    	'(define (safe-sum x y)
    		(if (and (TEST x) (TEST y))
    			(+ x y)
    			"INCORRECT TYPES")))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    与前两者基本类型,不同的地方为,这里我们定义 TEST 为一个通用类型的检查。注意 函数定义之前有个(quoting)引述 ‘ ,所以在定义时,这部分代码都被视作符号不进行执行 (evaluate)。

    如果我们想知道 generic-safe-sum 的内容,则会完整的输出这个引述的表达式。

    > generic-safe-sum
    ; (define (safe-sum x y)
    ;		(if (and (TEST x) (TEST y))
    ;			(+ x y)
    ;			"INCORRECT TYPES"))
    
    • 1
    • 2
    • 3
    • 4
    • 5

    然后我们定义一个整数类型检查并查看

    > (define safe-sum-q
    	(replace generic-safe-sum 'TEST 'integer?)) 
    	; 将通用类型的检查替换为 整数检查
    > safe-sum-q
    ; (define (safe-sum x y)
    ;		(if (and (integer? x) (integer? y))
    ;			(+ x y)
    ;			"INCORRECT TYPES"))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    与原 generic-safe-sum 几乎一致,除了 TEST 被替换为了 integer?,仍然是一个完整的引述表达式。
    safe-sum-q 为一个表,不为函数,只有 evaluate (eval) 时才会执行。

    > (eval safe-sum-q)
    ; 执行safe-sum-q,这里我们定义了一个函数 safe-sum 
    ; (define (safe-sum x y)
    ;		(if (and (integer? x) (integer? y))
    ;			(+ x y)
    ;			"INCORRECT TYPES"))
    > (safe-sum 1 2)
    ; 3
    > (safe-sum 1.1 2.4)
    ; "INCORRECT TYPES"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    本节通过示例,我们更清晰的知道了引述的用途,以及使用的方法。

  • 相关阅读:
    部署kafka后启动报错(坑):无法指定被请求的地址
    Docker学习_镜像和容器篇
    java servlet校园闲置商品交易平台的设计与实现源码
    IDaaS身份管理之属性映射和表达式
    FFmpeg开发笔记(三十)解析H.264码流中的SPS帧和PPS帧
    CMD shutdown命令
    SpringBoot(一):什么是SpringBoot?
    用Vite从零到一创建React+ts项目
    1600*D. Maximum Sum on Even Positions(贪心)
    activiti7 报错Couldn‘t resolve collection expression nor variable reference
  • 原文地址:https://blog.csdn.net/weixin_44488341/article/details/132150372