functional-programming - 为什么我们在 Lisp 解释器中使用序列到表达式的转换?

标签 functional-programming scheme lisp

我正在阅读SICP,它使用lisp的Scheme方言。我的问题是为什么需要如下定义的序列到表达式转换函数,该函数在条件定义中使用,但在 if 表达式中不使用?

(define (sequence->exp seq)
    (cond ((null? seq) seq)
          ((last-exp? seq) (first-exp seq))
          (else (make-begin seq))))

(define (make-begin seq) (cons 'begin seq))

以下是 if 表达式的定义,不需要序列到表达式的转换:

(define (if? exp) (tagged-list? exp 'if))
(define (if-predicate exp) (cadr exp))
(define (if-consequent exp) (caddr exp))
(define (if-alternative exp)
    (if (not (null? (cdddr exp)))
        (cadddr exp)
        'false))

(define (eval-if exp env)
  (if (true? (eval (if-predicate exp) env))
      (eval (if-consequent exp) env)
      (eval (if-alternative exp) env)))

以下是条件的定义,其谓词确实需要序列到表达式的转换。

(define (cond? exp) (tagged-list? exp 'cond))

(define (cond-clauses exp) (cdr exp))

(define (cond-else-clause? clause)
    (eq? (cond-predicate clause) 'else))

(define (cond-predicate clause) (car clause))

(define (cond-actions clause) (cdr clause))

(define (cond->if exp) (expand-clauses (cond-clauses exp)))

(define (expand-clauses clauses)
    (if (null? clauses) 
        'false ; no else clause
    (let ((first (car clauses))
         (rest (cdr clauses)))
        (if (cond-else-clause? first)
            (if (null? rest)
                (sequence->exp (cond-actions first))
                (error "ELSE clause isn't last: COND->IF"
                clauses))
            (make-if (cond-predicate first)
                     (sequence->exp (cond-actions first))
                     (expand-clauses rest))))))

最佳答案

if 表达式只能计算一个结果表达式或一个备用表达式。但是 cond 表达式计算与 true 条件子句关联的表达式序列。需要 sequence->exp 过程将表达式序列转换为单个表达式。通过将序列包装在 begin 形式中,可以创建一个表达式,可以将其计算为 if 表达式中的后续表达式或替代表达式。

发布代码中sequence->exp调用的目的是为了方便cond表达式到if表达式的转换;因此,在 cond 分支中找到的任何表达式序列都必须转换为新创建的 if 表达式中的单个表达式。

关于functional-programming - 为什么我们在 Lisp 解释器中使用序列到表达式的转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61692068/

相关文章:

java - 如何使用 "reduce"将此循环转换为函数表达式?

scheme - 在Scheme中将字符串转换为整数

windows - 使用 C-x C-f 让 Edwin 正确打开 Scheme 文件

lisp - 元循环评估器,实现环境

Haskell 组合 (.) 与 F# 的管道前向运算符 (|>)

javascript - 当您真正想要产生副作用时, "functional programming"背后的哲学是什么?

javascript - 动态生成的方法

algorithm - 如何在 Scheme 中反转列表?

clojure - Clojure 中的惰性序列是如何实现的?

lisp - 将原子拆分成列表 lisp