【问题标题】:Lisp / Scheme : Progn vs AndLisp / Scheme:Progn vs And
【发布时间】:2014-12-11 10:41:16
【问题描述】:

我想知道在函数必须评估一系列 s 表达式的情况下,是否可以将 progn 替换为 and

例子来自How To Design Programs (http://htdp.org/2003-09-26/Book/curriculum-Z-H-9.html#node_thm_6.6.12)

“开发draw-and-clear-rectangle,绘制一个矩形,休眠一会,然后清除矩形。”

(define (draw-and-clear a-rectangle)
  (and (draw-solid-rect... )
       (sleep-for-a-while... )
       (clear-solid-rect... )))

由于和的参数是按顺序计算的,与使用 progn/begin 形式有什么区别吗?

【问题讨论】:

  • 当其中一个子表单返回 NIL 时,Lisp 中大多数版本的 AND 将停止。 PROGN 将始终运行所有子表单,

标签: scheme lisp evaluation


【解决方案1】:

progn 将按顺序评估其每个 S 表达式。 and 不会在第一个返回 false 之后评估任何内容(Scheme 中的 #f 或 Common Lisp 中的 nil)。这种行为称为布尔运算符的short circuiting

(同样,or 不会在第一个返回真值的 S 表达式之后计算任何 S 表达式。)

【讨论】:

    【解决方案2】:

    我没有读过 HtDP,但是,我认为他们使用的是 and 而不是 begin,因为某些学生语言不提供 begin

    在Scheme中,唯一的错误值是#f,特别是,许多“副作用”过程返回“未指定的值”¹,这总是一个真值,因此您可以使用and有效地对它们进行排序.这与 Common Lisp 形成对比,后者的副作用过程通常返回 nil,这是一个错误值。

    ¹ 大多数 Scheme 实现将始终返回相同类型的未指定值:在 Racket 中,它使用 (void),而在大多数其他没有 (void) 的实现中,它是 (cond) 返回的任何值。

    【讨论】:

    • 我不认为 Common Lisp 是这样的。许多具有副作用的函数返回某种对象...
    • @Rainer 我不是指线性更新函数(如nreverse),我说的是像setf 这样纯粹用于副作用的东西。
    • 这很奇怪。 Common Lisp 中的 SETF 返回最后一种形式的多个值...
    • 哎呀,在写这些类型的 cmets 之前,我应该在我面前有 CLHS。 :-)
    • 看到(let ((obj ...)) ... (foo (setf obj (make-bar :baz 42))) ... obj ...)这样的代码。这需要 SETF 返回一些有用的东西......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-25
    相关资源
    最近更新 更多