posts - 5,comments - 0,views - 812

Lisp的求值规则


有些例子以scheme为例,不过大多在lisp都是通用的

lisp几乎所有类型都可以被求值。

数据类型的值:

  • 数的值就是它本身(它抽象概念上代表的那个数)。

  • 字符串也对自身求值。

  • 符号
    |-如果被引用(quote)的话,就表示它本身。

    |-如果不被引用,就是 关联着这个符号的对象

    • 如:函数 它的值是一个过程,一个对参数进行相关运算的过程,或者具体点说,就像是数学上的函数的表达式,如f(x,y)=x^2+y^2等。

    |-内部操作符(如+,-)就是相关的一系列机器代码。

  • 列表
    |-被引用,就是一个列表。

    |-不被引用,就是函数调用,它的值就是那个表达式的值。

一般的求值规则

为了方便,咱们称 由多个小表达式组成的叫组合式,小表达式叫子表达式。

一)对基础的函数调用求值(以(+ 2 3)为例):

  1. 首先从左至右对实参求值。&在本例中,数对自身求值,所以实参的值分别是23
  2. 实参的值传入以操作符命名的函数。&本例中,将23传给+函数,返回5

二)对组合式求值 与上类似(跳过_):

  1. 求值该组合式的各个子表达式。
  2. 将最左边的子表达式(运算符)的值(通常是过程)应用于相应的实际参数(其他子表达式的值)。

说白就是,先表达式的各个成分自己求值,然后因为最左边的函数的值是过程需要实参,所以将表达式的实参的值传入函数,最后函数的值作为表达式的值。

一些特殊的求值规则

lisp的大多数用到的都是一般求值规则,但有时候也需要特殊的求值规则

quote

这个大家都知道,就是 引用 ,简写 ' 英文单引号,
它的求值规则就是什么也不做,接受一个实参,直接返回被引用的部分。
如:


> '(+ 1 2)
(+ 1 2)

条件

像cond,if

定义

像define...

正则序和应用序

其实我们上述所说的一般求值规则,它的求值顺序被称为应用序
与之对应的是正则序

  • 应用序就是先对参数求值,而后应用于函数。
  • 正则序是先用将表达式完全展开,直到只包含基本运算符,然后在去求值。

就比如,我们定义一个函数,通过余弦定理来计算cosA的值。


; 以scheme为例
; a b c是三角形的三边
> (define (cosA a b c)
    (/ (- (+ (square b)
             (square c))
          (square a))
       (* 2 b c)))

例如(cosA (+ 1 2) 4 3)


#|
应用序
    就是(+ 1 2) 4 3先求值,然后代入cosA表达式,
    然后再求子表达式square的值。。。
    重复上述过程,最后求值。
    
正则序
    (cosA (+ 1 2) 4 3)
    1.
    (/ (- (+ (square 4)
             (square 3))
          (square (+ 1 2))
       (* 2 4 3)))
    2.
    (/ (- (+ (* 4 4)
             (* 3 3))
          (* (+ 1 2) (+ 1 2))   <-这里,就比应用的多用个加法函数
       (* 2 4 3)))
    3.
    然后就是计算。。
|#

可能我这个例子不是很直观,但我们都能知道 当复杂了的时候,我们要进行多次的外部函数调用,那样就重复运行了很多。

应用序可以节省一些资源,这俩一般影响的只是过程、复杂度(空间时间),一般不影响结果。

我们解释器大多时候采用应用序进行求值,不过一些特殊语句是用正则序的。如if语句。

xxxx

补充

或许通过求 阶乘 来比较两个会很明显。


> (define (factorial n)
    (if (= 1 n)
        n
        (* n (factorial (- n 1)))))

例如:


> (factorial 10)
3628800

如果 if 是应用序


(factorial 10)
(if (= 10 1) 1 (* 10 (factorial 9)))
(if (= 10 1) 1 (* 10 (if (= 9 1) 1 (* 9 (factorial 8)))))
...
...
(if (= 10 1) 1 (* 10 (if (= 9 1) 1 (* 9 40320))))  
(if (= 10 1) 1 (* 10 362880))
(if (= 10 1) 1 3628800)
(3628800) 

if 是正则序 (Scheme解释器是用正则序的)


(factorial 10)
(if (= 10 1) 1 (* 10 (factorial 9)))
(* 10 (factorial 9)) 
(* 10 (if (= 9 1) 1 (* 9 (factorial 8))))
(* 10 (* 9 (factorial 8))) 
...
...
(* 10 (* 9 (* 8 (* 7 (* 6 (* 5 (* 4 (* 3 (* 2 (1))))))))))
...
...
(3628800)
posted on   iceshadow  阅读(167)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示