代码之家  ›  专栏  ›  技术社区  ›  Davy8

为什么大多数编程语言只有二进制相等比较运算符?

  •  29
  • Davy8  · 技术社区  · 14 年前

    在我见过的每一种编程语言中,这都可以转化为:

    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)
    
    24 回复  |  直到 14 年前
        1
  •  12
  •   Zifre    14 年前

    在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")]
    
        2
  •  23
  •   mqp    14 年前

    我认为大多数人认为

    isPrimaryColor = ["Red", "Blue", "Yellow"].contains(someColor)
    

        3
  •  18
  •   miku    14 年前

    在python中,可以执行以下操作:

    color = "green"
    
    if color in ["red", "green", "blue"]:
        print 'Yay'
    

    它被称为 in 运算符,用于测试集成员身份。

        4
  •  13
  •   Daenyth    14 年前

    在Perl6中,可以使用 junctions :

    if $color eq 'Red'|'Blue'|'Green' {
        doit()
    }
    

    ~~ ). 以下内容大致相当于python的 if value in list: 语法,除了 在其他情况下做得更多。

    if ($color ~~ qw/Red Blue Green/) {
        doit()
    }
    

    paren还使它在perl 5中有效(>=5.10); 在Perl6中,它们是可选的。

        5
  •  9
  •   Mark Rushakoff    14 年前

    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
    
        6
  •  7
  •   Jeffrey L Whitledge    14 年前

    到目前为止,还没有人提到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
    
        7
  •  6
  •   NealB    14 年前

    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应该模仿英语 在某种程度上。

        8
  •  5
  •   dolmen    14 年前

    你会喜欢的 Perl 6 因为它有:

    $someNumber ~~ (1..100) | (1000..2000)
    
        9
  •  4
  •   Christian    14 年前

    Python实际上让您能够很好地完成最后一件事:

    >>> x=5
    >>> (1<x<1000 or 2000<x<3000)
    True
    
        10
  •  2
  •   Chris B.    14 年前

    用Python你可以说。。。

    isPrimaryColor = someColor in ('Red', 'Blue', 'Yellow')
    

    (== "Red" or == "Blue") 语法。为语言功能添加语法支持有几个原因:

    • 效率 :这不是原因,因为没有速度提升。
    • 功能 :也不是问题;在新语法中你做不到旧语法中做不到的事情。
    • 易读性 :大多数语言都能很好地处理检查多个值相等的情况。在其他情况下(例如。, someNumber (> 1 and < 10) )它可能更有用,但即便如此,它也不会给您带来太多好处(Python允许您这么说) 1 < someNumber < 10 ,这更清楚)。

        11
  •  2
  •   Qwertie    14 年前

    我猜语言是由习惯的力量设计的。早期的语言只有二进制比较运算符,因为它们更易于实现。每个人都习惯于说( x > 0 and 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
  •   Paul Nathan    14 年前

    Icon 有你描述的设施。

    if y < (x | 5) then write("y=", y)
    

    我比较喜欢图标的这方面。

        13
  •  2
  •   John Gietzen    14 年前

    在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;
        }
    }
    
        14
  •  1
  •   quantumSoup    14 年前

    您必须深入抽象层以找出原因。x86的比较/跳转指令是二进制的(因为它们可以很容易地在几个时钟周期内计算出来),这就是过去的情况。

    $isPrimaryColor = in_array($someColor, array('Red', 'White', 'Blue'));
    
        15
  •  1
  •   JeremyP    14 年前

    我还没有看到客观的答案。这里有一个:

    BOOL isPRimaryColour = [[NSSet setWithObjects: @"red", @"green", @"blue", nil] containsObject: someColour];
    
        16
  •  1
  •   supercat    14 年前

    这个问题是合理的,我不认为这个变化是句法上的甜点。如果所比较的值是计算的结果,那么最好说:

      if (someComplicatedExpression ?== 1 : 2 : 3 : 5)
    

      int temp;
      temp = someComplicatedExpression;
      if (temp == 1 || temp == 2 || temp == 3 || temp == 5)
    

    特别是如果没有其他需要讨论的temp变量。一个现代的编译器可能会识别“temp”的短暂有效期并将其优化为一个寄存器,并且可能会识别“查看变量是否是某个常量之一”模式,但是允许程序员为编译器省去麻烦并没有坏处。指定的语法不会在任何现有编译器上编译,但我认为它不会比(a+b>&燃气轮机;其行为在语言规范中定义。

        17
  •  1
  •   Jay    14 年前

    我想起了我刚开始学习编程的时候,在Basic中,我曾经写过

    if X=3 OR 4
    

    我的意图和你描述的一样,如果X是3或4。编译器将其解释为:

    if (X=3) OR (4)
    

    也就是说,如果X=3为真,或者如果4为真。因为它定义任何非零的事物为真,4为真,任何事物或真都为真,所以表达式总是真的。我花了很长时间才弄明白。

        18
  •  1
  •   Andreas Rejbrand    14 年前

    作为一个数学家,我想说颜色是原色当且仅当它是原色集合{红,绿,蓝}的一员。

    这正是你在德尔斐所说的:

    isPrimary := Colour in [clRed, clGreen, clBlue]
    

    事实上,我经常使用这种技术。上次是三天前。实现我自己的脚本语言的解释器,我写道

    const
      LOOPS = [pntRepeat, pntDoWhile, pntFor];
    

    然后,在几行,

    if Nodes[x].Type in LOOPS then
    

    问题的哲学部分

    @超级猫等(“至于为什么没人这么做,我不知道。”):

    X = Y,
    

    当然。但是如果X可以是a,B,C……中的一个,那么她将定义一个集合 S = {A, B, C, ...}

    X ∈ S.
    

    你们(数学家)所写的共同点 X ∈ S ,其中S是集合

    S = {x ∈ D; P(x)}
    

    在某个宇宙D中,具有P属性的物体,而不是书写 P(X) . 例如,人们不说“x是一个正实数”,或者“正实数(x)”,而是说 x ∈ ℝ⁺

        19
  •  1
  •   el.pescado - нет войне    14 年前

    这是因为编程语言特别受数学、逻辑和集合论的影响。布尔代数定义§, ¨ 运算符的工作方式不同于自然语言。你的例子可以写为:

    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
    

    对不起,我的英语不太好。

        20
  •  0
  •   Lazarus    14 年前

    后面给出的例子是有效的语法糖,它们的计算结果必须与较长形式的代码相同,因为在某个时候,执行的代码必须依次将您的值与每个条件进行比较。

    使语法更接近自然语言的主要问题是,自然语言不仅仅是模棱两可的,而且模棱两可。即使将歧义保持在最低限度,我们仍然设法在我们的应用程序中引入bug,你能想象如果你用自然英语编程会是什么样子吗?!

        21
  •  0
  •   Justin Hamilton    14 年前

    方案

    (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)))
    
        22
  •  0
  •   OscarRyz    14 年前

    boolean isPrimary = Arrays.asList("red", "blue", "yellow").contains(someColor);
    

    蟒蛇

    a = 1500
    if  1 < a < 10 or  1000 < a < 2000:
         print "In range"
    
        23
  •  0
  •   warspyking    9 年前

    这可以在Lua中用一些metatable魔法复制: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-以使其更具可读性。

        24
  •  -1
  •   Jay    14 年前