Ошибка: неожиданный инфиксный оператор в выражении, об успешно скомпилированном префиксном операторе
Немного поиграв с инфиксными операторами, я был удивлен следующим:
let (>~~~) = function null -> String.Empty | s -> s // compiles fine, see screenshot
match >~~~ input with .... // error: Unexpected infix operator in expression
а также:
Изменение первых символов префиксного оператора (на !~~~
например) исправляет это. То, что я получаю сообщение об ошибке, что инфиксный оператор является неожиданным, довольно странно. Зависание показывает определение быть string -> string
,
Я не слишком удивлен этой ошибкой, F# требует (iirc), чтобы первый символ префиксного оператора сам по себе был одним из предопределенных префиксных операторов. Но почему он компилируется просто отлично, и когда я его использую, компилятор жалуется?
Обновление: компилятор F#, кажется, прекрасно знает, что в других случаях, когда я использую недопустимый символ в своем определении оператора, он говорит: "Недопустимое определение оператора. В определениях префиксных операторов должно использоваться допустимое имя префиксного оператора".
1 ответ
Правила для пользовательских операторов в F# довольно жесткие - поэтому, даже если вы можете определить пользовательские операторы, существует множество правил их поведения, и вы не можете их изменить. Особенно:
- Только некоторые операторы (в основном те, с
!
а также~
) может использоваться в качестве префиксных операторов. С~
Вы также можете перегружать унарные операторы+
,-
,~
а также~~
, так что если вы определите оператор с именем~+.
, вы можете использовать его как, например,+. 42
, - Другие операторы (в том числе те, которые начинаются с
>
) можно использовать только как инфикс. Вы можете превратить любой оператор в обычную функцию, используя круглые скобки, поэтому(+) 1 2
является действительным. ?
Символы являются специальными (они используются для динамического вызова) и не могут появляться в качестве первого символа пользовательского оператора.
Я думаю, что наиболее интуитивный способ думать об этом заключается в том, что пользовательские операторы будут вести себя как стандартные операторы F#, но вы можете добавить дополнительные символы после имени стандартного оператора.