3

玩弄中缀运算符后,我对以下内容感到惊讶:

let (>~~~) = function null -> String.Empty | s -> s  // compiles fine, see screenshot
match >~~~ input with .... // error: Unexpected infix operator in expression

val (>~~~) : 字符串 -> 字符串)

和:

意外的中缀运算符

更改前缀运算符的第一个字符(!~~~例如)修复它。我得到一个中运算符意外的错误是相当奇怪的。悬停显示定义为string -> string

我对这个错误并不感到惊讶,F# 要求 (iirc) 前缀运算符的第一个字符本身必须是预定义的前缀运算符之一。但是为什么它编译得很好,当我使用它时,编译器会抱怨?

更新:F# 编译器似乎知道在其他情况下,当我在运算符定义中使用无效字符时,它会显示“无效的运算符定义。前缀运算符定义必须使用有效的前缀运算符名称。”

无效的运算符定义。

4

1 回答 1

3

F# 中自定义运算符的规则非常严格 - 因此即使您可以定义自定义运算符,也有很多关于它们的行为方式的规则,您无法更改这些规则。尤其是:

  • 只有一些运算符(主要是带有!and的运算符~)可以用作前缀运算符。~你也可以重载一元运算符+, -, ~and ~~,所以如果你定义了一个名为 的运算符,~+.你就可以将它用作 eg +. 42
  • 其他运算符(包括以 开头的运算符>)只能用作中缀。您可以使用括号将任何运算符转换为普通函数,这就是 eg(+) 1 2有效的原因。
  • 符号是特殊的?(用于动态调用),不能作为自定义运算符的第一个符号出现。

我认为最直观的思考方式是自定义运算符的行为类似于标准 F# 运算符,但您可以在标准运算符名称后添加其他符号。

于 2016-09-06T12:46:06.643 回答