博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Dart中可空性语法的定案: a?[b] 或 a?.[b]
阅读量:2356 次
发布时间:2019-05-10

本文共 3696 字,大约阅读时间需要 12 分钟。

简述:

这是一篇译文,来自于Dartlang官方在Medium上的一篇文章,文章中说到Dart正在重新设计它的类型系统,并且即将要加入可空类型和非空类型(这一点和Kotlin语言是极其的相似,正因为这种可空和非空的类型系统的严格划分,才能让Kotlin很好地避免NPE的问题)。为什么要翻译一篇这样的文章,算为我们下一篇语法篇Dart类型系统和泛型做一个铺垫。因为当你进入Dart类型系统,你会发现它实际上是一个不严格的类型系统,比如泛型型变安全方面。

翻译说明:

原标题: Dart nullability syntax decision: a?[b] or a?.[b]

原文地址: medium.com/dartlang/da…

原文作者: Kathy Walrath

Dart正在重新设计其类型系统,以便于各个类型都存在可空(该类型的表达式可以有null值)或者非空两种类型。今年晚些时候,我们将告诉您具体的发布时间和流程。但是Dart默认情况下都将不可为null, 并且当你需要为null的时候,必须使用特殊的语法来说明当前类型允许使用null值。

例如,当你要声明一个整型可以为null,则需要在声明的类型后面加一个?

 
int? someInt; // someInt变量可以为null

如果你看过Kotlin、Swift或C#代码,可能对问号?语法并不陌生。但是也存在一些不同的地方---特别是经常用来访问集合和数组中的下标([])运算符。C#和Swift都是使用?[],而目前Dart(以及ECMAScript)的计划是使用?.[]语法。

e1?.[e2] //如果e1为null,就返回null; 否则就返回e1[e2]的值

这篇文章主要说明做这个定案背后的原因,并鼓励你能有一些自己的想法和建议。这些内容大部分都是基于Bob Nystrom对issue #376的评论,该评论总结了Bob和NNBD规范负责人LeafPetersen之间的讨论。

为什么使用圆点语法方式?

e1?[e2]与e1?.[e2]两种方式都有各自的优点。	e1?[e2]:
  • 与C#、Swift保持一致

  • 更简洁

  • 类似于!运算符(即使它是可空类型,也可以使用它在表达式后面添加,表示它的值不为null)的语法: e1![e2]

e1.[e2]:	类似于级联语法:e1..[e2] //级联语法	e1?..[e2] // 可空检查的级联语法
  • 与其他可空检查方法语法相似: e1?.e2()

  • 可以很自然地扩展到其他运算法

  • 可以避免以下代码中的歧义: { e1 ? [e2] : e3 }

我们花了一段时间尝试找到避免?[]歧义的方法。问题在于你无法判断这这段代码{e1 ? [e2] : e3}是否是一个包含条件表达式结果的set集合,或者是一个包含可空检查下标key的map集合。

如果我们通过添加括号方式来消除歧义,可以选择在整个表达式周围添加--{ (e1 ? [e2] : e3) }--可以明确地把它当做一个set集合。或者我们可以将括号包裹第一部分的周围--{ (e1?[e2]) : e3) }--可以明确把它当做一个map集合。但是在没有括号的情况下,解析器就不知道该怎么做了。

对于这种歧义有多种解决方案,但是似乎没有一个令人满意的解决方案。一种方法是依靠空格来区分选项。在这种方法中,因为这个空格在?[之间,所以你总是会把e1 ? [e2]作为条件表达式的前半部分。而且你总是将e1?[e2]作为可空检查的下标,因为这两个标记之间没有空格。但是依赖空格确实对开发者体验不好。

从理论上来说,在格式化代码中,依靠空格不是问题。但是很多用户将未格式化的Dart代码编写作为格式化程序的输入。因此,在该语言的每个地方,这样输入格式将变得对空格更加敏感且脆弱。到目前为止,在Dart中这类情况很少见,这是一个不错的语法特性。(比如- - a--a都是有效的但却有着不同的含义

忽略歧义问题,使用圆点语法还有另一个原因: 如果我们为其他运算符(例如e1?.+(e2)等)添加可检测空值的形式,则可能需要使用点号。

我们为NNBD讨论的另一项功能是可检查null的调用语法。如果我们在此处不需要点,则它也存在相同的歧义问题:

 
var wat = { e1?(e2):e3 }; // Map or set?

无论我们为?[这种形式给出什么解决方案,它都必须同样适用于?(这种形式。最后,考虑链式调用下标的示例:

 
 

在我们看来,这看起来不太好。它看上去不像是方法链,而更像是中缀运算符的某种组合-有点像??运算符。将其与以下代码进行比较:

someJson?.[recipes]?.[2]?.[ingredients]?.[pepper]

在这里,它显然是一个方法调用链。视觉上看起来也很明显,因为用户需要快速了解有多少表达式会出现空短路。

总结这么多,似乎看起来我们应该使用?.[下面列举一些原因:

  • 它能避免歧义的问题。(词法分析器已经将?.作为单个"空检查"令牌)

  • 它能自然地扩展到可检查空值的调用。

  • 它能扩展到其他了解空值的运算符。

  • 它让Dart为格式化程序提供了更强大的输入语言。

  • 它在方法链中调用看起来符合习惯。

  • 它从视觉上就能看出可以使多少个方法链短路。

你怎么看?

我们一直对反馈和建议很重视,对于这种语法给出反馈最好方式就是对语言issue #376发表评论(或者给一些评论点赞)。那么在使用的时候,请可以考虑查看我们正在使用其他不错的语言特性。

您可以在这里找到更多信息:

NNBD:

  • 语法说明

  • 路线图

  • 问题

Dart语言的其他变更和特性:

  • 语言的变更

  • 语言演变过程

  • Dart语言说明

640?wx_fmt=other

译者有话说

其实这篇文章主要就是讨论一下,关于在Dart语言中对于数组或集合下标可空语法的表达是应该用a?[b]还是使用a?.[b]. 然后作者给出一些为什么会使用a?.[b]的原因。通过这篇文章,我们应该还得到一个信息就是Dart正在重构它的整个类型系统,它会像Kotlin那样把类型系统分为可空类型和非空类型,从而实现使得整个类型系统更加完备和严谨。

Dart可空和非空类型已经处于实验阶段,但是在Dart2.x源码中已经在开始使用了。

比如dart中的ListQueue的源码

//
class ListQueue
extends ListIterable
implements Queue
{ static const int _INITIAL_CAPACITY = 8; List
_table;//声明List
集合,泛型类型参数E为可空类型 int _head; int _tail; int _modificationCount = 0; /// Create an empty queue. /// /// If [initialCapacity] is given, prepare the queue for at least that many /// elements. ListQueue([int? initialCapacity])//声明可空类型的int : _head = 0, _tail = 0, _table = List
(_calculateCapacity(initialCapacity)); static int _calculateCapacity(int? initialCapacity) { //对可空类型initialCapacity做空检查 if (initialCapacity == null || initialCapacity < _INITIAL_CAPACITY) { return _INITIAL_CAPACITY; } else if (!_isPowerOf2(initialCapacity)) { return _nextPowerOf2(initialCapacity); } assert(_isPowerOf2(initialCapacity)); return initialCapacity; } ... }

但是需要注意的是目前还没有直接开放给开发者,还处于experiment阶段。

640?wx_fmt=other

所以,相信很快Dart中的可空和非空类型将会转正正式使用,到那时候学过Kotlin、Swift或C#的开发者将会对Dart类型系统有更深的认识。有了这一篇的铺垫,我们下一篇就可以正式进入Dart中的类型系统了,下一篇我们会将Dart中可选类型、泛型、协变、泛型类型具体化等。

转载地址:http://npbtb.baihongyu.com/

你可能感兴趣的文章
项目:Vue.js高仿饿了吗外卖APP(一)
查看>>
javascript中一些相对位置
查看>>
vue高仿饿了么课程项目--布局篇学习笔记
查看>>
es6 javascript的Iterator 和 for...of 循环
查看>>
Javascript中的shift() 、unshift() 和 pop()、push()区别
查看>>
将嵌套的数组扁平化
查看>>
vue-router的两种模式及区别
查看>>
c中嵌入python
查看>>
SPSS基础教程:SPSS统计分析基础
查看>>
ICMP协议
查看>>
SSL协议
查看>>
IMAP,POP3,SMTP协议
查看>>
单例模式(java)详细
查看>>
java线程中信号量Semaphore类的应用
查看>>
如何设置CentOS为中文显示
查看>>
FrameLayout之我见
查看>>
个人解读Activity之一
查看>>
实现自定义布局的Notification
查看>>
AlarmManager的学习与实现
查看>>
解读Content Provider之一
查看>>