我的一位朋友正在学习编程,他问我为什么没有“and if
”/“also if
”/“or if
”声明(非独占或),其中可以满足具有独立结果的多个独立测试条件,这将阻止任何“else
”条件触发。 修改:我认为我选择“或”可能是一个错误的关键字,因为or
关键字通常是懒惰地评估,因此第二个分支永远不会触发。我正在谈论的是所有真实条件的事情,但是如果or if
中有没有真实条件,那么你继续else
/ elif
分支。
这是一个例子(使用python语法):
if a:
print('a evaluates True')
orif b:
print('b evaluates True')
else:
print('Both a and b evaluate False')
这与elif
的不同之处在于,如果 a
和b
都为真,则输出结果为:< / p>
a evaluates True
b evaluates True
而在elif
中,该条件的输出将是:
a evaluates True
我接受了“我已经编程多年”的帽子并且开始解释,“好吧,当然没有orif
声明,因为......”,但我无法想出一个好理由。这个概念的一个很好的例子是fizzbuzz,其中要求您打印1到100之间的所有数字,但是所有可被3整除的数字被fizz
替换,所有可被5整除的数字被{{ 1}}和所有可被3和5整除的数字替换为buzz
。使用“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)
显然还有其他方法可以实现这一点,但它们都不像“orif”结构那样直观。回想一下,我注意到这是我实际上遇到的很多次,我有许多条件具有不同的效果,每个条件都需要进行评估,并且默认条件是如果满足 none ,则会发生。我通常通过在每个单独的条件中使用恼人的“flag”变量来“解决”这个问题:
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.
”的所有这些明确原因,我很震惊地发现Wikipedia article on conditionals中没有任何提及任何相似内容。这让我觉得我错过了一些基本的东西,为什么这不起作用。我能想到的唯一原因是,如上所述,评估需要稍微不那么懒,因为即使满足第一个“if”条件,它也需要检查是否出现“或if”分支。但是,这是一个非常容易解决的问题,因为你可以这么做,这样如果你在条件树中有任何orif
语句,那么所有 or if
语句需要是if
语句,如下:
or if
所以,有一个问题 - 我是否遗漏了与此基本相同的东西?我错过了一些原因,为什么它根本不可行,或者这只是一个巨大的错失机会?
答案 0 :(得分:1)
您要求的内容可替代地描述为模式匹配或决策表。即便如此,在假分支上获得正确的行为并不容易,而且我没有看到任何语言正是如此。
模式匹配语言(如awk)会触发与模式匹配的每个规则。您需要一些额外的代码来记录是否有任何规则被触发,如果没有则触发else规则。
决策表软件至少在30年前很受欢迎(作为预处理器)。基本上,您将测试和操作放在一个表中,系统会分析剩下的内容,以便执行默认操作。
就个人而言,我不认为它有用。在管理复杂的if测试集时存在实际问题,我不认为这个单一特性会解决其中的许多问题。在很多这些情况下,您可以自然地确保检测到else情况,因为某些变量从未被触及过。有更难的组合需要认真规划以避免完全混淆。
BTW使用'andif'和'orif'是无益的。他们确实让人完全想到别的东西。
答案 1 :(得分:0)
我不知道。但...
首先要知道你的'parallel if'几乎完全等同于标准'if'的序列。唯一的区别就是else
子句。如果谓词计算很昂贵,你可以随时缓存它(就像你的modulo示例中那样)
当我们谈论命令式/ OOP时,每个人都试图使用继承和一些功能习惯用法(比如各种'可选')来简单地删除分支。据说只有switch/case
语句才允许在工厂内部使用,它们应该没有逻辑,除了返回某种枚举之外什么都不做。
当我们谈论函数式编程时,似乎这个结构更没用。功能程序往往是功能组合。每个表达式应该返回一个值,并且(几乎)没有副作用。所以这个构造将丢弃几乎所有分支的返回值,并且仅对应该被隔离的非纯代码有用。
当我试图从日常工作中回忆起我的代码时,我真的找不到一个我想要使用它的地方。也许在通用语言中根本不需要它。但你总是可以实现宏
答案 2 :(得分:-1)
我认为orif
构造不适合C,因为它太复杂了。所有现有的C语句都具有简单的语法,并且只有一个子语句。例如在for
中你有
for (clause; expression; expression)
statement
即使是最复杂的切换,使用一个子语句和使用case
作为类似于goto
标签的标签的技巧。 orif
将会非常不同 - 它需要任意数量的子语句及其相应的条件。
从这个角度来看,orif
将是一个与所有现有C语句完全不同的野兽。今天,尽管许多流行的语言提供了C语言中没有的各种结构,但循环语句和条件语句等基本语句在很多情况下都是从C继承而来的(显然仍有变化)。我为C提出的论点也适用于许多其他语言。 (并非所有,因为例如Python有类似的elif
。)我想这至少部分解释了为什么没有orif
。