Scheme “cond”也是“let”吗?

Scheme “cond”也是“let”吗?,scheme,lisp,conditional-statements,let,Scheme,Lisp,Conditional Statements,Let,通常,我发现我需要根据以前值的值有条件地计算一系列值。例如,让我们调用这些值x,y和z。首先,我计算x。如果x满足某些条件,那么我计算y,这是x的函数,依此类推。示意图 ;; compute value x ;; if x =? #f -> #f ;; else compute value y = f(x) ;; if y =? #f -> #f ;; else compute value z = f(y) ;; et cetera 在这个计划中,你们是如何做到这一点的?我认为通常

通常,我发现我需要根据以前值的值有条件地计算一系列值。例如,让我们调用这些值
x
y
z
。首先,我计算
x
。如果
x
满足某些条件,那么我计算
y
,这是
x
的函数,依此类推。示意图

;; compute value x
;; if x =? #f -> #f
;; else compute value y = f(x)
;; if y =? #f -> #f
;; else compute value z = f(y)
;; et cetera

在这个计划中,你们是如何做到这一点的?我认为通常会使用
cond
,但
cond
会丢弃测试结果,因此在这种情况下没有任何用处。

使用
let*
,它在前面的绑定范围内按顺序评估初始化表单。在初始化表单中,使用
使计算有条件

(let* ((x (compute-x))
       (y (and x (f1 x)))
       (z (and y (f2 y))))
  ;; code that uses the variables
)

您可以使用
cond
子句中的
=>
设备,例如:

(define (testing p x)
   (if (p x) 
      x 
      #f))

(display
   (cond
      ((testing even? 1) => (lambda (x)          ; the clause is skipped
                              (list 10 x)))
      ((testing even? 2) => (lambda (x)          ; the clause is entered and
                              (list 20 x)))))    ;   `x` is bound to 2
您应该在相应的子句中嵌套
cond
,以表示您描述的嵌套条件


这样,代码结构明显遵循您的逻辑,这总是很好的。

因此,您的代码可以在标准的Common Lisp中这样编写:

(let ((it x-expression))
  (if it
      (let ((it (f it)))
        (if it
            it))))
注意,我没有给出else表单(可选),因为它在CL中是可选的。 Paul Graham以一种自动缓存测试值的方式引入

(defmacro aif (test-form then-form &optional else-form)
  `(let ((it ,test-form))
     (if it ,then-form ,else-form)))

(aif x-expression
  (aif (f it)
    (aif (f it)
         it)
这在CL中效果很好,但在Scheme中会带来卫生问题。我知道有人为绑定名创建了一个额外的参数,但它失去了优雅性:

(aif x x-expression
  (aif y (f x)
    (aif z (f y)
         z)))
在创建评估器时,我一直在试验
cond
,我通常在剥离之前进行测试,最后是
if
let
嵌套。我的第一次迭代看起来像:

(定义(ev expr env)
(除秒)
((符号?表达式)(符号->值表达式环境))
((非(对?expr))expr=>(操作员(ev(汽车expr)环境)))
((宏?运算符)(宏应用表达式(cdr expr)env)=>(参数(映射(lambda(e)(ev e env))(cdr expr)))
(else(fun apply操作符args env)))
它还支持另一种方式,因为我发现重用=>并不是那么优雅:

(定义(ev expr env)
(除秒)
((符号?表达式)(符号->值表达式环境))
((非(对?expr))expr)
(定义运营商(ev(汽车出口)环境))
((宏?运算符)(宏应用表达式(cdr expr)环境))
(定义参数(map(lambda(e)(ev e env))(cdr expr)))
(else(fun apply操作符args env)))
现在,这也可以与
aif
相同的方式使用。如果您感兴趣,Scheme宏是:

(定义语法defcond
(语法规则(else bind define=>)
((“构建”术语())
(条款)
((“构建”备选方案((绑定(BE)…rest))
(defcond“build”(让((b e)…备选)rest)
((u“build”备选方案((绑定名称(BE)…rest))
(defcond“build”(让name((b e)…可选)rest)
(uu“构建”备选方案((定义b e).rest))
(defcond“build”(letrec((b e))备选方案)rest))
((uu“build”替换((谓词-结果).rest))
(defcond“build”(if谓词-后续替换)rest)
((u“构建”备选方案((谓词结果=>(BE)…).rest))
(defcond“build”(如果谓词是后置的(let((b e)…)alternative))rest))
((uu“build”替换((谓词-结果).rest))
(defcond“build”(if谓词-后续替换)rest)
((uu“maybelse”((else表达式).rest))
(defcond“build”表达式rest))
((uu“maybelse”((某物表达)。休息))
(defcond“build”#f((某物表达式).rest)))
((“反向”术语())
(第二个“可能其他”术语)
((“反向”(第1术语…)
(第二个“反向”(第1个术语后…(术语…)
((uu)术语…)
(defcond“reverse”((术语…))))
不是很优雅的实现,但它可以工作。正如您所看到的,它支持
bind
,也支持名为
bind
。例如

(defcond
((不是(第1对))#f)
(绑定循环((lst lst)(acc 0)))
((空?lst)acc)
(其他(环路(cdr lst)(+acc(车辆lst)))
虽然我喜欢这个想法,但我仍然不认为它是一个神圣而优雅的想法。在更好的语法出现之前,我将为可读性编写它。例如:

(如果(不是(第1对))
#f
(让回路((一回路一回路)(附件0))
(如果(空?lst)
行政协调会
(环路(cdr lst)(+acc(车辆lst()()())))