3

我正在学习球拍/方案,并遇到了一个在线资源,该资源说,如果使用 cond 编写的函数给出 true 或 false,则只能使用notand, and or来重写它。我已经制定了一些简单的示例,我能够将 cond 语句转换为仅涉及 not and and or 的语句。我的问题是,在这两种类型的语句之间进行转换时,是否有一种方法可以立即“看到”逻辑。我知道将每个 cond 语句转换为 not 和 or 的组合并不总是可行的,但我有兴趣了解转换过程背后的逻辑。提前致谢。

(如果有关问题的某些内容没有意义,请发表评论,我将尝试澄清我想了解的内容)

4

3 回答 3

3

所有条件表达式(不仅是那些评估为真/假的条件表达式)都可以仅使用布尔组合器来重写。这是因为在 Scheme/Racket 中如何评估逻辑运算符。例如,(and a b)如果两者都为真a,则逻辑上b为真,否则为假。但是在 Racket 中,如果两者和都是真实的,否则结果(and a b)是错误的。也就是说,计算向右进行,直到遇到最后一个参数或一个假值。此时,评估停止并返回该值(可以是布尔值但不一定是)。这是因为并且不简单地产生布尔输出,它们可以用来代替条件表达式。babandor

例如

(if #t 'hello 'bye) ;=> hello
(or (and #t 'hello) 'bye) ;=> hello
(if #f 'hello 'bye) ;=> bye
(or (and #f 'hello) 'bye) ;=> bye
(cond [#f 'hello]
      [#f 'bye]
      [#t 'aloha]) ;=> aloha
(or (and #f 'hello)
    (and #f 'bye)
    (and #t 'aloha)) ;=> aloha

但是你通常不想那样使用它们,因为它们很难阅读。作为一般准则,在大多数情况下使用ifandcond而不是基本的布尔运算符。如果您只关心对条件的正面或负面结果采取行动,那么您可以使用whenor unless。如果您确实关心处理正面和负面结果,但其中一个是布尔结果,例如以下示例:

(if (positive? n)
  #t
  (even? n))

...那么这将是一个布尔运算符更可取的情况,如下所示:

(or (positive? n) (even? n))

如果条件的两个臂if都是布尔值,如下所示:

(if (> n 3)
  #t
  #f)

...然后只需将整个条件表达式替换为条件本身:

(> n 3)

否则,坚持ifand cond

于 2020-09-27T20:35:38.120 回答
2

将 a 转换cond为嵌套if的 s 后,您始终可以将其转换为and or如下not所示:

(if A B C) --> (or (and A B) (and (not A) C))

但是,如果你盲目地这样做,你会得到一个比你能得到的更复杂的表达式,所以我会添加更多可以使用的转换:

(if A B #f) --> (and A B)
(if A B #t) --> (or (not A) B)
(if A #f C) --> (and (not A) C)
(if A #t C) --> (or A C)

(注意:or上面可能会返回不同的真值而不是#t,使其在技术上不同但在用作布尔值时等效)

我应该注意的另一件事是,有时您可以将多分支cond转换为and or not,而无需先转换为ifs。例如一个 3 分支cond

(cond [A B]
      [C D]
      [else E])
-->
(or (and A B)
    (and (not A) C D)
    (and (not A) (not C) E))

或 4 个分支cond

(cond [A B]
      [C D]
      [E F]
      [else G])
-->
(or (and A B)
    (and (not A) C D)
    (and (not A) (not C) E F)
    (and (not A) (not C) (not E) G))

每个都and对应一个 cond-branch,每个 cond-branch除了它自己的条件外,对于每个先前的条件and都有s。not

您可以应用更通用的规则:

for i from 1 through n,
(cond [Q_i A_i]
      ...
      [else E])
-->
on each i, for j from 1 through i-1,
(or (and (not Q_j) ... Q_i A_i)
    ...
    (and (not Q_i) ... E)
于 2020-09-30T14:39:42.713 回答
1

首先,您需要将 cond 语言脱糖为一系列 if-then-else 序列,这很简单。

之后,您可以将 if 条件重写为布尔运算符。您可以查看命题逻辑手册来学习这一点。或者看这里

顺便提一句。禁止在堆栈溢出时粘贴作业。

于 2020-09-27T09:01:02.780 回答