F#自定义操作符

简介: F#语言支持自定义操作符,特别是对于数学相关领域的应用来说,自定义类型上的操作符可以大大简化代码,提高程序可读性。本文就通过示例讲解全局自定义操作符和附属于特定类型的操作符。

    我们知道,不少编程语言都支持自定义操作符,特别是对于数学相关领域的应用来说,自定义类型上的操作符可以大大简化代码,提高程序可读性。对于F#来说,支持全局的自定义操作符和附属于特定类型的操作符。这里需要注意的就是,全局自定义操作符需要慎用,他可能会覆盖默认的操作符。

   下面我们定义一个全局操作符,具体示例如下:

//全局操作符,覆盖默认的letinline (+)(a : float)(b : float) =2.*a*b ;;

   在F#交互环境下(;;为结束标志),此示例执行如下:

1(16).jpg

   此时,输入 2. + 3. 的计算结果为12.0 。其中的2.是2.0的简写,代表float类型。另外,如果此时输入2 + 3 则提示错误,因为此为int类型,而定义的操作符参数类型是float,不兼容。

   还有一类就是对于自定义类型上的自定义操作符。这种比较常见,下面给出一个自定义复数类型,并给出自定义操作符的示例。

moduleYdMath//https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/operator-overloadingtypeComplex=        {
Real : floatImaginary : float        }
staticmember (+) (f1 : Complex, f2 : Complex) =letcr=f1.Real+f2.Realletci=f1.Imaginary+f2.Imaginary           {Real=cr ; Imaginary=ci}
staticmember (-) (f1 : Complex, f2 : Complex) =letcr=f1.Real-f2.Realletci=f1.Imaginary-f2.Imaginary            {Real=cr ; Imaginary=ci}
overridethis.ToString() =if (this.Imaginary=0.) thenthis.Real.ToString()
elsethis.Real.ToString() +"+"+this.Imaginary.ToString()+"i"

   从数学上来说,复数(Complex)具有一个实部(Real)和一个虚部(Imaginary) ,这里的话,用float类型来代表每个部分的数值类型。其中的static member定义了一个静态成员方法,但它的函数名是一个操作符,可实现自定义操作符功能。这里简单的定义了一个复数的加法和减法操作。并override重写了ToString方法。最后,我们用如下代码段进行自定义操作符测试:

letc1= { Real=3. ; Imaginary=5. }
letc2= { Real=2. ; Imaginary=3. }
letc3=c1+c2letc4=c1-c2printfn"(%s) + (%s) = %s" (c1.ToString()) (c2.ToString()) (c3.ToString())
printfn"(%s) - (%s) = %s" (c1.ToString()) (c2.ToString()) (c4.ToString())

   运行此示例,结果如下:

(3+5i) + (2+3i) =5+8i(3+5i) - (2+3i) =1+2i

  最后,再给出一个根据官方文档示例修改的自定义操作符:

letrechcfab=ifa=0.thenbelifa<bthenhcfa (b-a)
elsehcf (a-b) b//分数typeFract=       {
fz : float//分子fm : float//分母       }
staticmember (+) (f1 : Fract, f2 : Fract) =letfz=f1.fz*f2.fm+f2.fz*f1.fmletfm=f1.fm*f2.fmletcf=hcffzfm          { fz=fz/cf; fm=fm/cf }
staticmember (-) (f1 : Fract, f2 : Fract) =letfz=f1.fz*f2.fm-f2.fz*f1.fmletfm=f1.fm*f2.fmletcf=hcffzfm           { fz=fz/cf; fm=fm/cf }
staticmember (*) (f1 : Fract, f2 : Fract) =letfz=f1.fz*f2.fzletfm=f1.fm*f2.fmletcf=hcffzfm          { fz=fz/cf; fm=fm/cf }
staticmember (/) (f1 : Fract, f2 : Fract) =letfz=f1.fz*f2.fmletfm=f2.fz*f1.fmletcf=hcffzfm          { fz=fz/cf; fm=fm/cf }
overridethis.ToString() =if (this.fm=1.)
thenthis.fz.ToString()
elsethis.fz.ToString() +"/"+this.fm.ToString()

执行测试代码示例如下:

letf1= { fz=2.; fm=5.}
letf2= { fz=1.; fm=6.}
letf=f1+f2printfn"(%s) + (%s) = %s" (f1.ToString()) (f2.ToString()) (f.ToString())
letf=f1-f2printfn"(%s) - (%s) = %s" (f1.ToString()) (f2.ToString()) (f.ToString())
letf=f1*f2printfn"(%s) * (%s) = %s" (f1.ToString()) (f2.ToString()) (f.ToString())
letf=f1/f2printfn"(%s) / (%s) = %s" (f1.ToString()) (f2.ToString()) (f.ToString())

执行示例结果如下:

(2/5) + (1/6) =17/30(2/5) - (1/6) =7/30(2/5) * (1/6) =1/15(2/5) / (1/6) =12/5
相关文章
|
存储 缓存 安全
C++数组全解析:从基础知识到高级应用,领略数组的魅力与技巧
C++数组全解析:从基础知识到高级应用,领略数组的魅力与技巧
776 1
C#学习相关系列之多线程---ConfigureAwait的用法
C#学习相关系列之多线程---ConfigureAwait的用法
708 0
|
数据库
AOP(面向切面编程)的基本概念和原理
AOP(面向切面编程)的基本概念和原理
955 0
|
SQL Oracle 关系型数据库
SQL SELECT TOP 详解
SQL SELECT TOP 详解
|
SQL 消息中间件 canal
Flink cdc自定义format格式数据源
变更数据捕获 (CDC) 已成为一种流行的模式,本文介绍如何通过自定义format来获取不同格式cdc数据源
Flink cdc自定义format格式数据源
|
安全 网络虚拟化
VLAN这6个常见问题,是个网工都遇到过!
VLAN这6个常见问题,是个网工都遇到过!
644 0
|
安全 Java 开发者
如何在Java中实现线程安全的单例模式
如何在Java中实现线程安全的单例模式
|
安全 Java PHP
代码审计——命令执行详解
代码审计——命令执行详解
515 0
|
Java
JDK8中Stream的Filter方法
JDK8中Stream的Filter方法
694 0

热门文章

最新文章