做者:Alexey Bykov@EastBancTech
原文:http://bit.ly/1nGroOz
翻译:kk1982.com
转载请注明git
F#是由微软研究团队为.NET平台研发的一种现代函数式语言。该语言自从2005年开始研发,到2013年12月份发布了3.1版本。F#最开始只是一个学术研究项目,通过若干年的发展,已经成为了一门成熟的语言,并被众多商业公司所使用,尤为在财务领域。程序员
之因此要研发一门与C#大为不一样的语言的缘由:github
从语言特性的角度来讲,F#是C#的超集,所以C#能作的事情F#也能作,但反之则非亦然,F#有不少事情C#作不了。算法
在F#与其余.NET语言之间有着完整的互通性。当F#被编译成程序集后,就能够被任何一种.NET语言使用,包括C#和VB.NET等。这也意味着F#的代码能够跟系统中以C#写成的部分和平共处。express
C#有项危险的特性就是容许使用NULL值替代对象,这个特性是一大批易于产生而难于检测的Bug的来源,为了不此类错误而在代码中处处增长的检查又下降了代码的可读性。编程
F#并不容许NULL值,取而代之的是使用option。与C#同样,option在表示缺失对象值上与NULL值意义相同,可是却能保证安全性。安全
C#对于代数数据类型(ADT)没有完整的支持,这种数据类型能够用简单的数据结构组成更为复杂的结构。C#所使用的类型是由类与结构构成的,对于Sum类型的支持极为有限,仅由枚举形式来体现。数据结构
相对的,F#对于ADT有着全面的支持,这使得其可以更为精准地以数据结构的角度去描述业务实体,减小误解数据含义的概率,从而提升代码质量。一般,F#能够经过不呈现的手段来避免不想要的状况,这样就没有可能去写出不合适的代码来。编程语言
C#鼓励更改数据以及使用状态机制,这表明着一旦对象被建立,就要在其生命周期内经历一系列的修改以改变其状态。依据对象当前状态的不一样,能够容许对其执行或者不容许执行部分操做。要想安全地使用该对象,必须先对其进行状态检查,以确保处于正确的状态下,若是不这样作,极可能就会产生不可预计的结果甚至于产生崩溃的Bug。模块化
而对于F#来讲,则鼓励使用变换而非可变体。变换并不会修改对象,所以也不会更改其状态。F#会建立一个新对象并将值传递过去,以保持原对象的完整。这也意味着一个对象会一直保持着其被建立时的状态。只跟一个单一的状态打交道能够极大地简化开发过程,并减小代码量,由于当咱们看到一个对象时,咱们知道它必定只处于一种可能的状态下,所以不须要作额外的检查就能够安全地使用它。
由于C#依赖于状态与变更,所以作变更的顺序就变得额外地重要,两条语句的位置互换均可能会产生Bug,所以在C#中语句的顺序是另一件须要考虑的事情。相反,一个F#程序本质上来讲就是一个由较小表达式拼成,且将输入值映射到部分输出值上的大表达式。表达式哪一部分先被计算并不重要,由于在一个无反作用的计算模型下,计算的顺序并不影响结果。所以从写语句转变到用表达式编程能够确保不会由于语句顺序错误而产生Bug。
C#经过在类与结构之下同时建立属性与方法的形式鼓励混合数据与逻辑,可是在进行序列化的时候,逻辑就须要被剔除,这也是为什么当须要序列化的时候,类的数据要被转移到没有逻辑的纯数据对象上。
函数编程语言建议你不要将数据和逻辑混合在一块儿,这样当序列化为JSON或者XML时就更为直观与容易。
C#的语法略啰嗦,对于同一件事情的表达,C#写的代码要比F#多得多。C#的啰嗦尤为表如今为方法的参数和返回值指定类型上。F#有一个高级类型推断系统,能够经过数值是怎样被使用的而推断出这些数值的类型,所以在大部分状况下推荐不要输入类型而让F#自行推断。录入的内容少了,生产力就提升了,代码也得到了更好的可维护性。一些人认为F#的语法更为优雅更易阅读。
C#中文件,类以及方法声明的顺序并不重要,而对于F#来讲,声明的顺序则严格取决于文件的顺序,所以你没法引用或使用还没有声明的东西。这看起来像是没必要要的设计,但实际上是一件好事儿,由于这能够强制程序员遵照规范。
现代的面向对象设计准则,被称之为SOLID,在C#中能够轻易地违反,因此才须要了解规范并严格地遵循。可是,基本一样的准则倒是函数式编程天生即有的。所以F#从一开始就以正确的方式编码,而写出不良的设计反而须要故意为之才行。
在C#中并行运行代码不是件容易的事情,由于存在竞态条件,会在两个线程试图同时修改同一个对象时产生。F#彻底消灭了这个问题,由于它不容许对象在建立后进行修改,当须要修改对象时,须要对原对象应用一个变换而建立一个新对象,这意味着在F#中不须要作太多事情就能够直接运行并行代码。
在F#中,逻辑的基础单位是函数,在C#中则是类。函数在F#中是“头等公民”,所以能够做为参数传递给其余函数或者做为函数的返回值。写一个函数比写一个类要省事儿,所以能够实现一个良好的模块化设计,以及以较低成本实现一个较为复杂的组合场景。用这种方式写出的代码更加易于维护而且易于重构。
F#鼓励使用泛型类型而非具体类型。为泛型类型所写的算法能够做用于具体的类型如数字,字符串以及复杂对象。用一个泛型的实现去替代多个不一样的类型可以使得代码复用性更高,出错的概率更小。
F#有一种特别的机制,用一种便捷统一的方式来处理异质数据源的数据,称做类型提供程序。类型提供程序抽象了不一样来源的数据的实现细节,确保类型安全,公开设计良好的标准接口。同时还具有类型按需发现功能,只有在须要时才会载入新的类型。在这里有一个代码库,存放着针对不一样数据源的数据提供程序,并由社群维护保持其持续更新。类型提供程序经过从不一样数据源获取数据的能力,为开发带来了信息丰富的编程。
F#有着两个标准工具:FsLex以及FsYacc,用于基于一个正式语法来生成解析器。这俩工具是根据Unix世界里的著名解析器生成工具Lex和Yacc来命名的。FsLex和FsYacc有着丰富的诊断能力,能够参与整个构建以简化开发过程。
如下缺点仅当从函数式编程所习惯的准则去使用F#时才存在,若是你选择不使用这些准则,那么这些缺点也就不存在了。
对于一个从未接触过函数式编程的人来讲,用一种全新的思考方式来进行F#编程极可能是一个挑战。
在使用变换而非变更的概念之下,须要使用更高级的数据结构才能更加有效率地操做数据。举个例子,在F#中你要使用二叉树而非C#中的哈希表。其余例子还有可能会大量使用拉链结构而非遍历器。
使用变换而非变更的概念会致使建立比实际须要多的对象,这些对象须要及时被销毁,所以与只更改状态的对象相比,垃圾回收器的负担要大得多。开发人员须要在这之中谨慎地寻找一个平衡。
F#不像C#那样容许对方法进行重载,因此在F#同一模块里的两个函数不能有同样的名字,这样就致使对函数进行惟一命名比较困难。制定一个统一的F#命名规范不是一件容易的事情。
微软在为C#程序员打造工具上花费了大力气,很不幸,F#就没有那么多工具可供使用,这使得编码就不是那么舒服。F#连基本的重构工具都没有。
举一个不错的例子,开发带界面的应用程序对于F#来讲就比较尴尬,由于操纵控件必需要更改其状态的,而这不是F#所擅长的事情。
F#是一个现代的函数式编程语言,被设计做为面向对象编程的C#及VB语言的备选。F#从后者中继承了优秀的特性,并抛除那些危险的特性。这是为何写F#代码更为安全而且易于维护。尽管部分项目类型不是F#的强项,可是对于那些进行密集数据计算的项目绝对应该是首选。F#对于业务问题的描述要比C#精准的多,使得其很适合做为服务端应用的候选。