在Common Lisp中,为什么(if)语句的多表达式主体需要(progn)?

14 lisp common-lisp

这只是20世纪50年代遗留下来的一些历史遗留问题,还是在语法上存在一些理由,为什么(if)形式的多表达体需要(预测)?为什么不能将多个表达式包装在一组括号中,如(let):

   (if some-cond
     ((exp1) (exp2) (exp3)) ; multi exp "then"
     (exp4)) ; single exp "else"
Run Code Online (Sandbox Code Playgroud)

看起来编写一个宏来测试每个主体首先看它是否是一个列表,如果它是,如果它的第一个元素也是一个列表(因而不是一个函数调用),然后包装它的子组件,这似乎是微不足道的因此,在(预测)内.

Ken*_*Ken 17

在Common Lisp中,这段代码:

(if t
    ((lambda (x) (+ x 5)) 10)
   20)
Run Code Online (Sandbox Code Playgroud)

将返回15.对于您的提议,我认为它会看到true-clause是一个列表,并自动将其转换为:

(if t
    (progn (lambda (x) (+ x 5)) 10)
   20)
Run Code Online (Sandbox Code Playgroud)

哪个会回来10.这是对的吗?

我不确定在CL中区分"list"和"function invocation"是"微不足道的".您是否打算将此更改与非向后兼容?(新的和有趣的Lisp方言总是很酷,但它不是Common Lisp.)或者你能举出一个你想到的例子吗?


Sva*_*nte 11

Common Lisp并不完美,因为它是完美的,它是完美的,因为它是完美的.

整个语言建立在25个特殊运营商之上; if是其中之一, progn是另一个.

if提供了测试条件的基本机制,然后跳转到一个或另一个代码地址. progn提供了做几件事并返回最后一个值的基本机制.

有在语言标准,建立在这几款宏-如when,unless,cond,case.

如果你愿意,你有几个选项来制作你想象的东西:例如,你可以编写一个ifm宏,希望隐式progns作为then-和else-clause,或者你可以像你说的那样写它,以便它检测到意图,或者你甚至可以写一个读取宏来添加语法糖progn.


Nat*_*ers 6

是否有一些合理的理由为什么(if)形式的多表达体需要(预测)?

答案是"是",尽管可能不是你期望的原因.因为Common Lisp(与Scheme和其他Lisps不同)需要funcall,你的提议不含糊不清.即使它含糊不清,只要您的用户知道括号progn在这里暗示,它就会起作用.

但是,该语言中没有其他构造*具有可选的单/双括号.很多构造都有隐式progns,但它们的括号语法总是相同的.

例如,每个分支cond都有一个隐含progn的:

(cond (test1 body1) (test2 body2) ...)
Run Code Online (Sandbox Code Playgroud)

你不能来回切换:

(cond test1 exp1 (test2 body2) t exp3)
Run Code Online (Sandbox Code Playgroud)

因此,即使您的提案不明确,也不符合其他语言的语法.然而!就像你说的那样,这个宏很容易实现.你应该自己做,看看它是否运作良好.我很容易出错; 因为几乎所有的Lisping都在Scheme中,所以我很偏颇.

*除外case.HMF.现在我想可能还有其他人.


Phi*_*hil 3

扩展版本已经有宏。这本书真的很好:http://www.gigamonkeys.com/book/你的答案就在本章中:http://www.gigamonkeys.com/book/macros-standard-control-constructs.html

标准宏是when 和unless。