F#:'&'通常不应重新定义运算符

时间:2010-02-22 20:30:08

标签: f# operators

当从有限的单字符运算符(可以是中缀运算符和+ - % &)定义自定义运算符时,我决定使用&符号,因为它是我拥有的那些运算符中唯一的一个到目前为止还没有机会在我的F#代码中使用。我推断,因为&似乎在F#中有fairly limited use,重新定义它对于使用我的库的人来说是最不容易的。

然而,当我这样做时,我收到编译器警告:

  

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

我的问题是,为什么这个看似罕见的运算符会生成此警告消息,而常用的运算符(如加号和减号)则不会?另外,我应该多么认真地接受这个警告?

2 个答案:

答案 0 :(得分:8)

创建自定义运算符时,我通常更喜欢找到一个与任何现有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

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

答案 1 :(得分:4)

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

关于“AND模式”的问题,这里有一个简单的例子。但请注意,定义自己的一元&运算符不会以某种方式影响此行为。

let (|Contains|_|) (s:string) (x:string) =
  if (x.Contains(s)) then Some() else None

match "test" with
| Contains "e" & Contains "s" -> printfn "Success!"
| _ -> ()

奇怪的是,我只看到您在定义二进制 (&)运算符时提到的警告,而不是一元(~&)运算符。

修改

虽然我没有在规范中明确地看到它,但看起来二进制&运算符被用作二进制&&运算符的同义词。我猜想没有重新定义这个运算符的建议存在,因为它是一个短路运算符,但你的重载不可能。