首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么<e>在if和cond中被设计成在方案中被不同的处理?

为什么<e>在if和cond中被设计成在方案中被不同的处理?
EN

Stack Overflow用户
提问于 2022-10-02 11:29:24
回答 3查看 122关注 0票数 1
代码语言:javascript
复制
(if <predicate> <consequent> <alternative>)

(cond (<p1> <e1>)
  (<p2> <e2>)
   ..........
  (<pn> <en>))

ifcond之间的一个小区别是,cond__'s表达式部分在cond子句中可能是一个表达式序列.

我想知道为什么方案语言的设计者使if和cond的表达式不同。

这个设计的目的是什么?

EN

回答 3

Stack Overflow用户

发布于 2022-10-02 12:17:55

在一种并非纯功能性的语言中,允许在语法上有空间的情况下使用一系列表达式通常是有用的:例如,在一个过程的主体中,等等。因此,例如,纯函数式Lisp可能有一个函数的语法,

代码语言:javascript
复制
(λ (<arg> ...)
  <expression>)

但是计划允许

代码语言:javascript
复制
(λ (<arg> ...)
  <expression-1>
  <expression-2>
  ...)

除了最后一个表达式之外,所有的值都被忽略了:它们只是因为副作用而发生。而且由于语法上有这方面的空间,Scheme允许这样做。

但是,在if的语法中,根本就没有这种情况的空间(见下文)。

在语法没有空间的情况下设计多向条件表达式是可能的,这可能是这样的:

代码语言:javascript
复制
(kond
 a 1
 b 2
 c 3
 else 4)

例如,(在这里,elsekond是神奇的:我不记得SICP的方案是否有此功能)。

但是,如果您考虑一下cond的实际语法是什么:

代码语言:javascript
复制
(cond
 (a 1)
 (b 2)
 (c 3)
 (else 4))

然后很明显,现在语法上有空间在每个子句的结果位置上写一个表达式序列。因此,计划容许这样做,因为根本没有理由不这样做。所以而不是

代码语言:javascript
复制
(cond
 (<t> <e>)
 ...)

你可以写

代码语言:javascript
复制
(cond
 (<t> <e1> <e2> ...)
 ...)

例如:

代码语言:javascript
复制
(cond
 (world-has-ended
  (displayln "The world has ended: rain of fire imminent")
  (rain-fire-from-sky 'yes-really))
 ...)

实际上,Scheme有一个操作符,begin,它的全部目的是允许只允许一个表达式序列。因此,例如,如果您想拥有一个表达式序列(其中自然只有一个),则可以使用begin

代码语言:javascript
复制
(if world-has-ended
    (begin
      (displayln "The world has ended: rain of fire imminent")
      (rain-fire-from-sky 'yes-really))
    (begin
      (displayln "World has not yet ended, sorry for the frogs")
      (rain-frogs-from-sky)))

然后,您可以将cond定义为ifbegin

代码语言:javascript
复制
(cond
 (world-has-ended
  (displayln "The world has ended: rain of fire imminent")
  (rain-fire-from-sky 'also-rocks))
 (world-has-nearly-ended
  (displayln "The world has nearly ended")
  (rain-frogs-from-sky 'also-some-fire)))

是相同的

代码语言:javascript
复制
(if world-has-ended
  (begin
    (displayln "The world has ended: rain of fire imminent")
    (rain-fire-from-sky 'also-rocks))
  (if world-has-nearly-ended
      (begin
        (displayln "The world has nearly ended")
        (rain-frogs-from-sky 'also-some-fire))
      #f))

至于为什么cond的语法被设计成有多个表达式的空间:这是一个历史问题。我认为有两件事有助于解释:

  1. (cond <t1> <e1> <t2> <e2> ...)这样的语法很难阅读,因为您需要计算身体中的表单数量,而(cond (<t1> ...) (<t2> ...) ...)则要容易得多。
  2. 在Lisp的早期,那些只接触FORTRAN和汇编程序的人(因为几乎就是这样)倾向于编写程序,就像FORTRAN中的程序一样,并且有很多命令式操作、副作用、排序等等。cond的语法允许这样做。
票数 1
EN

Stack Overflow用户

发布于 2022-10-02 12:17:41

如果允许在if中使用任意数量的表达式,如何判断真正的表达式何时结束,而假的表达式是什么时候开始的?对于cond,每一种情况都是一个列表,其中第一个元素是测试表达式,而列表的其余部分则在为true时得到计算。没有歧义。

1:使用begin

代码语言:javascript
复制
(if <test>
  (begin <true  exprs> ...)
  (begin <false exprs> ...))

cond通常是一个扩展为

代码语言:javascript
复制
(if <p1>
  (begin <e1>)
  (if <p2>
    (begin <e2>)
    ...))
票数 0
EN

Stack Overflow用户

发布于 2022-10-03 14:48:54

cond 在Scheme中有隐式,这是由于60年代LISP!的母语言中的意外设计造成的。

如果不是设计condif的方案的设计者。cond是McCarhty论文的原始条件,他的eval不支持多个后续表达式。基本上,如果你要写一个以上的结果,它只会做第一个。if在那篇文章中并不存在,而且自从它拥有算术if之后,它在Fortran中也不存在。

在括号中包装每个术语是为lisp的新版本打开的,它实际上允许多个后续的结果,最后一个是尾表达式。想象一下,他并没有这么做,而是提出了这样的建议:

代码语言:javascript
复制
; a and c are predicates
(cond a b
      c d
      t e)

问题在于,只有我的格式才能帮助确定什么是什么。如果我把它写成一行,几乎不可能读到这段简单的简短代码:

代码语言:javascript
复制
(cond a b c d t e)

加入父母是一种把属于自己的东西组合在一起的方法。当if出现时,它不支持相同形式的两个分支,当lisp变得命令式时,progn cond由于意外设计而隐式,而if需要progn形式,因此只保留了3个操作数。

你可能对lisp的根感兴趣

顺便说一句。我的平面cond示例非常类似于Paul的lisp语言弧中if的实现:

代码语言:javascript
复制
(if p1 c1
    p2 c2
    c3)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73925436

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档