由Dave Fancher编写的《The book of F#》一书对F#这门语言的各个方面进行了详细的论述,书中也涵盖了异步编程与并行编程等方面的内容。
在本书中,Fancher谈到了Visual Studio在F#这门语言中扮演的角色,并展示了可以使用在沙盒(Sandbox)与F#交互控制台中的各种脚本。接下来,他对F#中各方面的概念进行了完整的讲述,包括绑定、核心数据类型、枚举、流程控制、泛型、字符串格式化、注释的使用以及异常处理的各个步骤等等。
Fancher随后对一些相关概念进行了详细的阐述,包括类、结构、继承、接口、定制操作符、对象表达式、递归函数、lambda表达式、序列、数组、List、Set与map等等。
在本书第七章,你将通过一些代码片段学习模式表达式以及null匹配、元组、记录和集合相关方面的内容。此外还涵盖了部分主动模式与参数化主动模式等内容。
本书中另外还涵盖了其它一些方面的主题:
在全书结尾部分,Fancher也提供了一些高级主题的讲解,例如异步编程与并行编程,特别是任务并行库的应用。此外还专门用了一章的篇幅,通过几个简单的应用介绍了计算表达式的应用。
对于希望学习F#中各方面概念的开发者来说,《The Book of F#》会对他们提供许多帮助,同时也可以作为一本能够随时翻阅的参考书使用。
你可以在这里下载本书的一个免费的章节样例,也可以在No Starch Press出版社网站订购本书。
InfoQ有幸与Fancher进行了一次对话,谈论了关于F#与本书的更多内容。Fancher同时还是一位微软的MVP。
InfoQ:Dave,这本书为读者展示了一个关于逆波兰表示法(Reverse Polish Notation——RPN)计算器的应用作为示例,而不是常见的Hello World程序。为什么你会选择它作为示例呢?
传统的Hello World示例是一种让读者迅速获得满足感的简单方式。我承认,对于新入行的程序员来说,能够让计算机完成他们的命令确实能够体验到某些成就感,但《The Book of F#》这本书并不是为新入行的程序员所准备的,它所针对的读者是富有经验的程序员,只是他们希望进入函数式编程的世界。考虑到这一点,一个普通的Hello World无法为读者展示这门语言的任何实用性。因此我做了一些调整,为读者首先展示了逆波兰表示法计算器,它能够用简短的代码为读者展现一系列F#的特性,包括作为一等对象的函数、闭包、模式匹配、绑定以及模块函数。
InfoQ:在本书第三章的核心数据类型这一部分,你谈到了类型缩写和类型推断。这两个术语是否什么不同之处呢?
是的,它们确实有所不同。类型缩写是已知类型的一种别名。比方说,string是System.String的缩写,而int则是System.Int32的缩写。而类型推断是指编译器能够判断出某个给定值的正确类型。F#编译器能够准备地推断出某个绑定或参数的正确类型,但在有些情况下还需要给它提供一些帮助。在这种情况下,我们需要使用类型注解(annotation),其中包含了显式的类型名称或者是类型缩写。
InfoQ:泛型在F#中扮演了怎样的角色呢?
泛型是F#的类型系统中一个重要的组成部分。它们在F#中所扮演的角色与它们在传统的.NET语言中所起的作用大体上相近,但F#与传统.NET语言的一个关键差别在于,它的类型推断系统会尝试自动对参数进行泛型化。 这意味着如果编译器认为某个函数并不假设它的参数是某种具体的类型,那么编译器就会自动将这个函数转为泛型。编译器还能够检测出这些泛型类型参数所必须的某些限制条件,这样就在保证了类型安全的同时,也使得代码更为健壮。这一特性使我们免于定义大量的方法重载,而且往往在进行重构之前是很难一上来就想到这种使用代码的方式的。
InfoQ:与C#相比,F#的优势体现在哪些方面?是否在某些特定场合下你会偏向于使用其中一种语言呢?
从高层次角度来说,F#相较于C#的优势在于它简洁的语法、强大的类型推断以及它对函数式编程的强调。如果要讲到特定的语言特性,那么例如调制函数(curried function)、记录类型、可区分联合、模式匹配、集成的度量单位以及对象表达式等特性是使我难以割舍F#而选择C#的重要因素。我的观点或许有些老套,但我还是认为在建立一个新的应用程序的前提下,只有在一种情况下我会优先选择C#而不是F#,那就是该应用程序需要使用到某些框架(例如ASP.NET MVC),而这些框架在Visual Studio工具中尚不支持F#。即使如此,要使用这些框架也不是没有可能的,只是需要将各种组件手动进行连接,而在C#项目中,Visual Studio往往已为你做好了这一切。
InfoQ:F#与Haskell非常密切相关,你认为它们的不同之处有哪些呢?
我对Haskell的熟悉程度或许还不足以让我完整地回答这个问题,不过,这两者之间一个众所周知的不同之处在于:Haskell是一门纯粹的函数式语言,而F#则不那么纯粹。这一区别意味着Haskell不允许函数中产生副作用(除了在受控的场景下之外),而F#则允许带副作用的函数。
InfoQ:在本书第九章,你谈到了.NET反射机制。你认为它在F#应用程序的开发中扮演了什么样的角色呢?
我在第九章提到.NET反射,是为了讲解如何为不受读者控制的外部代码生成引用的表达式。反射在F#中的所扮演的角色和在传统.NET语言中是一致的。
InfoQ:你能为我们分享一下异步编程模型(APM)的作用和它的优势吗?
正如我在第十一章的开头部分所写的,人们长期以来一直倾向于使用异步编程模型在.NET中进行异步编程的,而F#提供了一些其它选择,例如异步工作流和基于代理(Agent)的编程方式。这些方式对线程创建、同步以及回调函数的细节进行了抽象,因而能够提高异步编程的可访问性和可维护性
InfoQ:任务并行库中的主要特性是什么?
虽然任务并行库本身并不属于F#的特性,但它通过充分利用了可用的计算机资源,提高了CPU密集型操作的伸缩性。它的一些关键特性包括:基于任务(相对于基于线程)、简易的取消操作以及简易的延续任务处理。
InfoQ:你能为我们分享一下F#是怎样从异步工作流中受益的吗?
在某些方面上,异步工作流更适用于I/O密集型操作,而任务并行库则更适用于CPU密集型操作。异步工作流能够简化对某些代价高昂的操作的处理方式,例如文件操作和发起网络请求,而不会阻塞UI线程(或者其它父线程)。与更传统的方式相比,异步工作流的独特之处在于它使用了一些常见的关键字对异步操作以及延续任务进行了隐式的处理。此外,异步工作流使用了与并行任务库相同的取消操作机制,因此不需要编写很多代码就能够很方便地取消异步操作。
InfoQ:在F#中使用计算表达式的主要优势有哪些呢?
计算表达式在F#的开发中占据重要的地位,包括序列表达式、查询表达式与异步工作流等诸多方面。从本质上来说,计算表达式就是builder类的语法糖。计算表达式在编译期进行语法解析,每个嵌套表达式都会被转化为对builder类的相应的方法调用。这种编程模型使得开发者能够定义自己的builder类,并通过相应的计算表达式转化为一系列语法元素,因此在F#中能够以一种自然的方式表达复杂的操作。
InfoQ:除了本书之外,你还有哪些关于学习F#的推荐参考资料吗?
在F#已经有许多优秀的学习资料了。我特别为大家推荐以下一些资源:
- F# Software Foundation
- F# for Fun and Profit
- Try F#
- F# Language Reference
Dave Fancher在.NET Framework上已经有超过10年的软件开发经验。他是印第安纳开发者社区的常客,经常在全美举办的活动中充当演讲者和用户讨论组中的参与者角色。在2013年7月,Dave获得了Visual F#方面的微软MVP(Most Valuable Professional)。除了编写代码,以及在davefancher.com撰写关于代码方面的文章之外,他还非常喜爱看电影,或是打Xbox One游戏。
查看英文原文:The Book of F# - Review and Interview with Dave Fancher