如果你也会C#,那不妨了解下F#(2):数值运算和流程控制语法
2016-08-14 22:57
357 查看
本文链接:http://www.cnblogs.com/hjklin/p/fs-for-cs-dev-2.html
推广得好,用的人多,问题也能及时得到解决,用的人就越多,这是一个良性循环,即使语言本身有很多不足也很快能得到解决。
但有的语言本身很好,使用者却不多,缺少交流和推广,致使进入恶性循环。
《黑客与画家》作者把Lisp吹上天,但却没见他继续推广,至今在使用的团队和行业还是很有限。
而说到F#,国内也出过F#的高校教材,不知道是否有高校开课,在企业上更是很少使用。
“赵姐夫”(博客)在10年说过要做F#在国内的推广者,几年过去了,也是无声无息。
那为什么在2016年的现在,那么多新的语言和技术,我们还要来了解F#呢?
F#和C#一样,也是基于.Net平台的语言,了解了语法后,就能快速地使用.Net框架甚至C#编写的框架,
而且在学习过程中.Net框架中很多以前不理解的东西,通过F#就变得很容易理解了。作为.Net程序员,还是值得了解的。
函数式语言的“天然支持异步和并行”的能力,也使得多线程开发变得简单。
C#在最近的版本中经常得益于F#对.Net框架的推进,如加入了
在最近发布的.Net Core中,也可以通过
F#并无法替代C#,但两者却能起到互补的作用。
记得《七周七语言》里说过:
每学一门新的语言,思维方式都会发生改变。编程语言亦是如此。
作者在书中说,每学习一门语言都会去找互动教程,但大多数情况下并找不到称心如意的。
若想领会一门语言的精髓,它(指互动教程)可就无能为力了。我想要的是那种痛快淋漓、深入探索语言本质的感觉。
我是没有作者的这种能通过探索语言本质的能力来介绍F#,但希望也能让大家发现F#语言的动人心弦之处。
废话说得有点多了,下面继续介绍F#吧。
四则运算和模运算(取余)不必多说,但对于浮点数(
像
大整数于.Net 4.0添加到框架中,在
在内存足够的情况下,
当然也可以使用.Net框架的
注:“或”使用
那就会有人说,F#也有可变的值啊,怎么赋值呢!没错,在上面的示例代码中
所以需要注意,C#中的
此外,F#中还有一个
这个比较在C#中有实现过
在.Net中,比较是一个复杂的话题,在此就不展开了,可参考MSDN文章(Object.Equals方法和IComparable 接口)。
C# 代码:
F# 代码:
F#版本中的
遗憾的是
while循环语句
用
C# 代码:
F# 代码:
需要注意的是,F#中并没有
刚开始接触F#或习惯了C#的循环语句可能会不习惯,但当你熟悉了函数式编程的思想后,会发现这些在F#中都是不重要的,甚至循环语句都是不必要的。
同时,也尽量不要使用可变类型。因为值的不可变性,使多线程编程变得简单;而在C#中,因为值默认为可变的,使程序在多线程运行中增加了很多不确定因素。
在F#中,
在F#的if语句中,每个分支必须返回相同类型的值,但不需要
如果if分支没有返回值(即返回
C#中的
C# 代码:
F# 代码:
其中
但F#中的
模式匹配(Pattern Matching)。
模式匹配在函数式编程中有着作用,在之后的函数式编程中也会进行介绍。
在下一篇中,我们来了解数组和列表,以及一些F#特有的类型。
一些废话
一门语言火不火,与语言本身并没太大关系,主要看语言的推广。推广得好,用的人多,问题也能及时得到解决,用的人就越多,这是一个良性循环,即使语言本身有很多不足也很快能得到解决。
但有的语言本身很好,使用者却不多,缺少交流和推广,致使进入恶性循环。
《黑客与画家》作者把Lisp吹上天,但却没见他继续推广,至今在使用的团队和行业还是很有限。
而说到F#,国内也出过F#的高校教材,不知道是否有高校开课,在企业上更是很少使用。
“赵姐夫”(博客)在10年说过要做F#在国内的推广者,几年过去了,也是无声无息。
那为什么在2016年的现在,那么多新的语言和技术,我们还要来了解F#呢?
F#和C#一样,也是基于.Net平台的语言,了解了语法后,就能快速地使用.Net框架甚至C#编写的框架,
而且在学习过程中.Net框架中很多以前不理解的东西,通过F#就变得很容易理解了。作为.Net程序员,还是值得了解的。
函数式语言的“天然支持异步和并行”的能力,也使得多线程开发变得简单。
C#在最近的版本中经常得益于F#对.Net框架的推进,如加入了
async关键字,有
Tuple了(虽然在语法层面不支持)等等。
在最近发布的.Net Core中,也可以通过
dotnet new -l f#来创建F#项目。.Net Core里F#的坑,这里就不细说了。 😅 通过.Net博客,也可以发现越来越多人在使用F#。
F#并无法替代C#,但两者却能起到互补的作用。
记得《七周七语言》里说过:
每学一门新的语言,思维方式都会发生改变。编程语言亦是如此。
作者在书中说,每学习一门语言都会去找互动教程,但大多数情况下并找不到称心如意的。
若想领会一门语言的精髓,它(指互动教程)可就无能为力了。我想要的是那种痛快淋漓、深入探索语言本质的感觉。
我是没有作者的这种能通过探索语言本质的能力来介绍F#,但希望也能让大家发现F#语言的动人心弦之处。
废话说得有点多了,下面继续介绍F#吧。
数值运算
我们再翻出上一篇的小例子:let mutable sum = 0 for i = 0 to 100 do if i%2 <> 0 then sum <- sum + i printfn "0到100中的奇数的和为%A" sum ;;
四则运算和模运算(取余)不必多说,但对于浮点数(
float和
float32)类型,还支持
**(幂)语法。
2. ** 3.;; // val it : float = 8.0
像
abs、
sin等这些基本数学函数在F#里也包含在操作符(Operators)的模块里,所有操作符可在MSDN文章(Core.Operators Module(F#))查看。
大整数(BigInteger)
在上一篇的数值类型对比中,我们可以看出,F#在语法层面上支持大整数。大整数于.Net 4.0添加到框架中,在
System.Numerics模块里。F#创建项目时默认引用了此dll。(大整数也支持
**运算符,但指数必须为
int,其实就是
Pow方法。)
let bigInt = 4325I;; //相当于C#的 var bigInt = new BigInteger(4325); 3I ** 8;; // val it : System.Numerics.BigInteger = 6561 ...
在内存足够的情况下,
BigInteger支持任意大的整数。 通过大整数,我们也可以自己实现大实数,或直接使用第三方类库。
数值类型转换
在F#中,没有隐式类型转换,就连int到
long或
float也没有。所以,数值类型转换使用返回对应类型的转换函数:
int 2.5;; // 2 float "3.1415" // 3.1415 (float 2)**(float 3);; //8.0
当然也可以使用.Net框架的
System.Convert静态类。上述方法在转换字符串时也是调用的此方法。
位运算符
F#中的位运算符均使用三重符号:运算符 | 名称 | 示例 | 结果 |
---|---|---|---|
&&& | 与 | 0b1111 &&& 0b0011 | 3 |
||| | 或 | 0xFF00 ||| 0x00FF | 65535 |
~~~ | 取反 | ~~~0b0011 | -4 |
^^^ | 异或 | 0b0011 ^^^ 0b0101 | 6 |
<<< | 左移 | 0b0001 <<< 3 | 8 |
>>> | 右移 | 0b1000 >>> 3 | 1 |
|||,博客园的Markdown渲染时,竟然不支持表格里的
|转义。😅
比较
因为函数式语言中,数值不可变,所以=在F#中并不是赋值符号。
=在F#执行相等比较操作,而不等则为
<>,这两个符号与C#有异:
5=8 ;; //false "ax"<>"ay" ;; //true
那就会有人说,F#也有可变的值啊,怎么赋值呢!没错,在上面的示例代码中
sum为可变值,每次循环通过
<-符号改变其值。好诡异但又好有道理的符号啊! 😲
所以需要注意,C#中的
int i = 1;其实是相当于F#中的
let mutable i = 1。因为C#默认创建的是可变类型。 请查看后面的while循环介绍。
此外,F#中还有一个
compare函数用来比较两个值:
compare 31 31;; // 0 compare 5 4;; // 1 (* compare x y 若x > y则返回1;若x < y则返回-1;若x = y则返回0 *)
这个比较在C#中有实现过
IComparable接口的应该了解,其实
compare函数的参数就是需要实现了
IComparable接口的类型。
在.Net中,比较是一个复杂的话题,在此就不展开了,可参考MSDN文章(Object.Equals方法和IComparable 接口)。
流程控制语法
for循环语句
下面是0到100的循环,从0打印到100:C# 代码:
for (int i=0; i<=100; i++) { System.Console.WriteLine(i); }
F# 代码:
for i=0 to 100 do printfn "%i" i for i in [0..100] do printfn "%i" i for i=100 downto 0 do printfn "%i" i //逆向循环,从100到0
F#版本中的
[0..100]是创建一个从0到100的列表(
list),在之后列表模块会进行介绍。
遗憾的是
for ... to和
for ... downto语句无法创建如
for (int i=0; i<=100; i+=2)这种间隔不为1的循环,只能使用
for ... in再加上一个列表。
while循环语句
用while循环实现的从0打印到100:
C# 代码:
int i = 0; while (i <= 100) { System.Console.WriteLine(i); i++; }
F# 代码:
let mutable i = 0 while i <= 100 do printfn "%i" i <- i + 1
需要注意的是,F#中并没有
do...while的循环,在
for循环和
while循环中,也都没有
break和
continue关键字。
刚开始接触F#或习惯了C#的循环语句可能会不习惯,但当你熟悉了函数式编程的思想后,会发现这些在F#中都是不重要的,甚至循环语句都是不必要的。
同时,也尽量不要使用可变类型。因为值的不可变性,使多线程编程变得简单;而在C#中,因为值默认为可变的,使程序在多线程运行中增加了很多不确定因素。
条件语句之if
在上面的示例代码中已经使用过if语句。
在F#中,
if语句的完整结构是这样的:
if x>y then "x大于y" elif x<y then "x小于y" else "x等于y" if x>y then printfn "x大于y" //if分支无返回值
在F#的if语句中,每个分支必须返回相同类型的值,但不需要
return关键字(在介绍函数时会涉及)。
如果if分支没有返回值(即返回
unit),则else为可选的;否则,必须有else分支。(类似于C#的
?:操作符,但F#中没有这个操作符。)
C#中的
else if在F#中为
elif。
条件语句之switch(match)
在C#中,还有一种分支结构的语句是使用switch...case。在F#中类似的语法是
match...with。
C# 代码:
int i = 1; switch (i) { case 1: Console.WriteLine("this is one"); break; case 2: Console.WriteLine("this is two"); break; case 3: Console.WriteLine("this is three"); break; default: Console.WriteLine("this is something else"); break; }
F# 代码:
let i = 1 match i with | 1 -> printfn "this is one" | 2 -> printfn "this is two" | 3 -> printfn "this is three" | _ -> printfn "this is anything else"
其中
_为通配符,与C#
switch中的
default类似。
但F#中的
match语句功能非常强大,可查看MSDN文章Match表达式(Match Expressions)和
模式匹配(Pattern Matching)。
模式匹配在函数式编程中有着作用,在之后的函数式编程中也会进行介绍。
在下一篇中,我们来了解数组和列表,以及一些F#特有的类型。
相关文章推荐
- 黑马程序员——C语言基础语法--scanf函数、基本运算、流程控制
- C#笔记(2)---基本语法 [流程控制语句]
- C#笔记(2)---基本语法 [流程控制语句]
- C语言基础之基础语法、基本运算及流程控制
- Java基础语法(一)---数据、数值类型、运算符、程序流程控制语句和循环结构
- C#笔记(2)---基本语法 [流程控制语句]
- C#中控制流程
- C#流程控制
- [叩响C#之门]第4章 流程控制 4.1 算法的概念(以“人鬼过河”游戏为例)
- ActionScript流程控制语法详解
- C#中控制流程
- C#知识点之流程控制【1】
- java中支持Label语法,不过要配合流程控制语句使用(备忘)
- JavaScript语言基础-数据运算和流程控制
- python语法31[基本数据类型和流程控制]
- C#流程语句控制【3】
- C#学习2--流程控制
- [学习笔记]Asp.net(C#)菜鸟进级系列之流程控制
- 快速撑握C#知识点之流程控制
- C# 学习总结 之 流程控制