简单介绍

F#(与C#一样,念作“F Sharp”)是一种基于.Net框架的强类型、静态类型的函数式编程语言。
可以说C#是一门包含函数式编程的面向对象编程语言,而F#是一门包含面向对象的函数式编程语言。
可以查看官方文档了解更多信息。

本系列文章假设你在了解C#的情况下,将F#与C#在异同点上进行说明,让读者能快速地对F#有个系统的了解。
才疏学浅,错漏难免,如果您在阅读过程中有什么建议或意见,还请不吝指教。

函数式编程这几年一直不温不火,但相信了解了F#之后,对C#也会有更深的认识,对学习其他函数式语言也会更容易上手。

Hello, World

在使用F#时,可以像C#一样创建一个控制台项目进行测试。
但因为F#支持以脚本形式运行,所以直接打开F# Interactive(以下简称fsi)进行交互是最方便的。

在Visual Studio中可在“视图-其他窗口”中打开。以前没有csi的时候,一直拿fsi来测试C#代码,在VS2015中终于添加了csi。
如果不想打开臃肿的VS,可在Microsoft SDK的安装位置找到fsi。以下是我安装的F# 4.0的fsi的位置:

"C:\Program Files (x86)\Microsoft SDKs\F#\4.0\Framework\v4.0\Fsi.exe"

介绍任何语言的特有方式就是通过那几乎成为标准的“Hello, World”程序。
F# 输出可使用 printf 函数,如下:

printf "Hello, world!"

当然,也可以像C#一样使用 .Net 的控制台输出函数:

System.Console.Write("Hello World")

当把以上代码敲进fsi里按回车后,会发现并没反应,是因为在fsi里提交代码必须以;;双分号结尾。
请输入 printf "Hello, world!";; 和 System.Console.Write("Hello World");; 或者在换行后输入;;再次回车。
如图:

F#基础类型

下面,我们尝试把以下简单的C#代码转换成F#代码:

int sum = 0;
for (int i = 0; i<=100; i++)
{     if (i%2 != 0)           sum += i;
}
Console.WriteLine("0到100中的奇数的和为{0}", sum);

这段命令式代码只是简单地把0到100中的奇数相加,并把和输出。
虽然在C#中也支持函数式,但在这里我们为了了解基本语法,使用简单语句来介绍。

以下是F#版本的代码:

let mutable sum = 0
for i = 0 to 100 doif i%2 <> 0 then sum <- sum + i printfn "0到100中的奇数的和为%A" sum ;;

以上代码在fsi里的运行结果为:

0到100中的奇数的和为2500
val mutable sum : int = 2500
val it : unit = ()

可以看出,F#中每行代码结尾的;是可选的。

因为函数式编程语言的特点之一便是无副作用(No Side Effect)、不可变(Immutable),所以没有变量(Variable)的概念,只有值(Value)的概念。
所以在上面的运行结果中,都是以val开头;而值it默认为最后一次运行结果,在此例中其类型为unit,相当于C#中的void,即无返回值。

但是在很多场景下,Mutable(可变)可以带来很多便利,尤其是在像上面结合命令式编程的场景中。
在上面的代码中,val mutable sum即为一个可变的值。

基础类型

下面将C#和F#的数据类型定义作对比:

数据类型 C# F#
Int int i = 0; let i = 0 
let i = 0l
Uint uint i = 1U; let i = 1u 
let i = 1ul
Decimal decimal d = 1m; let d = 1m 
let d = 1M
Short short c = 2; let c = 2s
Long long l = 5L; let l = 5L
unsigned short ushort c = 6; let c = 6us
unsigned long ulong d = 7UL; let d = 7UL
byte byte by = 86; let by = 86y 
let by = 0b00000101y 
let by = ‘a’B
unsigned byte sbyte sby = 86; let sby = 86uy 
let sby = 0b00000101uy
bool bool b = true; let b = true
double double d = 0.2;
double d = 0.2d 
double d = 2e-1 
double d = 2 
double d0 = 0
let d = 0.2 
let d = 2e-1 
let d = 2. 
let d0 = 0x0000000000000000LF
float float f = 0.3;
foat f = 0.3f;
float f = 2;
float f0 = 0.0f;
let f = 0.3f 
let f = 0.3F
let f = 2.f 
let f0 = 0x0000000000000000lf
native int IntPtr n = new IntPtr(4); let n = 4n
unsigned native int UIntPtr n = new UIntPtr(4); let n = 4un
char char c = ‘c’; let c = ‘a’
string string str = “abc\n”;
string str = @"c:\filename";
let str = “abc\n” 
let str = @"c:\filename"
big int BigInteger i = new BigInteger(9); let i = 9I

F#的字面量详细介绍可查看MSDN文章。

十六进制、八进制和二进制

我们知道,在C#中,可以用0x前缀定义十六进制数值。
而F#中除了十六进制(0x,还可以直接定义八进制(0o)和二进制(0b的数值。

let hex = 0xFABClet oct = 0o7771Llet bin = 0b00101010y;;

输出结果为:

val hex : int = 64188
val oct : int64 = 4089L
val bin : sbyte = 42y

浮点数

需要注意的是,在F#里,doublefloat都代表双精度浮点数,单精度浮点数称为float32
String还有一个字面量表示方法是三个双引号:

let str = """<book title="Paradise Lost">    <content /> </book>"""

在使用@为前缀(称为Verbatim String)时,字符串内的若出现双引号必须使用两个双引号转义,使用三个双引号的表示法避免了这个问题。
这种表示法最常用在把XML文档编码到代码文件里。

字节数组

在类型对比表中,byte行可以看到有一个创建字节数组的语法:

let asciiBytes = "abc"B  // val asciiBytes : byte [] = [|97uy; 98uy; 99uy|]

其等价的C#代码是:

byte[] asciiBytes = Encoding.ASCII.GetBytes("abc");

当然,只支持ASCII编码。

变量名

F#的变量名命名规则与C#基本一致,但也可在变量名中包含单引号':

let x = 10let x' = 11let Tom's = "2010"

通过let关键字,将10绑定(赋值)到x,将11绑定到x'

在C#中,若要将关键字或保留字作为变量名,则可以变量名前加@实现:
例如使用代码

class @class {}

定义一个名为class的类。

但是在F#中,只需在前后加上``即可将任意字符串指定为变量名:

let ``let`` = 4let ``I love F#`` = "This is an F# program."(*在fsi的输出结果为:val let : int = 4val ( I love F# ) : string = "This is an F# program."*)

注意在F#中,单行注释和C#一样使用//,但多行注释使用(* *)

F#的运算符与C#类似,部分区别将在下一篇介绍。感兴趣的可以在fsi里尝试输入运算玩一玩,或许就可以发现区别了。

原文地址:http://www.cnblogs.com/hjklin/p/fs-for-cs-dev-1.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

如果你也会C#,那不妨了解下F#(1):F# 数据类型相关推荐

  1. 如果你也会C#,那不妨了解下F#(6):面向对象编程之“类”

    前言 面向对象的思想已经非常成熟,而使用C#的程序员对面向对象也是非常熟悉,所以我就不对面向对象进行介绍了,在这篇文章中将只会介绍面向对象在F#中的使用. F#是支持面向对象的函数式编程语言,所以你用 ...

  2. 如果你也会C#,那不妨了解下F#(5):模块、与C#互相调用

    F# 项目 在之前的几篇文章介绍的代码都在交互窗口(fsi.exe)里运行,但平常开发的软件程序可能含有大类类型和函数定义,代码不可能都在一个文件里.下面我们来看VS里提供的F#项目模板. F#项目模 ...

  3. 如果你也会C#,那不妨了解下F#(4):了解函数及常用函数

    函数式编程其实就是按照数学上的函数运算思想来实现计算机上的运算.虽然我们不需要深入了解数学函数的知识,但应该清楚函数式编程的基础是来自于数学. 例如数学函数f(x) = x^2+x,并没有指定返回值的 ...

  4. Jove:@houyr 那你也可以用totalcmd发。下个curl.然后配有个tc的命令。。。。。

    Jove:@ houyr 那你也可以用totalcmd发.下个curl.然后配有个tc的命令.....

  5. numpy 下的数据结构与数据类型的转换(np.array vs. np.asarray)

    numpy 下的数据结构与数据类型的转换(np.array vs. np.asarray) 原创  2017年02月18日 10:35:43

  6. Linux下通过rm -f删除大量文件时提示-bash: /bin/rm: Argument list too long的解决方法...

    Linux下通过rm -f删除/var/spool/postfix/maildrop/中大量的小文件时提示: "-bash: /bin/rm: Argument list too long& ...

  7. 在X32与X64下,每种数据类型占用的字节数

    在X32与X64下,每种数据类型占用的字节数分别如下: X32                             X64 指针                                  ...

  8. windows下的tail -f 命令

    大家都知道,在linux下的 tail -f 命令,可以动态查看文件的变化. 今天在windows下也找到了这个办法. 附件的文件解压缩放到system32下即可. 启动DOS,输入 tail -f ...

  9. Word2013默认情况下按Ctrl+F到导航框问题处理

    Word2013默认情况下按Ctrl+F会到导航框: 而不是像之前Word2003.Word2007等版本一样弹出"查找"窗口: 要实现按Ctrl+F就直接弹出"查找&q ...

最新文章

  1. 时间复杂度和空间复杂度3 - 数据结构和算法05
  2. 如何增加SAP_ALL的权限
  3. [html] 你知道著名的3像素Bug指的是什么吗?怎么解决呢?
  4. [vue] vue边界情况有哪些?
  5. mysql性能调优精简版
  6. 小时候都想当科学家后来只有他做到了——对话阿里云MVP朱祺
  7. Array 的方法们 和 object 那些让人纠结的问题 ......
  8. linux机器的物理内存监控,Linux内存监控工具
  9. Rsync结合Inotify 实时同步配置
  10. 医学统计学计算机操作教程第3版附录答案,医学统计学课后习题集答案解析.doc...
  11. 根据IP获取国家地区
  12. 对话阿里云弹性计算负责人褚霸:把计算做到极致,关键还加量不加价!
  13. U3D资源导出至Laya
  14. 软件测试就是点点点?你想的太简单了......
  15. mysql where not in_mysql查询条件not in 和 in的区别及原因说明
  16. python遍历列表易出错!!!!!
  17. java与seo_java实现seo优化 提高运行效率
  18. Java 基础--封装
  19. Xcode Server 教程1:入门
  20. 安卓逆向学习——多开原理和实验

热门文章

  1. sql server2008中怎样用sql语句创建数据库和数据表
  2. UILabel自适应高度和自动换行
  3. [有奖励]GeneralUpdate开源项目招募开发者
  4. .NetCore跨域
  5. 跟我一起学.NetCore之Swagger让前后端不再烦恼及界面自定义
  6. .Net5发布在即,当心技术断层!
  7. 在.NET Core中使用MongoDB明细教程(3):Skip, Sort, Limit, Projections
  8. .NET 异步详解(更新)
  9. Kubernetes引发“军备赛”,K8s真是企业生存的关键吗
  10. .NET Core开发实战(第17课:为选项数据添加验证:避免错误配置的应用接收用户流量)--学习笔记...