为什么(位置<大小)在条件句中如此流行?


9

每个人都在条件语句(IF)中使用(position < size),但是为什么呢?
仅惯例还是有充分理由?

在野外发现:

if (pos < array.length) {
   // do some with array[pos];
}

很少发现:

if (array.length > pos) {
   // do some with array[pos];
}

7
我不介意在右边有“变量”的一种情况是if (MIN <= x && x <= MAX)。(在某些语言MIN <= x <= MAX中,它可以写为;在C语言中,这是完全合法的,但并不意味着您可能认为这意味着什么)。
Keith Thompson


5
可能与间隔的写法有关,[min, max]而与不相关[max, min]。因此,x通过写入来检查元素是否属于区间是很自然的min <= x <= max
Andres F.

真是个难题。
TulainsCórdova13年

可以进一步澄清第二个示例,好像(!(array.lengh <= pos))...
OldFart 2015年

Answers:


48

更深层的模式是我们自然使用“ [变化的事物] [比较] [不变的事物]”作为标准顺序。此原则适用于您的示例,因为位置可能会有所变化,而大小不会变化。

唯一的常见例外是,在进行相等性测试时,某些程序员训练自己使用相反的顺序(称为Yoda条件),以避免出现常见错误variable = constant而不是variable == constant错误-我不赞成这种想法,因为我发现所描述的自然顺序更具可读性,主要是因为这是我们用英语表达想法的方式,并且因为大多数现代编译器会检测到此情况并发出警告。


3
根据您的开发工具,许多人也会在variable = constant构造上发出警告(或错误)。
GalacticCowboy

5
+1。在“ Yoda条件”中搜索有关此constant == variable现象的更多详细信息。
John M Gant

我在我自己的代码库(如最近看到同样的事情if(DBNull == row["fieldName"]) methodCall(),并想知道如果我要疯了,因为大部分时间我见过它做的其他方式。
安德鲁·格雷

1
我还要补充一点,它(position < size)通常表示一个上限,因此实际上是在重述部分lowerbound <= position < upperbound,大小作为上限。在明确两个约束的情况下,position只能在中间。
Steve314

4
它可能与语言有关。我们将“ X运算符Y ” 解析为“ X is(运算符Y)”,就像该关系是X的特征。通过询问比较,我们询问X的值是好是坏(Y在本地被视为常数)。问“ pos <array.length”感觉就像是在问:“位置还可以(小于数组长度)吗?” 如果否,则该职位有问题;再给我一个职位,我很乐意做你想做的。但是数组长度没有错。询问“ array.length> pos”感觉就像我们应该增加数组,如果它太短。

14

我见过的唯一理由就是就像数字线或我们在学校学到的其他排序事物。例如,我们这样写数字行:

<--|--|--|--|--|--|-->
   1  2  3  4  5  6

较小的事物显示在较大事物的左侧。这同样适用于其他事物,例如日期(考虑日历的布局方式)。

基本上可以归结为我们自然地思考事物顺序的方式。阅读第一种形式更容易,因为您无需对其进行过多的心理处理。


1
您是说条件值较小的表达式排在最前面?如果值更改运行时,您如何确定该设置为true?
TulainsCórdova13年

@ user61852您不需要知道运行时的值。例如:我有2个在运行时计算的值valueA和valueB,我想测试valueA小于valueB。我会写“ if(valueA <valueB)”。值A是否最终小于值B无关紧要。至少对我而言(至少对我而言),并且知道我正在寻找的是valueA小于valueB的情况。如果我看到“ if(valueB> valueA)”,那么我必须停下来想一想,当我遵循该代码分支时,哪件事是较小的事情。
Becuzz

1
我误会了。我否决了答案。现在我想投票,但是该站点要求对答案进行编辑,以便我可以更改投票。请进行一些编辑,以便我投票。
TulainsCórdova13年

@ user61852您应该现在可以更改投票。
Becuzz

11

虽然这主要是约定俗成的问题,但我认为这最符合我们的思维方式-它显示了我们强调的内容。

如果我们将其翻译为英语,则将使用短语“如果位置小于数组长度”,则句子的主题为过渡项。

换句话说,“如果数组长度大于位置”,则将数组长度(假定为固定值)置于主体中,而位置(瞬态)成为直接对象。


3
实际上(在最后一句话中)该位置成为介词的宾语。但我同意您要说的话。在语言学中,我们可以说位置是主题,“小于数组长度”是注释。“倾向于将主题化的成分置于句子开头(主题前沿)的趋势很普遍。” en.wikipedia.org/wiki/...
LarsH

4

我的观点(这只是我的观点)是关于可读性的约定。尽管两者相同,但在我的大脑中却感觉不同。我不想知道数组大小是否大于pos。我想知道pos是否小于数组大小。

就像半空讨论还是半空讨论。在数学上是相同的,但是根据上下文,我的大脑会看到不同的内容。

就个人而言,如果我看到

if (array.lengh > pos) {
    // do some with array[pos];
}

我将开始考虑这是否是错误以及程序员的含义。他是否在尝试进行边界检查以外的其他操作?

也许我不是很聪明,但是如果我必须对每一行代码进行这种分析,我的大脑就会痛。


3

用不同的方式表达一些人试图达到的目标...

如果顺序对程序的行为没有影响,则区别显然是人类最容易理解的问题。这是为什么将“主题”放在左侧有意义的语言原因:

在语言学中,句子的主题是正在谈论的话题评论是关于该主题的谈论话题。在此示例中,我们可以假设positiontopic,而“小于数组长度”是comment。用英语以及许多其他语言,通常在评论之前表达主题。
倾向于首先将主题化成分置于句子中(主题前沿)。

所以,一个好的经验法则是觉得你的代码行作为一个句子(或条款,在这种情况下),决定一句话就是,并提出首先,如果你能。通常,句子中的“关于”将是变量而不是常量。但是有时注释中还会包含一个变量,因此您不能仅仅这样做。


1

这是两件事的结合,两者都来自早期语言被编译为的底层汇编器(还有很多当前的语言)。

  1. 数组是内存中从零开始的偏移量(即,数据的第一块位于分配的内存块的开头... 0索引)。因此,对变化的片段使用0..n-1。

  2. 如果一个值小于另一个值(或寄存器等),则分支通常是一条指令。因此,使用简单的小于(<)运算符。

因此,模式从老式的汇编器转移到ANSI-C(在某种程度上更像是宏汇编器),然后从那里转移到Java和其他类似C的语言。


0

正如许多其他答案所言,它通常更易于阅读:

[thing that varies] [comparison] [thing that does not vary]

我认识的几乎每个人都只使用这种样式。

=对于用于赋值和==比较的C样式语言,有一个例外。如果您不小心输入:

if (variable = 5) ...

代替:

if (variable == 5) ...

那么您将不会收到错误,因为这是有效的代码行。(某些编译器和IDE会警告您这样做,但是拥有这样简单的错字仍然非常容易。)

但是,如果您写:

if (5 == variable) ...

编译器/解释器将出错,因为它不是有效的构造(无论如何在大多数语言中)。

这种切换通常称为Yoda条件

更新:这是尤达条件有用地方列表。


-1

就个人而言,我更喜欢这样:

bool positionIsWithinBounds = pos < array.length;
if (positionIsWithinBounds) {
   // do some with array[pos];
}

...这是更多代码,但也很容易阅读。


4
+1为比较命名。但是,实际上,对于更复杂的条件,我更喜欢这种方法,而对于像这样的简单情况,则不那么喜欢。它实际上让我停下来想一想“阵列”,“边界”,“以内”,以及这些都意味着,当我本能地知道这意味着什么为pos> array.length。换句话说,即使它使条件的含义非常明确,但实际上使阅读IMO更加困难。
John M Gant

还有一个名称要注意...
Deduplicator 2015年

-1

这是偏好或约定的问题。如果要保持一致,可以采用两种同样合理的方法:

  1. 始终将“主题”放在首位(将其视为句子)-测试所涉及的值。例如,你会写if (age>5)

  2. 或始终将较小的元素放在第一位(请考虑一下,因为值在屏幕上以自然顺序排列)。因此,例如if (a<b),无论该代码是大约a还是b左右,您都将编写。

两种约定都会推荐您显示的第一个代码段,而不是第二个,因此我想在这种情况下您会找到答案。我会说避免在这里编写违反(1)和(2)的代码是明智的,因为这会使大多数人难以阅读。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.