如何删除 if 块中的否定?

ove*_*nge -2 boolean-logic go boolean-algebra

遵循此处推荐的 do..while 模式:

for {
    work()
    if !condition {
        break
    }
}
Run Code Online (Sandbox Code Playgroud)

下面的代码使用 for 循环实现 do..while(condition) :

var r *s
var err error
counter := 0

for { // do..while(specificerror && < MAX && trigger_not_initiated)

    r, err = f()
    counter = counter + 1
    if !(err != nil &&
        strings.Contains(err.Error(), "specificerror") &&
        counter < MAX &&
        !IsTriggerInitiated()) {
        break
    }
}
Run Code Online (Sandbox Code Playgroud)

if但审查小组建议通过删除语句中的否定(条件)中的否定来使 if 条件更具可读性

如何删除否定(条件)forif语句中的否定?

icz*_*cza 7

您需要的转变称为德摩根定律:

  • 不是(A或B)=(不是A)和(不是B)
  • 不是(A 和 B)=(不是 A)或(不是 B),

所以如果你有这样的声明:

if !(a && b && c) {}
Run Code Online (Sandbox Code Playgroud)

它相当于

if !a || !b || !c {}
Run Code Online (Sandbox Code Playgroud)

在你的例子中:

if !(err != nil &&
    strings.Contains(err.Error(), "specificerror") &&
    counter < MAX &&
    !IsTriggerInitiated()) {
    break
}
Run Code Online (Sandbox Code Playgroud)

翻译版本:

if err == nil ||
    !strings.Contains(err.Error(), "specificerror") ||
    counter >= MAX ||
    IsTriggerInitiated() {
    break
}
Run Code Online (Sandbox Code Playgroud)

需要检查的一件事:短路评估。在一系列&&if 表达式被求值为 时false,其余的将不会被求值(我们知道结果是false)。

幸运的是,这在翻译版本中保持不变:短路求值将是相同的,因为在一系列||if 表达式被求值为 时true,其余的将不会被求值(我们知道结果是true)。因此,当 为 的原始形式a时,与 为变换后的形式时false的情况完全相同。!atrue

  • not (A or B) ⟷ (not A) and (not B) 仅在经典逻辑中成立。在构造性(直觉主义)逻辑中,您只是没有(A或B)⟵(不是A)和(不是B),这不允许您建议的翻译。但我怀疑问OP问题的人对逻辑的这些更精细的部分并不真正感兴趣,所以请投票。 (2认同)