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

F#:什么是有效的前缀运算符?

f#
  •  15
  • Joel Mueller  · 技术社区  · 14 年前

    let (~--) (str:string) = [str];;
    -----^^^
    
    stdin(4,6): error FS1208: Invalid operator definition. 
    Prefix operator definitions must use a valid prefix operator name.
    

    编辑:

    Brian的链接包括以下有效前缀运算符列表:

    ! (or repetitions of !)
    ~ (or repetitions of ~)
    +
    -
    +.
    -.
    %
    %%
    &
    &&
    

    我下面的链接只列出了这些运算符:

    ~
    !
    ?
    

    快速测试表明MSDN文档似乎与语言规范不符。谢谢,Brian。

    3 回复  |  直到 14 年前
        1
  •  14
  •   itowlson    14 年前

    http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/spec.html#_Toc245030784

    说明了规则。我在下面引用了一些(另请参见

    http://msdn.microsoft.com/en-us/library/dd233228(VS.100).aspx

    以下符号操作标记可用于形成表达式:

    infix-op :=
        or || & && <OP >OP $OP = |OP &OP ^OP :: -OP +OP *OP /OP %OP 
        **OP
    
    infix-or=prefix-op :=
        -OP +OP % %% & &&
    
    prefix-op :=
        ! (or repetitions of !)
        ~ (or repetitions of ~) 
        +
        -
        +.
        -.
        %
        %%
        &
        &&
    

    由以下内容组成的运算符始终是前缀运算符:

    • 重复的!
    • 重复~

    不允许使用以这些字符开头的其他运算符。

    运算符+、-、+、-、%、&&&和可以用作前缀和中缀运算符。当用作前缀运算符时,这些运算符有一个带有~前缀的隐式运算符名称。例如,-x被解析为运算符~-对表达式x的应用程序。在为这些前缀运算符提供定义时,也使用此名称:

    这意味着这些前缀运算符是通过添加~字符来定义的:

    // For a complete redefinition of the operator:
    let (~+) x = x
    
    // For defining the operator on a type:
    type C(n:int) =
        let n = n % 7
        member x.N = n
        static member (~+) (x:C) = x
        static member (~-) (x:C) = C(-n)
        static member (+) (x1:C,x2:C) = C(x1.N+x2.N)
        static member (-) (x1:C,x2:C) = C(x1.N-x2.N)
    
        2
  •  17
  •   Olaf    9 年前

    前缀运算符有两种类型:tilde前缀运算符和bang前缀运算符。颚化符前缀运算符以颚化符“~”开头,bang前缀运算符以bang“!”开头。主要区别在于,在应用波浪号前缀运算符时,忽略了波浪号字符。

    颚化符前缀运算符

    以波浪号为前缀的运算符以波浪号“~”开头,后跟以下内容之一:

    波浪号前缀运算符也可以构建为任意数量波浪号的列表:
    ~~, ~~~, ~~~~, ~~~~~, ...

    应用运算符时,必须省略波浪形,除非它是波浪形蛇。

    ╔═════════════╦════════════╦══════════════════════════╗
    ║ declaration ║   usage    ║         remark           ║
    ╠═════════════╬════════════╬══════════════════════════╣
    ║ ~~          ║ ~~         ║                          ║
    ║ ~~~         ║ ~~~        ║                          ║
    ║ ~~~~~~~~~   ║ ~~~~~~~~~  ║ or any number of tildes  ║
    ║ ~+          ║ +          ║                          ║
    ║ ~+.         ║ +.         ║                          ║
    ║ ~-          ║ -          ║                          ║
    ║ ~-.         ║ -.         ║                          ║
    ║ ~%          ║ %          ║                          ║
    ║ ~%%         ║ %%         ║                          ║
    ║ ~&          ║ &          ║                          ║
    ║ ~&&         ║ &&         ║                          ║
    ╚═════════════╩════════════╩══════════════════════════╝
    

    Bang前缀运算符

    带bang前缀的运算符以bang“!”开头后跟以下字符的任意组合:

    此规则的例外是“!=”。前缀运算符不能以此组合开头。

    ╔══════════════╦══════════════╗
    ║ declaration  ║    usage     ║
    ╠══════════════╬══════════════╣
    ║ !!           ║ !!           ║
    ║ !%           ║ !%           ║
    ║ !&           ║ !&           ║
    ║ !*           ║ !*           ║
    ║ !+           ║ !+           ║
    ║ !.           ║ !.           ║
    ║ !/           ║ !/           ║
    ║ !<           ║ !<           ║
    ║ !>           ║ !>           ║
    ║ !@           ║ !@           ║
    ║ !^           ║ !^           ║
    ║ !|           ║ !|           ║
    ║ !~           ║ !~           ║
    ║ !?           ║ !?           ║
    ║ !@=@>        ║ !@=@>        ║
    ║ !!!/<=>@!!!* ║ !!!/<=>@!!!* ║
    ╚══════════════╩══════════════╝
    

    type SomeString = SomeString of string
    
    let ( ~~  ) (SomeString s) = "~~ "  + s
    let ( ~~~ ) (SomeString s) = "~~~ " + s
    let ( ~~~~~~~~~ ) (SomeString s) = "~~~~~~~~~ " + s
    let ( ~+  ) (SomeString s) = "~+ "  + s
    let ( ~+. ) (SomeString s) = "~+. " + s
    let ( ~-  ) (SomeString s) = "~- "  + s
    let ( ~-. ) (SomeString s) = "~-. " + s
    let ( ~%  ) (SomeString s) = "~% "  + s
    let ( ~%% ) (SomeString s) = "~%% " + s
    let ( ~&  ) (SomeString s) = "~& "  + s
    let ( ~&& ) (SomeString s) = "~&& " + s
    
    let x = SomeString "tilde"
    
    printf "%s\n" (~~  x)           // ~~ tilde
    printf "%s\n" (~~~ x)           // ~~~ tilde
    printf "%s\n" (~~~~~~~~~ x)     // ~~~~~~~~~ tilde
    printf "%s\n" (+  x)            // ~+ tilde      
    printf "%s\n" (+. x)            // ~+. tilde
    printf "%s\n" (-  x)            // ~- tilde
    printf "%s\n" (-. x)            // ~-. tilde
    printf "%s\n" (%  x)            // ~% tilde
    printf "%s\n" (%% x)            // ~%% tilde
    printf "%s\n" (&  x)            // ~& tilde
    printf "%s\n" (&& x)            // ~&& tilde
    

    type SomeString = SomeString of string
    
    let ( !! ) (SomeString s) = "!! " + s
    let ( !% ) (SomeString s) = "!% " + s 
    let ( !& ) (SomeString s) = "!& " + s 
    let ( !* ) (SomeString s) = "!* " + s 
    let ( !+ ) (SomeString s) = "!+ " + s 
    let ( !. ) (SomeString s) = "!. " + s 
    let ( !/ ) (SomeString s) = "!/ " + s 
    let ( !< ) (SomeString s) = "!< " + s 
    let ( !> ) (SomeString s) = "!> " + s
    let ( !@ ) (SomeString s) = "!@ " + s 
    let ( !^ ) (SomeString s) = "!^ " + s 
    let ( !| ) (SomeString s) = "!| " + s 
    let ( !~ ) (SomeString s) = "!~ " + s 
    let ( !? ) (SomeString s) = "!? " + s 
    let ( !@=@> ) (SomeString s) = "@=@> " + s 
    let ( !!!/<=>@!!!* ) (SomeString s) = "!!!/<=>@!!!* " + s 
    //let ( != )   (SomeString s) = "!= " + s   // prefix != is not allowed
    //let ( !=@@ ) (SomeString s) = "!= " + s   // prefix != is not allowed
    
    let y = SomeString "bang"
    
    printf "%s\n" (!! y)            // !! bang
    printf "%s\n" (!% y)            // !% bang
    printf "%s\n" (!& y)            // !& bang
    printf "%s\n" (!* y)            // !* bang     
    printf "%s\n" (!+ y)            // !+ bang
    printf "%s\n" (!. y)            // !. bang
    printf "%s\n" (!/ y)            // !/ bang
    printf "%s\n" (!< y)            // !< bang
    printf "%s\n" (!> y)            // !> bang
    printf "%s\n" (!@ y)            // !@ bang
    printf "%s\n" (!^ y)            // !^ bang
    printf "%s\n" (!| y)            // !| bang
    printf "%s\n" (!~ y)            // !~ bang
    printf "%s\n" (!? y)            // !? bang
    printf "%s\n" (!@=@> y)         // !@=@> bang
    printf "%s\n" (!!!/<=>@!!!* y)  // !!!/<=>@!!!* bang
    
        3
  •  1
  •   Joel Mueller    14 年前

    没关系,我想我 found the list here ,在第二个表的“重载运算符名称”标题下。