微信号:infoqchina

介绍:有内容的技术社区媒体

你分析过“F#4.0”的社区基因吗?

2015-05-13 11:28 邵思华 译



尽管近期所有的新闻都在关注C#和Windows 10,但F#也没有坐以待毙。随着Visual Studio 2015 RC的面世,F# 4.0也一同浮出水面。

首先要注意的第一点就是,这是一个由社区的努力所推出的项目。在全部38位贡献者中,只有4分之1的人与微软有所关联。所有的工作都是在F#的GitHub网站上公开完成的,他们也希望能够通过这个平台获得用户的反馈。


这个新的发布版本对语言本身和运行时都带来了大量的变更,也对IDE进行了一些改进。你可以在F#博客上找到完整的变更列表,我们在这里将着重分析几个重点特性。


元编程的支持



自从.NET 4.0中引入了LINQ之后(译注:此处原文有误,LINQ首次是在.NET 3.5中出现的),通过表达式树在.NET中实现元编程就成为了一种非常重要的特性。而在F# 4.0中,编写表达式树变得前所未有的简单。


如果你为某个类型为FSharp.Quotations.Expr的参数加上ReflectedDefinition这个属性,那么调用方会自动地切换到按名称调用的方式。在之前的版本中,你必须按照下面的代码中的前两个表达式的方式对调用方进行标注,而现在只需按照第3个表达式那样写就可以了:


Test.Expression1 ( <@ x + 1 @> ) //typed expression Test.Expression2 ( <@@ x + 1 @@> ) //untyped expression Test.Expression3 ( x + 1 ) //typed expression with ReflectedDefinition attribute


消除了明确地对表达式进行引用的负担之后,那些应用了元编程技术的类库就变得容易使用多了。


改进的预处理指令



不管你相信与否,直至目前为止,F#对预处理器指令的支持少得可怜。类似于“#ifTRACE || DEBUG”这样的布尔操作直到这个版本才刚刚实现。对于F# 3以及更早的版本来说,一种临时方案是使用嵌套的#if语句以模拟“and”表达式,并用重复性的代码模拟“or”表达式。


度量单位



在进行科学应用或工程应用时,经常会因为单位的差错而导致错误。举例来说,你可能会混淆英制单位和公制单位这两种不同的度量值。在1999年,正是因为这个错误导致了造价达1亿2千5百万美元的航天探测器 —— 火星气候探测器(Mars Orbiter)的毁灭。


F#通过某种被称为度量单位的概念消除了这种类型的bug的产生。将某个标量数值加上“<cm>”“<miles/hour>”这样的前缀,就可以将其转换为单位度量。正如下面一行代码所示,在单位之间进行的每种转换都是由度量单位所表达的。

let cmPerInch : float<cm/inch> = 2.54<cm/inch>


F# 4中的新功能之一是能够在度量单位表达式中使用分数指数。

举例如下:

[<Measure>] type Jones = cm Hz^(1/2) / W


从具有多个泛型接口的类型继承



如果你不熟悉F#的话,要理解这一点有些困难,而如果你熟悉F#,你就知道这一点多么令人头疼了。在开始之前,首先想象一个表示16进制数字的类。在C#中,你在设计这个类时或许会决定让它能够与字符串和整数进行比较。



public class Hexidecimal : IComparable<string>, IComparable<int>


由于F#中类型推断的复杂性,在之前的版本中无法表达这个类。一方面,你无法定义一个具有多个接口,并且这些接口的唯一区别只在于它们的类型参数的这种类型。另一方面,你也不能够继承这样的类型。


F# 4也没有完全解决这个问题,但它提供了某种临时方案。你现在要创建两个类,让每个类实现一个接口,并让第二个类继承于第一个类。这种代码有些繁琐,但如果你正好使用了某个基于C#编写的类库,那么在某些情况下必须使用这种方法。


在对象初始化器中使用扩展属性


扩展属性这一特性是C#使用者非常渴望得到的特性,而F#已经具备这一特性了。在这个最新版本中,能够在对象的初始化器中使用扩展属性了。


去除了微软的品牌标志

F#这门语言的专属命名空间总是以“Microsoft.FSharp”开头的,这种传统从Visual Basic 7就开始了。但随着F#逐渐从微软自有变成由社区驱动的项目,这种方式也显得不那么恰当了,而它身上的微软标记也在逐渐地淡化。


在这种情况下,为了保持F#代码不依赖于任何提供商与平台,在引用FSharp.Core运行时的命名空间、模块和类型的时候,可以选择忽略“Microsoft.”这一命名空间前缀。


性能改进:非结构化的比较


在默认的情况下,F#使用的是结构化的比较方式,而不是类型内置的操作符,例如op_Equality等。这种方式虽然能够简化复杂数据的比较,但也对性能造成了损害。


如果你希望选择注重内置比较操作符的性能或是语义,现在你可以使用“打开NonStructuralComparison”这一操作改变例如=等操作符的工作方式了。在对某个循环中的DateTime对象的比较进行的基础测试中,其结果显示性能提高了一个数量级。


调试


在VS 2015之前,F#开发者只能选择使用F#的互动模式,或是选择完整地访问调试器。有了新版本中的脚本调试特性,你可以右键单击某段F#脚本,并在调试器中运行它,这种方式结合了两种模式的优点。



智能地进行重编译



在VS 2013和之前的版本中,Visual Studio无法检测出某个F#项目是否需要进行编译。因此,即使某个F#中没有任何变化,也必须进行重新编译。而在VS 2015中能够检测到某个F#项目是否保持最新,因此开发者无需等待项目进行无意义的编译了。


其它的新特性还包括改进的智能提示、针对Option<T>的互操作API、对于WebClient的异步工作流扩展等等。



回复关键词查看对应内容:

React | 架构师 | 运维 | 云 | 开源 | Kubernetes | 架构 | 人工智能 | Kafka | Docker | Netty | CoreOS | QCon | Github | Swift | 敏捷 | 语言 | 程序员 | 实践 | 物联网 |





 
InfoQ 更多文章 Facebook如何实现PB级别数据库自动化备份 学术派Google软件工程师Matt Welsh谈移动开发趋势 Spotify为什么要使用一些“无聊”的技术? 妹纸们放假了,汉纸们做啥? 大多数重构可以避免
猜您喜欢 微软宣布.NET开发环境将开源 支持Mac OS X和Linux 让金融IT变得简单 ✎_人穷的时候,要少在家里 五个维度看清太后版芈月的领导力(微剧透) 勘误