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.
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.
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 ║
║ ~+ ║ + ║ ║
║ ~+. ║ +. ║ ║
║ ~- ║ - ║ ║
║ ~-. ║ -. ║ ║
║ ~% ║ % ║ ║
║ ~%% ║ %% ║ ║
║ ~& ║ & ║ ║
║ ~&& ║ && ║ ║
╚═════════════╩════════════╩══════════════════════════╝
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 ║
╠══════════════╬══════════════╣
║ !! ║ !! ║
║ !% ║ !% ║
║ !& ║ !& ║
║ !* ║ !* ║
║ !+ ║ !+ ║
║ !. ║ !. ║
║ !/ ║ !/ ║
║ !< ║ !< ║
║ !> ║ !> ║
║ !@ ║ !@ ║
║ !^ ║ !^ ║
║ !| ║ !| ║
║ !~ ║ !~ ║
║ !? ║ !? ║
║ !@=@> ║ !@=@> ║
║ !!!/<=>@!!!* ║ !!!/<=>@!!!* ║
╚══════════════╩══════════════╝
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
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:
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)
Never mind, I think I found the list here, in the second table under the "Overloaded Operator Names" heading.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With