对于案例来说,这些表达案例的方法中最好的是哪种? [英] With case, which is the best of these methods for expressing the cases?

查看:31
本文介绍了对于案例来说,这些表达案例的方法中最好的是哪种?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所有这些工作:

(defun testcaseexpr (thecase)
  (case thecase
    ('foo (format t "matched foo"))
    (bar (format t "matched bar"))
    ((funk) (format t "matched funky"))))

这三个表达式中的哪个被视为惯用方式?也许还有一点是,当它们显然不是相同的语法时,为什么它们都起作用呢?实际上,在其他情况下,它们完全具有不同的语义.列表(funk)当然与引用的原子'foo不同.但是只是传递foobarfunk这两个字都是一样的.

Which of these three expressions is considered the idiomatic way? And perhaps as a side point, why are they all working, when clearly they are not the same syntax. In fact in other contexts they have different semantics completely. A list (funk) is certainly not the same as a quoted atom, 'foo. Yet just passing in the words foo bar and funk all work the same.

推荐答案

首先,请注意,这里实际上只有两种情况.读者将'foo扩展为(quote foo),因此您的代码等效于

First, note that you've actually only got two cases here. 'foo is expanded by the reader as (quote foo), so your code is equivalent to

(defun testcaseexpr (thecase)
  (case thecase
    ((quote foo) (format t "matched foo"))
    (bar         (format t "matched bar"))
    ((funk)      (format t "matched funky"))))

其中第一种情况和第三种情况具有相同的结构;子句的 keys 部分是对象列表.

wherein the first and third cases have the same structure; the keys part of the clause is a list of objects.

也许这个问题是不合时宜的,因为它要求最佳",这可能主要基于意见.我同意 wvxvw的答案中的观点,但是我倾向于使用您在第三种情况下显示的样式只.我有几个原因:

Perhaps this question is off-topic, since it's asking for the "best", and that might be primarily opinion based. I agree with the points made in wvxvw's answer, but I tend to use the style you've shown in the third case almost exclusively. I've got a couple reasons for this:

这是最通用的形式.在case的文档中,我们了解到normal-clause ::= (keys form*) keys是键列表的代号.这意味着像(2 (print 'two))这样的子句等效于((2) (print 'two)).您永远不会通过使用列表而不是非列表来丢失所有内容,但是如果您有一些带有多个对象的子句而某些带有单个对象的子句,那么所有这些子句都将具有一致的语法.例如,您可以拥有

It's the most general form. In the documentation for case, we read that in an normal-clause ::= (keys form*) keys is a designator for a list of keys. This means that a clause like (2 (print 'two)) is equivalent to ((2) (print 'two)). You never lose anything by using a list instead of a non-list, but if you have some clauses with multiple objects and some with single objects, you'll have consistent syntax for all of them. E.g., you can have

(case operator
  ((and or) ...)
  ((if iff) ...)
  ((not)    ...))

很难搞砸.

很难弄清totherwise的特殊情况.该文档说明了有关(强调)的信息:

It's harder to mess up.

It makes it harder to mess up the special cases of t and otherwise. The documentation says about keys that (emphasis added):

键-对象列表的指示符. 在这种情况下, 符号totherwise不能用作键指示符. 单独将这些符号称为键,代号(t)和 必须分别使用(otherwise).

keys—a designator for a list of objects. In the case of case, the symbols t and otherwise may not be used as the keys designator. To refer to these symbols by themselves as keys, the designators (t) and (otherwise), respectively, must be used instead.

在实践中,即使似乎不应允许使用某些实现,也可以在常规子句中将totherwise用作.例如,在SBCL中:

In practice, some implementations will let you use t and otherwise as keys in normal-clauses, even though it seems like this shouldn't be allowed. E.g., in SBCL:

CL-USER> (macroexpand-1 '(case keyform
                          (otherwise 'a)
                          (otherwise 'b)))


(LET ((#:G962 KEYFORM))
  (DECLARE (IGNORABLE #:G962))
  (COND ((EQL #:G962 'OTHERWISE) NIL 'A)
        (T NIL 'B)))

使用显式列表可以消除对您要执行的操作的任何歧义.即使totherwise被专门调用,是一个列表指示符,这意味着nil(一个原子和一个列表)需要一些特殊的考虑.以下代码会产生ab吗? (您可以不进行测试或检查规格就知道吗?这种情况实际上在示例中已突出显示.)

Using explicit lists removes any ambiguity about what you're trying to do. Even though t and otherwise are called out specifically, keys is a list designator, which means that nil (an atom and a list) needs some special consideration. Will the following code produce a or b? (Can you tell without testing it or checking the spec? This case is actually highlighted in the examples.)

(case nil
  (nil 'a)
  (otherwise 'b))

它返回b.要返回a,第一个正常子句必须为((nil) 'a).

It returns b. To return a, the first normal-clause would have to be ((nil) 'a).

如果您始终确保是列表,则将:

If you always make sure that keys is a list, you'll:

  1. 最终得到外观更一致的代码;
  2. 避免出现边缘错误(特别是如果您正在编写扩展为case的宏);和
  3. 使您的意图更清晰
  1. end up with more consistent looking code;
  2. avoid edge-case bugs (especially if you're writing macros that expand into case); and
  3. make your intentions clearer.

这篇关于对于案例来说,这些表达案例的方法中最好的是哪种?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆