【问题标题】:Does any major language have an "or if" / "also if" conditional, and if not, why not?是否有任何主要语言有条件“或如果”/“也如果”,如果没有,为什么不呢?
【发布时间】:2014-03-04 15:48:48
【问题描述】:

我的一个朋友正在学习编程,他问我为什么没有“and if”/“also if”/“or if”语句(非排他或),其中多个,独立可以满足具有独立结果的测试条件,以防止触发任何“else”条件。 编辑:我认为我在这里选择的“或”可能是一个不好的关键字,因为or 关键字通常是懒惰地评估的,所以第二个分支永远不会触发。我所说的是所有真实条件触发的东西,但如果or ifs中没有真实条件,那么你继续@ 987654329@/elif分公司。

这是一个例子(使用python语法):

if a:
    print('a evaluates True')
orif b:
    print('b evaluates True')
else:
    print('Both a and b evaluate False')

这与elif 的不同之处在于,如果 ab 都为真,则输出为:

a evaluates True
b evaluates True 

而在elif 中,该条件的输出将是:

a evaluates True

我戴上“我已经编程多年”的帽子并开始解释,“嗯,当然没有 orif 声明,因为......”,但我想不出一个很好的理由.这个概念的一个很好的例子是fizzbuzz,你被要求打印1到100之间的所有数字,但所有能被3整除的数字都被fizz替换,所有能被5整除的数字被buzz替换,所有数字可被 3 和 5 整除,替换为 fizzbuzz。使用“orif”语法,它可以通过一个条件来完成:

for x in range(1, 100):
    outstr = ""
    if x%3 == 0:
        outstr += "fizz"
    orif x%5 == 0:
        outstr += "buzz"
    else:
        outstr = x

    print(x)

但如果没有它,你会遇到一些不太优雅的事情,要么切换到三个条件,要么至少再进行一次模运算:

for x in range(0, 100):
    outstr = ""
    if x%3 == 0:
        outstr += "fizz"

    if x%5 == 0:
        outstr += "buzz"

    if not x%15 == 0:       # Could also be not (x%3 and x%5)
        outstr = x

    print(x)

或者您可以通过提前存储它们来避免额外的模运算:

for x in range(0, 100):
    outstr = ""
    fizz = (x%3 == 0)
    buzz = (x%5 == 0)

    if fizz:
        outstr += "fizz"

    if buzz:
        outstr += "buzz"

    if not (fizz or buzz):
        outstr = x

    print(x)

显然还有其他方法可以做到这一点,但没有一个像“orif”结构那样直观。回想起来,我注意到这是我实际上遇到很多次的事情,其中​​我有许多具有不同效果的条件,每个条件都需要评估,以及一个默认条件如果没有满足,则发生。我通常通过在每个单独的条件中都有一个烦人的“标志”变量来“解决”这个问题:

OneConditionMet = False
if a:
    # Do the "a" stuff
    OneConditionMet = True

if b:
    # Do the "b" stuff
    OneConditionMet = True

#       ...

if n:
    # Do the "n" stuff
    OneConditionMet = True

if not OneConditionMet:
    # Do the default behavior.

显然,这是一种非常不雅且令人讨厌的方式,“orif”解决了另一个问题。因此,考虑到“orif”的所有这些明确原因,我震惊地发现在Wikipedia article on conditionals 中没有任何提及任何类似的内容。这让我觉得我缺少一些基本的东西来解释为什么这不起作用。我能想到的唯一原因是,如上所述,评估需要稍微不那么懒惰,因为即使满足第一个“if”条件,它也需要检查是否出现任何“或 if”分支。不过,这是一个很容易解决的问题,因为您可以这样做,如果条件树中有任何 or if 语句,那么 all if 语句必须是 or if陈述,例如:

orif a:
    print('a evaluates True')
orif b:
    print('b evaluates True')
else:
    print('Neither a nor b evaluate True')

那么,问题来了——我是否遗漏了一些与此基本相同的东西?我是否错过了它从根本上不可行的一些原因,或者这只是一个巨大的错失机会?

【问题讨论】:

  • python 有ifelifelse 构造。许多其他语言都有switchcasedefault 语句
  • 这些构造实际上都没有这样做。在 C 中,switch 结构最接近,因为可以执行多个分支,但它不能像这样评估多个条件。
  • 所以您希望条件ab 彼此独立执行并在两者之间有一个else?很少有这样的事情在没有我可以关闭的变量集的情况下有用。
  • 当然,但这又是一个不优雅的问题解决方案,涉及额外的不必要的条件评估。这显然没有为任何图灵完备的编程语言添加核心功能,令我感到惊讶的是,当感觉像是做事的自然方式时,似乎没有个例子发生这种事情。跨度>
  • 我很难理解这个orif 与大多数语言允许的else if 构造有何不同。你能举个例子说明使用orifelse if 写的更好吗?

标签: programming-languages conditional-statements


【解决方案1】:

您所要求的也被描述为模式匹配或决策表。即便如此,在错误分支上获得正确的行为并不容易,而且我还没有看到任何语言可以做到这一点。

模式匹配语言(如 awk)触发与模式匹配的每个规则。您需要一些额外的代码来记录是否触发了任何规则,如果没有触发则触发 else 规则。

决策表软件至少在 30 年前很流行(作为预处理器)。本质上,您将测试和操作放入表中,系统会分析剩余的内容以执行默认操作。

就个人而言,我认为它没有那么有用。管理复杂的 if 测试集确实存在问题,我认为这个单一功能无法解决其中的许多问题。在很多情况下,您自然可以确保检测到 else 情况,因为某些变量从未被触及。有一些更难的组合需要认真计划以避免完全混淆。

顺便说一句,“andif”和“orif”的使用没有帮助。他们确实确实让人们完全想到了其他事情。

【讨论】:

    【解决方案2】:

    我不知道。但是……

    首先请注意,您的“并行如果”几乎完全等同于标准“如果”的序列。唯一的区别只是else 子句。如果谓词计算很昂贵,您可以随时缓存它(例如在您的示例中使用模数)

    当我们谈论命令式/OOP 时,每个人都试图使用继承和一些功能性惯用语(如各种“可选”)来简单地删除分支。据说只有 switch/case 语句被允许在工厂内部使用,它们应该没有逻辑,除了返回某种枚举之外什么都不做。

    当我们谈论函数式编程时,这种结构似乎更没用了。功能程序往往是功能组合。每个表达式都应该返回一个值并且(几乎)没有副作用。所以这个结构会丢弃几乎所有分支的返回值,并且只对应该隔离的非纯代码有用。

    当我试图从我的日常工作中回忆我的代码时,我真的找不到我想要使用它的地方。所以也许通用语言根本不需要它。但你总是可以实现为宏

    【讨论】:

      【解决方案3】:

      我认为orif 结构不太适合 C 语言,因为它太复杂了。所有现有的 C 语句都有简单的语法并且只有一个子语句。例如在for 你有

      for (clause; expression; expression)
          statement
      

      即使是最复杂的 switch,也使用了一个子语句和一个技巧,即使用case 作为标签,类似于goto 标签。 orif 会非常不同 - 它需要任意数量的子语句及其相应的条件。

      从这个角度来看,orif 将是与所有现有 C 语句完全不同的野兽。今天,尽管许多流行的语言提供了 C 中没有的各种结构,但循环和条件等基本语句在许多情况下是从 C 继承的(变化明显但仍然存在)。我为 C 提出的论点也适用于许多其他语言。 (不是全部,因为例如 Python 有类似的elif。)我想这至少部分解释了为什么没有orif

      【讨论】:

        猜你喜欢
        • 2011-09-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-10
        相关资源
        最近更新 更多