跳转到内容

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
上一页:异常处理 索引 下一页:类
华夏公益教科书