1月24日,F# 4.6 预览版正式公布,与以往一样,新版本的设计与开发过程是整个 F# 开源社区共同努力的结果,这次更新的具体讨论内容可以通过下面两个链接来查看:

这次更新的主要内容有:

  1. 匿名记录类型(Anonymous Records)
  2. ValueOption 模块
  3. ListArraySeq 新增的 tryExactlyOne

匿名记录类型(Anonymous Records)

快速上手

F# 新增了匿名记录类型,举个例子:

// {| ... |} 用来声明一个匿名的记录
let data = {| X = 1; Y = "abc" |}
// val data : {| X : int; Y : string |} let result = data.X + data.Y.Length // 匿名记录同样可以使用 with 关键字复制并更新
let newData = {| data with Z = data.X + 5 |} // 匿名记录还可以作为函数的参数使用
let someFunc (d: {| X : int; Y: string |}) =
printfn "X: %d; Y: %s" d.X d.Y

为什么我们需要这个新特性

  1. F# 中声明一个记录类型真的很繁琐,尤其是我们只需要一次性的引用一个记录类型的时候
  2. C# 3.0 引入的匿名对象在 F# 中找不到对应的概念,这在把 C# 代码转换为 F# 代码的时候带来很大的痛苦
  3. C# 7.0 为元组类型添加了命名字段,而当前的 F# 会忽略掉这部分的信息

匿名记录的类型

为了保证程序集中拥有相同结构的匿名记录类型的一致性,编译器会使用 SHA1 算法根据匿名记录的字段名列表(排序后)为匿名记录生成唯一的类型标识。

  • {| X : int |}{| Y : int |} 会被生成为两个不同的类型
  • {| X : int; Y : int |} 与 {| Y : int; X : int |} 是同一个类型
  • 匿名记录可以使用 struct 关键字修饰,这样生成出来的就是结构体类型的记录了

与 Record 的不同

拷贝更新

匿名记录的拷贝更新功能非常的灵活,这是因为匿名记录的拷贝更新并不要求原始类型与结果类型一致,所以下面的代码都是成立的:


type RefRecord = { X : int; }
let refRecord = { X = 1 } // 结果类型不必与原始类型相同
let dataA = {| refRecord with Y = "string" |} // 结果为 {| X = 1; Y = "string" |}
let dataB = {| dataA with Y = 23333 |} // 结果为 {| X = 1; Y = 23333 |} // 甚至还可以从引用类型中拷贝数据到结构体中,反过来也是可以的
let dataC = struct {| dataB with Z = true |} // 结果为 {| X = 1; Y = 23333; Z = true |}

不过在现阶段,我们还是无法通过拷贝更新的方法用匿名记录来创建 Record。

模式匹配

由于匿名记录的特点,现阶段还无法对匿名记录使用模式匹配解构,这是因为当我们把匿名记录中的某些字段在模式匹配中忽略掉的时候,可能会产生新的类型,如上面所说的,匿名记录的类型标识是由其全部的字段决定的。

其他的一些限制

  1. 无法使用 CLIMutable 特性修饰,这也意味着匿名记录是不可变的
  2. 匿名记录无法定义类成员(包括成员字段、属性、方法等),这是因为记录仅仅只是用来保存数据的,

ValueOption 模块

FSharp.Core 4.6.0 中带来了 ValueOption 模块,为 FSharp.Core 4.5.0 中引入的 ValueOption 类型带来了大量的实用函数,详情请见 RFC 说明页面

ListArraySeq 新增的 tryExactlyOne

这个函数类似于 LINQ 中的 SingleOrDefault(),不过它并不会抛出异常,而是以一个温和的 Option 类型作为返回值:

List.tryExactlyOne []
// None
List.tryExactlyOne [1]
// Some 1
List.tryExactlyOne [1; 2]
// None Array.tryExactlyOne null
// ArgumentNullException
Array.tryExactlyOne [||]
// None
Array.tryExactlyOne [|1|]
// Some 1
Array.tryExactlyOne [|1; 2|]
// None Seq.tryExactlyOne null
// ArgumentNullException
Seq.tryExactlyOne (Seq.ofList [])
// None
Seq.tryExactlyOne (Seq.ofList [1])
// Some 1
Seq.tryExactlyOne (Seq.ofList [1; 2])
// None

最后

尽管 F# 4.6 只是一个小小的功能特性更新,但是匿名记录出现给 F# 开发带来了新的活力,除了能够减少代码量之外,匿名记录也让 F# 开发者能够更加轻松的使用以 C# 为主导的 .NET 生态。

以上就是 F# 4.6 的更新简介,更加详细的介绍可以查看微软博客的公告以及相关的 RFC 记录。


同步发表于个人博客: F# 4.6 预览版正式公布

最新文章

  1. 将做好的py文件打包成模块,供别人安装调用
  2. Number of 1 Bits(Difficulty: Easy)
  3. Javascript之UI线程与性能优化
  4. 【转】Android Gson的使用
  5. ural 1864
  6. hbuider 中点击就显示出一个单选的列表 ,然后后台跨域向里面动态添加数据,注意里面的格式是json object
  7. 网易云课堂_C语言程序设计进阶_第5周:链表
  8. NOIP2002-普及组复赛-第二题-级数求和
  9. 【BZOJ3529】数表(莫比乌斯反演,树状数组)
  10. P2500 - 【DP合集】背包 bound
  11. 1013团队Beta冲刺day2
  12. python3.* socket例子
  13. 老男孩python学习之作业一购物小程序
  14. 2018-2019-2 网络对抗技术 20165206 Exp3 免杀原理与实践
  15. Python学习笔记【第八篇】:Python内置模块
  16. Orchard详解--第三篇 依赖注入之基础设施
  17. editplus tag
  18. metasploit学习之情报搜集
  19. SGU 140. Integer Sequences 线性同余,数论 难度:2
  20. Django 发送html邮件

热门文章

  1. Linux SSH 连接安全设置
  2. $.extend(obj1,obj2...,objN)小结 扩展obj1属性,有返回值,返回第一个被扩展后的对象
  3. vue.js不仅是一种模式,也是一种工程组织方式
  4. 第3章 Spring AOP
  5. 牛客挑战赛32 E. 树上逆序对
  6. 恕我直言,在座的各位根本不会写 Java!
  7. 015_matlab运行C语言
  8. Redis 迁移 DB; move key db
  9. Linux OOM一二三
  10. pwd函数实现