• 第一章 构造过程抽象


    心智的活动, 除了尽力生产各种简单的认识之外,主要表现在如下三个方面:

    1)
    将若干简单的认识组合为一个复合的认识, 由此产生出各种复杂的认识。

    2)将两个认识放在一起对照,不管它们如何简单或者复杂,在这样做时并不将它们合而为一。由此得到有关它们的相互关系的认识。

    3)将有关认识与那些在实际中和它们同在的所有其他认识隔离开,这就是抽象,所有具有普遍性的认识都是这样得到的。

    ​ -- John Locke. (有关人类理解的随笔, 1690)

    Lisp 语言包含了 9 种思想

    1. 条件结构(即"if-then-else"结构)。现在大家都觉得这是理所当然的,但是 Fortran I 就没有这个结构,它只有基于底层机器指令的 goto 结构。
    2. 函数也是一种数据类型。在 Lisp 语言中,函数与整数或字符串一样,也属于数据类型的一种。它有自己的字面表示形式(literal representation),能够储存在变量中,也能当作参数传递。一种数据类型应该有的功能,它都有。
    3. 递归。Lisp 是第一种支持递归函数的高级语言。
    4. 变量的动态类型。在 Lisp 语言中,所有变量实际上都是指针,所指向的值有类型之分,而变量本身没有。复制变量就相当于复制指针,而不是复制它们指向的数据。
    5. 垃圾回收机制。
    6. 程序由表达式(expression)组成。Lisp 程序是一些表达式区块的集合,每个表达式都返回一个值。这与 Fortran 和大多数后来的语言都截然不同,它们的程序由表达式和语句(statement)组成。区分表达式和语句,在 Fortran I 中是很自然的,因为它不支持语句嵌套。所以,如果你需要用数学式子计算一个值,那就只有用表达式返回这个值,没有其他语法结构可用,因为否则就无法处理这个值。
    7. 符号(symbol)类型。符号实际上是一种指针,指向储存在哈希表中的字符串。所以,比较两个符号是否相等,只要看它们的指针是否一样就行了,不用逐个字符地比较。
    8. 代码使用符号和常量组成的树形表示法。
    9. 无论什么时候,整个语言都是可用的。Lisp 并不真正区分读取期、编译期和运行期。你可以在读取期编译或运行代码;也可以在编译期读取或运行代码;还可以在运行期读取或者编译代码。

    应用序与正则序

    正则序: 解释器首先对运算符和各个运算对象求值,而后将得到的过程应用于实际的参数。举个粒子:
    预先定义:

    (define (square x)
        (* x x))
    (define (sum-of-squares x y)
        (+ (square x) (square y)))
    (define (f a)
    (sum-of-squares (+ a 1) (+ a 2)))
    

    求表达式 (f, 5) 的值。

    (sum-of-squares (+ 5 1) (+ 5 2))
    (+ (square (+ 5 1)) (square (+ 5 2)))
    (+ (* (+ 5 1) (+ 5 1)) (* (+ 5 2) (+ 5 2)))
    (+ (* 6 6) (* 7 7))
    (+ 36 49)
    85
    

    这种“完全展开而后归约”的求值模型称为正则序求值。与之相对的是现代解释器采用的是先求值参数而后应用的方式,它称为应用序求值

    条件表达式和谓语

    (cond (<e1> <p1>)
    (<e2> <p2>)
    ..
    (<en> <pn>))
    
    (if <pred> <conse> <alter>)
    (and <e1> <e2> ...<en>)
    (or <e1> <e2> ... <en>)
    (not <e>)
    

    实例

    Ben 发明了一种方法检测解释器采用哪种方式求值,他定义了一个过程:

    (define (p) (p))
    (define (test x y)
    (if (= 0 x)
        0
        y))
    

    而后他求下面表达式的值:

    (test 0 (p))
    

    如果解释器采用应用序求值, Ben 将会看到什么? 如果解释器采用正则器求值, Ben 又会看到什么?假设 if 语句在两种求值方式中的规则是一样的, 即谓词总是先被执行。

    答: 如果解释器采用应用序求值, 那么必须知道表达式 (p) 的值, (p) 是一个调用自己的函数。

    (test 0 (p))
    (test 0 (p))
    ...
    

    反之如果解释器采用正则序求值,那么

    (test 0 (p))
    (if (= 0 0)
    0
    (p))
    0
    

    说明性知识与行动性知识

    采用牛顿法求平方根

    平方根函数可定义为: 根号 x = 存在这样的 y, y >= 0 并且 y^2 = x;

    (define (sqrt x)
    (the y (and (>= y 0)
    (= (sqrt y) x)
    ))
    

    这样又重新提出了原来的问题。函数只不过是描述一件事情的特征,并没有描述如何计算的过程。在数学里,人们通常关心的是说明性的描述(是什么),而在计算机科学,人们通常更关心行动性的描述(怎么做)。
    计算机如何计算平方根呢? 最常用的就是牛顿的逐步逼近法。这一方法告诉我们:如果。。。

  • 相关阅读:
    python基础33——进程池&线程池/协程
    python基础32——线程
    pycharm2020
    python基础31——进程
    python基础31——操作系统史&多道
    jmeter如何保持JSESSIONID
    Jmeter中自动重定向与跟随重定向的区别
    Jmeter之HTTP Cookie 管理器
    Kubernetes简述
    docker集群部署
  • 原文地址:https://www.cnblogs.com/hackers/p/12067620.html
Copyright © 2020-2023  润新知