Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F#: What are the valid prefix operators?

Tags:

f#

Is there a list of valid prefix operator names somewhere? I haven't been able to find one, but I've noticed that some operators that used to be valid as prefix operators in the last CTP are no longer valid in the RC.

let (~--) (str:string) = [str];;
-----^^^

stdin(4,6): error FS1208: Invalid operator definition. 
Prefix operator definitions must use a valid prefix operator name.

Edit:

Brian's link includes the following list of valid prefix operators:

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

My link below lists only these operators:

~
!
?

A quick test shows that the MSDN docs do not seem to be current with the language spec. Thanks, Brian.

like image 663
Joel Mueller Avatar asked Feb 20 '10 23:02

Joel Mueller


3 Answers

There are two types of prefix operators: tilde-prefixed operators and bang-prefixed operators. Tilde-prefixed operators start with a tilde "~" and bang-prefixed operators start with a bang "!". The main difference is that you omit the tilde character when you apply a tilde-prefixed operator.

Tilde-prefixed operators

A tilde-prefixed operator begins with a tilde "~" followed by one of these:
+, -, +., -., %, %%, &, &&

A tilde-prefixed operator can also be build as a list of any numbers of tildes:
~~, ~~~, ~~~~, ~~~~~, ...

When you apply the operator you have to omit the tilde unless it is a tilde snake.

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

Bang-prefixed operators

A bang-prefixed operator begins with a bang "!" followed by any combination of these characters:
!, %, &, *, +, ., /, <, =, >, @, ^, |, ~, ?

The exception of this rule is "!=". A prefix operator must not begin with this combination.

This table lists some examples.

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

Code snippet tilde-prefixed operators

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

Code snippet bang-prefixed operators

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
like image 200
Olaf Avatar answered Nov 11 '22 14:11

Olaf


See

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

which spells out the rules. I've quoted some of it below. (See also

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

but I think it doesn't have the full rules.)

The following symbolic-op tokens can be used to form expressions:

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 ~) 
    +
    -
    +.
    -.
    %
    %%
    &
    &&

Operators made of the following are always prefix operators:

  • repeated !
  • repeated ~

Other operators beginning with these characters are not permitted.

The operators +, -, +., -., %, &, && and may be used as both prefix and infix operators. When used as prefix operators these operators have an implicit operator name with ~ prepended. For example, -x is parsed as an application of the operator ~- to the expression x. This name is also used when giving definitions for these prefix operators:

This means that these prefix operators are defined with the ~ character added:

// 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)
like image 28
Brian Avatar answered Nov 11 '22 15:11

Brian


Never mind, I think I found the list here, in the second table under the "Overloaded Operator Names" heading.

like image 2
Joel Mueller Avatar answered Nov 11 '22 14:11

Joel Mueller