F# 程式設計/運算子過載
外觀
< F# 程式設計
| F#:運算子過載 |
運算子過載允許程式設計師為 F# 中的預設運算子提供新行為。在實踐中,程式設計師過載運算子以提供一種簡化的語法,用於可以數學組合的物件。
你已經使用過運算子了
let sum = x + y
這裡 + 是使用數學加法運算子的示例。
運算子是具有特殊名稱的函式,用括號括起來。它們必須定義為靜態類成員。以下是在複數上宣告 + 運算子的示例
type Complex =
{ Re: double
Im: double }
static member ( + ) (left: Complex, right: Complex) =
{ Re = left.Re + right.Re; Im = left.Im + right.Im }
在 FSI 中,我們可以按如下方式新增兩個複數
> let first = { Re = 1.0; Im = 7.0 };;
val first : Complex
> let second = { Re = 2.0; Im = -10.5 };;
val second : Complex
> first + second;;
val it : Complex = {Re = 3.0;
Im = -3.5;}
除了過載現有的運算子之外,還可以定義新的運算子。自定義運算子的名稱只能是以下一個或多個字元
!%&*+-./<=>?@^|~
F# 支援兩種型別的運算子:中綴運算子和字首運算子。
中綴運算子接受兩個引數,運算子出現在兩個引數之間(即 arg1 {op} arg2)。我們可以使用以下語法定義自己的中綴運算子
let (op) arg1 arg2 = ...
除了數學運算子之外,F# 還將其庫中定義了許多中綴運算子,例如
let inline (|>) x f = f x
let inline (::) hd tl = Cons(hd, tl)
let inline (:=) (x : 'a ref) value = x.contents <- value
假設我們正在編寫一個執行大量正則表示式匹配和替換的應用程式。我們可以透過定義自己的運算子來使用 Perl 風格的運算子匹配文字,如下所示
open System.Text.RegularExpressions
let (=~) input pattern =
Regex.IsMatch(input, pattern)
let main() =
printfn "cat =~ dog: %b" ("cat" =~ "dog")
printfn "cat =~ cat|dog: %b" ("cat" =~ "cat|dog")
printfn "monkey =~ monk*: %b" ("monkey" =~ "monk*")
main()
該程式輸出以下內容
cat =~ dog: false cat =~ cat|dog: true monkey =~ monk*: true
字首運算子接受一個引數,該引數出現在運算子的右側({op}argument)。你已經看到 ! 運算子是如何為 ref 單元格定義的
type 'a ref = { mutable contents : 'a }
let (!) (x : 'a ref) = x.contents
假設我們正在編寫一個數字處理應用程式,我們想要定義一些在數字列表上工作的運算子。我們可能會在 fsi 中定義一些字首運算子,如下所示
> let ( !+ ) l = List.reduce ( + ) l
let ( !- ) l = List.reduce ( - ) l
let ( !* ) l = List.reduce ( * ) l
let ( !/ ) l = List.reduce ( / ) l;;
val ( !+ ) : int list -> int
val ( !- ) : int list -> int
val ( !* ) : int list -> int
val ( !/ ) : int list -> int
> !* [2; 3; 5];;
val it : int = 30
> !+ [2; 3; 5];;
val it : int = 10
> !- [2; 3; 7];;
val it : int = -8
> !/ [100; 10; 2];;
val it : int = 5