代码之家  ›  专栏  ›  技术社区  ›  Joel Mueller

F:通常不应重新定义“&”运算符

  •  6
  • Joel Mueller  · 技术社区  · 14 年前

    从有限的单字符运算符集定义自定义运算符时,可以同时使用中缀和前缀运算符( + - % & )我决定使用和号,因为它是迄今为止我在代码中唯一有机会使用的运算符。我的理由是 fairly limited use 在f中,重新定义它对于使用我的库的人来说是最不容易混淆的。

    但是,当我这样做时,会收到一个编译器警告:

    通常不应重新定义“&”运算符。考虑使用不同的运算符名称。

    我的问题是,为什么这个看似罕见的操作符会生成这个警告消息,而像加号和减号这样常用的操作符却不会?另外,我应该如何认真对待这个警告?

    2 回复  |  直到 14 年前
        1
  •  8
  •   Tomas Petricek    14 年前

    在创建自定义运算符时,我通常更喜欢查找不与任何现有f运算符冲突的简单符号组合。事实上,符号集是非常有限的,所以这并不总是可能的。但是,例如,您可以定义 -&- 您可以经常选择一些反映运算符含义的组合。只是出于好奇,你的接线员是什么意思?

    不管怎样,当我找不到一个好的操作符名时,我认为这是一个标志,也许我不应该使用自定义操作符(毕竟,许多语言在没有自定义操作符的情况下很容易生存)。我认为自定义运算符的主要用途可能是一些专门的数学知识。您可以经常更换操作员(例如 a -&- b )与管道系统一起使用的功能(例如 a |> connectTo b )还有一个 neat trick 它允许您将函数用作中缀运算符。

    万一 & ,我认为,如果您对运算符有很好的使用,并且您想要定义的运算符的行为与 & 符号。

    编辑 定义自己的 & 操作员不会破坏 & 符号(在模式匹配中)。下面是一个 和模式 :

    // define custom & operator
    let (&) a b = a + b
    
    match 2 with
    | num1 & num2 -> num1 + num2 // Still works fine
    

    这个 和模式 允许您将单个值与单个模式中的多个模式匹配(在上面的示例中,我们只是将其绑定到两个不同的值)

        2
  •  4
  •   kvb    14 年前

    您将无法调用采用byref参数的方法。这对你来说可能是件大事,也可能不是什么大事。

    关于你关于“和模式”的问题,这里有一个简单的例子。但是,请注意定义自己的一元 & 操作员不会以任何方式影响此行为。

    let (|Contains|_|) (s:string) (x:string) =
      if (x.Contains(s)) then Some() else None
    
    match "test" with
    | Contains "e" & Contains "s" -> printfn "Success!"
    | _ -> ()
    

    奇怪的是,我只看到你在定义 二元的 (&) 操作员,而不是一元 (~&) 操作员。

    编辑

    虽然我看不到它在规范中显式调用,但它看起来像二进制文件 & 运算符用作二进制文件的同义词 && 操作员。我想建议不要重新定义这个运算符,因为它是一个短路运算符,但您的重载不能。