在自然语言中,我们会说“如果颜色是红色,蓝色或黄色,某些颜色是原色。”
在我看过的每种编程语言中,都转化为:
isPrimaryColor = someColor == "Red" or someColor == "Blue" or someColor == "Yellow"
为什么没有更接近匹配英语句子的语法。毕竟,如果颜色是红色,或者颜色是蓝色,或者颜色是黄色,你就不会说“某些颜色是原色”。
我只是简单地认识isPrimaryColor = someColor == ("Red" or "Blue" or "Yellow")
因为它不是红蓝色和黄色,而是布尔语句,在这种情况下布尔逻辑适用,但是如下所示:
isPrimaryColor = someColor ( == "Red" or == "Blue" or == "Yellow")
作为一个额外的好处,语法可以提供更大的灵活性,比如你想看一个数字是介于1到100还是1000和2000之间,你可以说:
someNumber ((>= 1 and <=100) or (>=1000 and <=2000))
编辑:
非常有趣的答案,并指出我应该学习更多语言。在阅读完答案之后,我同意,对于严格的相等比较,类似于集合成员资格的东西是表达同一事物的清晰简洁的方式(对于具有简明内联列表或集合和测试成员资格的语言支持的语言)
出现的一个问题是,如果要比较的值是昂贵计算的结果,则需要(好的,应该)创建临时变量。另一个问题是可能需要检查不同的评估,例如“一些昂贵的计算结果应该是素数且在200到300之间”
这些场景也包含在更多功能语言中(尽管取决于语言可能不是更简洁),或者实际上任何可以将函数作为参数的语言。例如,前面的例子可能是
MeetsRequirements(GetCalculatedValue(), f(x):x > 200, f(x):x < 300, IsPrime)
答案 0 :(得分:23)
我认为大多数人会考虑像
这样的东西isPrimaryColor = ["Red", "Blue", "Yellow"].contains(someColor)
要足够清楚,他们不需要额外的语法。
答案 1 :(得分:18)
在python中你可以这样做:
color = "green"
if color in ["red", "green", "blue"]:
print 'Yay'
它被称为in
运算符,用于测试集合成员资格。
答案 2 :(得分:13)
在perl 6中,您可以使用junctions执行此操作:
if $color eq 'Red'|'Blue'|'Green' {
doit()
}
或者,您可以使用智能匹配运算符(~~
)来完成此操作。以下大致相当于python的if value in list:
语法,除了~~
在其他上下文中做得更多。
if ($color ~~ qw/Red Blue Green/) {
doit()
}
parens也使其有效perl 5(&gt; = 5.10);在perl 6中,它们是可选的。
答案 3 :(得分:12)
在Haskell中,很容易定义一个函数来执行此操作:
matches x ps = foldl (||) False $ map (\ p -> p x) ps
此函数获取谓词的值列表(类型为a -> Bool
),如果任何谓词与值匹配,则返回True
。
这可以让你这样:
isMammal m = m `matches` [(=="Dog"), (=="Cat"), (=="Human")]
好消息是,它不必只是相等,你可以使用正确类型的任何东西:
isAnimal a = a `matches` [isMammal, (=="Fish"), (=="Bird")]
答案 4 :(得分:9)
irb(main):023:0> %w{red green blue}.include? "red"
=> true
irb(main):024:0> %w{red green blue}.include? "black"
=> false
irb(main):008:0> def is_valid_num(x)
irb(main):009:1> case x
irb(main):010:2> when 1..100, 1000..2000 then true
irb(main):011:2> else false
irb(main):012:2> end
irb(main):013:1> end
=> nil
irb(main):014:0> is_valid_num(1)
=> true
irb(main):015:0> is_valid_num(100)
=> true
irb(main):016:0> is_valid_num(101)
=> false
irb(main):017:0> is_valid_num(1050)
=> true
答案 5 :(得分:7)
到目前为止,还没有人提到过SQL。它有你的建议:
SELECT
employee_id
FROM
employee
WHERE
hire_date BETWEEN '2009-01-01' AND '2010-01-01' -- range of values
AND employment_type IN ('C', 'S', 'H', 'T') -- list of values
答案 6 :(得分:6)
COBOL使用88
级别来实现命名值,命名值组
和命名的值范围。
例如:
01 COLOUR PIC X(10).
88 IS-PRIMARY-COLOUR VALUE 'Red', 'Blue', 'Yellow'.
...
MOVE 'Blue' TO COLOUR
IF IS-PRIMARY-COLOUR
DISPLAY 'This is a primary colour'
END-IF
范围测试包括如下:
01 SOME-NUMBER PIC S9(4) BINARY.
88 IS-LESS-THAN-ZERO VALUE -9999 THRU -1.
88 IS-ZERO VALUE ZERO.
88 IS-GREATER-THAN-ZERO VALUE 1 THRU 9999.
...
MOVE +358 TO SOME-NUMBER
EVALUATE TRUE
WHEN IS-LESS-THAN-ZERO
DISPLAY 'Negative Number'
WHEN IS-ZERO
DISPLAY 'Zero'
WHEN IS-GREATER-THAN-ZERO
DISPLAY 'Positive Number'
WHEN OTHER
DISPLAY 'How the heck did this happen!'
END-EVALUATE
我想这一切都发生了,因为COBOL应该模仿英语 在某种程度上。
答案 7 :(得分:5)
你会爱Perl 6,因为它有:
chaining comparison operators:
(1 <= $someNumber <= 100) || (1000 <= $someNumber <= 2000))
$isPrimaryColor = $someColor ~~ "Red" | "Blue" | "Yellow"
您可以将两者结合使用范围:
$someNumber ~~ (1..100) | (1000..2000)
答案 8 :(得分:4)
Python实际上让你能够做得最好:
>>> x=5
>>> (1<x<1000 or 2000<x<3000)
True
答案 9 :(得分:2)
在C#中:
if ("A".IsIn("A", "B", "C"))
{
}
if (myColor.IsIn(colors))
{
}
使用这些扩展程序:
public static class ObjectExtenstions
{
public static bool IsIn(this object obj, params object [] list)
{
foreach (var item in list)
{
if (obj == item)
{
return true;
}
}
return false;
}
public static bool IsIn<T>(this T obj, ICollection<T> list)
{
return list.Contains(obj);
}
public static bool IsIn<T>(this T obj, IEnumerable<T> list)
{
foreach (var item in list)
{
if (obj == item)
{
return true;
}
}
return false;
}
}
答案 10 :(得分:2)
在Python中你可以说......
isPrimaryColor = someColor in ('Red', 'Blue', 'Yellow')
...我觉得比你的(== "Red" or == "Blue")
语法更具可读性。为语言功能添加语法支持有几个原因:
someNumber (> 1 and < 10)
)它可能更有用,但即使这样它也不会给你带来太大的帮助(Python允许你说1 < someNumber < 10
,这更加清晰)。所以不清楚提议的更改是否特别有用。
答案 11 :(得分:2)
我的猜测是语言是靠习惯设计的。早期语言只有二进制比较运算符,因为它们更容易实现。每个人都习惯说(x > 0 and x < y
),直到语言设计师不再费心去支持数学中的常见形式(0 < x < y
)。
在大多数语言中,比较运算符返回布尔类型。在0 < x < y
的情况下,如果将其解释为(0 < x) < y
,那将毫无意义,因为<
对于比较布尔值没有意义。因此,新编译器可以将0 < x < y
解释为tmp:=x, 0 < tmp && tmp < y
,而不会破坏向后兼容性。但是,对于x == y == z
,如果变量已经是布尔值,则这意味着x == y && y == z
还是(x == y) == z
是不明确的。
在C#中,我使用以下扩展方法,以便您可以编写someColor.IsOneOf("Red", "Blue", "Yellow"
)。它比直接比较效率低(如果Equals()
是值类型,则与数组,循环,T
调用和装箱相比),但它确实很方便。
public static bool IsOneOf<T>(this T value, params T[] set)
{
object value2 = value;
for (int i = 0; i < set.Length; i++)
if (set[i].Equals(value2))
return true;
return false;
}
答案 12 :(得分:2)
答案 13 :(得分:1)
我还没有看到Objective-C答案。这是一个:
BOOL isPRimaryColour = [[NSSet setWithObjects: @"red", @"green", @"blue", nil] containsObject: someColour];
答案 14 :(得分:1)
这是因为编程语言尤其受到数学,逻辑和集合论的影响。布尔代数以一种不像口语自然语言那样工作的方式定义∧,∨运算符。您的示例将写为:
Let p(x) be unary relation which holds if and only if x is a primary color
p(x) ⇔ r(x) ∨ g(x) ∨ b(x)
or
p(x) ⇔ (x=red) ∨ (x=green) ∨ (x=blue)
如您所见,它与编程语言中使用的符号非常相似。由于数学提供了强大的理论基础,编程语言基于数学而不是自然语言,这总是为解释留下了很多空间。
编辑:使用集合表示法可以简化上述声明:
p(x) ⇔ x ∈ {red, green, blue}
实际上,一些编程语言,最着名的是Pascal,包括set,所以你可以输入:
type
color = (red, green, blue, yellow, cyan, magenta, black, white);
function is_primary (x : color) : boolean;
begin
is_primary := x in [red, green, blue]
end
但作为语言特征的集合并没有流行起来。
PS。抱歉我的英语不完美。
答案 15 :(得分:1)
我想起了我第一次开始学习编程的时候,在Basic中,有一次我写了
if X=3 OR 4
如果X是3或4,我打算像你所描述的那样。编译器将其解释为:
if (X=3) OR (4)
即,如果X = 3为真,或者如果4为真。因为它将非零定义为真,4为真,任何OR TRUE都为真,因此表达式始终为真。我花了很长时间想出那个。
我不认为这会增加讨论的内容。我只是觉得这可能是一个有趣的轶事。
答案 16 :(得分:1)
作为一名数学家,我会说,当且仅当它是原色{红色,绿色,蓝色}的成员时,颜色才是主要颜色。
这正是你在Delphi中所说的:
isPrimary := Colour in [clRed, clGreen, clBlue]
事实上,我经常使用这种技术。上次是三天前。我写了
,实现了我自己的脚本语言解释器const
LOOPS = [pntRepeat, pntDoWhile, pntFor];
然后,几行,
if Nodes[x].Type in LOOPS then
@supercat等(“至于为什么没有人这样做,我不知道。”):
可能是因为编程语言的设计者是数学家(或者至少是数学上倾向的)。如果数学家需要陈述两个对象的相等性,她会说
X = Y,
自然。但是如果X可以是A,B,C ......之类的东西之一,那么她会定义这些东西的集合S = {A, B, C, ...}
并写下
X ∈ S.
事实上,你(数学家)写X ∈ S
,其中S是集
S = {x ∈ D; P(x)}
具有属性P的某些Universe D中的对象,而不是写P(X)
。例如,不是说“x是正实数”或“PositiveReal(x)”,而是说x ∈ ℝ⁺
。
答案 17 :(得分:1)
这个问题是合理的,我不认为这种改变是语法糖。如果被比较的值是计算的结果,那么可以更好地说:
if (someComplicatedExpression ?== 1 : 2 : 3 : 5)
而不是说
int temp; temp = someComplicatedExpression; if (temp == 1 || temp == 2 || temp == 3 || temp == 5)
特别是如果没有其他需要的temp变量。现代编译器可能会识别'temp'的短暂使用寿命并将其优化为寄存器,并且可能识别出“看看变量是否是某个常量之一”模式,但允许程序员使用它并没有什么坏处保存编译器的麻烦。指示的语法不会在任何现有的编译器上编译,但我认为它不会比(a + b&gt;&gt; c + d)更加模糊,其行为是在语言规范中定义的。
至于为什么没有人这样做,我不知道。
答案 18 :(得分:1)
你必须在抽象层上稍微找一下原因。 x86的比较/跳转指令是二进制的(因为它们可以在几个时钟周期内轻松计算),这就是事情的发展方式。
如果你愿意,许多语言都提供了抽象。例如,在PHP中,您可以使用:
$isPrimaryColor = in_array($someColor, array('Red', 'White', 'Blue'));
答案 19 :(得分:0)
只是添加语言示例
<强>方案强>
(define (isPrimaryColor color)
(cond ((member color '(red blue yellow)) #t)
(else #f)))
(define (someNumberTest x)
(cond ((or (and (>= x 1) (<= x 100)) (and (>= x 10000 (<= x 2000))) #t)
(else #f)))
答案 20 :(得分:0)
两种可能性
爪哇
boolean isPrimary = Arrays.asList("red", "blue", "yellow").contains(someColor);
的Python
a = 1500
if 1 < a < 10 or 1000 < a < 2000:
print "In range"
答案 21 :(得分:0)
你给出的后一个例子是有效的语法糖,他们必须评估与更长形式相同的代码,因为在某些时候执行的代码必须依次将你的值与每个条件进行比较。
数组比较语法,在这里以几种形式给出,更接近,我怀疑还有其他语言更接近。
使语法更接近自然语言的主要问题是后者不仅含糊不清,而且含糊不清。即使将模糊性保持在最低限度,我们仍然设法在我们的应用程序中引入错误,你能想象如果用自然英语编程会是什么样的吗?!
答案 22 :(得分:0)
这可以在Lua中用一些可以理解的魔法复制:D
local function operator(func)
return setmetatable({},
{__sub = function(a, _)
return setmetatable({a},
{__sub = function(self, b)
return f(self[1], b)
end}
)
end}
)
end
local smartOr = operator(function(a, b)
for i = 1, #b do
if a == b[i] then
return true
end
end
return false
end)
local isPrimaryColor = someColor -smartOr- {"Red", "Blue", "Either"}
注意:您可以将-smartOr-的名称更改为-isEither-,以使其更具可读性。
答案 23 :(得分:-1)
计算机上的语言比较为二进制,因为它们都是使用二进制来表示信息的机器。它们使用类似的逻辑和大致相似的目标设计。英语不是逻辑设计的,旨在描述算法,人脑(它运行的硬件)不是基于二进制。它们是专为不同任务而设计的工具。