作者 | Michael Thomsen
译者 | 王强
编辑 | 张之栋、Yonie
9 月 10 日, Dart 2.5 SDK 稳定版正式发布。其中包括两项重要的开发者新功能的技术预览:机器学习自动完成——由机器学习(ML)驱动的代码自动完成功能;以及用来直接从 Dart 调用 C 代码的 dart:ffi 外部函数接口。另外,Dart 2.5 还改进了对常量表达式的支持。
随着新版发布,我们在打造最优秀的客户端优化语言,为任何平台快速构建应用程序的道路上又迈进了一步。我们已有的生产力工具套件包括 热重载、可自定义静态分析 和 Dart 开发工具 等,新加入的机器学习自动完成功能在基础上锦上添花。第二项预览功能 dart:ffi 使你能够在众多操作系统上运行 Dart 代码时利用已有的原生 API,以及用 C 编写的跨平台原生库。
谈到打造最优秀的客户端优化语言,我们很高兴看到上周发布的 IEEE Spectrum 2019 顶级编程语言评级 中出现了 Dart 的身影。Dart 初次进入 IEEE Spectrum 编程语言评级就拿到了 16 名的成绩,趋势排名则是第 10 位;只看移动平台的语言时排到了第 6 位(在 Java、C、C ++、C# 和 Swift 之后)。
预览:通过机器学习提供代码补全
类型化编程语言的核心优势有一条是,在类型中捕获的附加信息使 IDE/ 编辑器能够在键入代码时提供自动完成来帮助开发人员。在代码补全的帮助下,开发人员只需键入字符的开头,然后从提供的自动完成选项中选择即可,这样就能避免拼写错误并浏览 API 提供的内容。
随着 API 逐渐膨胀,想要找到合适的选项也越来越困难;因为可选的自动完成列表太长了,按字母顺序浏览很费劲。我们经过一年的努力,成功将机器学习技术应用到了这个问题上。简单来说,这个功能是通过对大量 GitHub 开源 Dart 代码 的分析采集来训练模型,从而基于给定上下文给出可能的选项。这个模型基于 TensorFlow Lite,可在开发人员编辑代码时预测下一个字符的内容。新功能名为机器学习自动完成(ML Complete)。下面是使用 Flutter 框架开发新的 MyHome 小部件的示例:
来深入了解一下背后的工作机制。比如说你正在编写一个小程序,计算当前时间后一天的时间信息。使用机器学习自动完成功能的体验如下图一所示。首先,请注意它会根据名为 now 的变量向 DateTime.now() 提供自动完成推荐。接下来,请注意它在变量名 tomorrow 上提供的自动完成,最后在 now 变量上提供的第二个自动完成就是 add(...)。下图二是没有开启这一功能的自动完成演示,我们必须手动键入 DateTime,在 tomorrow 变量名上没有自动完成,此外 add(...) 方法在备选列表里排得比较靠后。
如何试用机器学习自动完成
机器学习自动完成功能现在以预览版状态发布。它直接内置在 Dart 分析器里,因此可用于所有支持 Dart 的编辑器,包括 Android Studio、IntelliJ 和 VS Code。有关启用此预览功能的详细信息,以及提供反馈和报告问题的具体介绍,请参阅此 Wiki 页面:https://github.com/dart-lang/sdk/wiki/Previewing-Dart-code-completions-powered-by-machine-learning
由于该功能仍在预览中,因此当前 Flutter 和 Dart 稳定版中的功能版本不会包含我们将在接下来的构建中加入的性能优化等改进。因此,我们建议你在预览此功能时临时使用 Flutter 开发通道 或 Dart 开发通道。
Flutter 开发通道:https://github.com/flutter/flutter/wiki/Flutter-build-release-channels
Dart 开发通道:https://dart.dev/tools/sdk/archive#dev-channel
预览:dart:ffi,用于 Dart-C 互操作的外部函数接口
有许多开发人员要求我们改善在 Dart 中调用 C 代码的操作。典型证据就是 Flutter 的问题跟踪器,其中 C 互操作是评级最高的功能开发需求,拿到 600 多票。这些需求背后有许多有趣的用例,例如调用平台底层 API(如 stdlib.h、Win32),以及利用现有的跨平台库和用 C 语言编写的实用程序(如 TensorFlow、Realm 和 SQLite)等。
目前,从 Dart 直接调用 C 的支持仅限于使用 原生扩展 深度集成到 Dart VM。此外 Flutter 应用程序可以使用 平台通道 调用主机,并从那里向前调用 C,这是个间接的方法,但这种双层间接路径很不理想。我们希望实现一种新的机制,提供出色的性能,易于使用,并且可以在许多支持 Dart 的平台和编译器上运行:https://dart.dev/platforms
Dart-C 互操作支持两大场景:
在主机操作系统(OS)上调用基于 C 的系统 API。
调用基于 C 的库,库可以是单平台也可以是跨平台的。
调用基于 C 的操作系统 API
来看看第一类场景。这里我们将调用 Linux 命令 system。该命令可以执行任何系统命令;传递给它的参数实际上是传递给了 shell/ 终端并在那里运行。这是此命令的 C 头:
所有互操作机制的核心挑战都是处理两种语言的语义差异。对于 dart:ffi 来说,Dart 代码需要表达两件事:
C 函数及其参数类型和返回类型。
对应的 Dart 函数及其类型。
我们定义了两个 typedef 来做到这一点:
接下来我们需要加载库并查找我们要调用的函数。具体实现方法取决于操作系统;在这个例子中我们使用的是 macOS。下面是所有三种操作系统执行的完整示例:macOS、Windows、Linux。
// Load `stdlib`. On MacOS this is in libSystem.dylib.
finaldylib = ffi.DynamicLibrary.open('/usr/lib/libSystem.dylib');
// Look up the system function.
finalsystemP = dylib.lookupFunction('system');
接下来,我们使用特定于操作系统的编码来编码字符串参数、调用该函数,并再次释放参数内存:
通过 dart:ffi 执行系统命令来在默认浏览器中打开 dart.dev:
调用基于 C 的框架和组件
dart:ffi 的第二项核心用途是调用基于 C 的框架和组件。前文介绍的基于机器学习的代码补全就是一个实例!它使用 TensorFlow Lite,这是一个基于 C 的 API。dart:ffi 允许我们在需要提供代码补全的所有操作系统上运行 TensorFlow,性能还媲美原生 TensorFlow 实现。如果你想查看 Dart TensorFlow 集成的代码,请参阅此代码库:https://github.com/dart-lang/tflite_native
我们还希望调用基于 C 的库这一能力能给 Flutter 应用程序带来好处。比如你可以调用 Realm 或 SQLite 等原生库;此外我们认为 dart:ffi 可以为 Flutter 桌面 提供插件功能,这也很有用。
包装 API 和代码生成
你可能已经注意到在描述函数和查找函数符号时会有一些编程开销。这类模板代码中有很多可以从 C 头文件中生成。我们目前专注于提供基础原语,但也很愿意与感兴趣的朋友合作来开发一个生成器。
如何试用 dart:ffi
dart:ffi 库今天发布的是预览版。由于它仍处于预览状态,因此我们建议你使用 Flutter 主通道 或 Dart 开发通道 以快速获取我们所做的更改和改进。请注意 API 在推出最终正式版之前可能会有重大变化,因为我们会做很多改进并支持更多常见模式。这里可以详细了解第一个正式版计划包含的内容。以下是你应该了解的一些限制:
该库不支持嵌套结构、内联数组、打包数据或与平台相关的基本类型。
指针操作的性能不佳(但可以使用 Pointer.asExternalTypedData 来解决)。
该库不支持终结器(当对象即将被垃圾收集时调用的回调)。
C 互操作文档 和 dart:ffi API 参考文档 介绍了功能的核心概念,并给出了一些参考示例。如果你遇到任何问题或有疑问,我们邀请你在 Dart FFI 讨论组上发帖或提交问题。
dart:ffi API 参考文档:https://api.dart.dev/dev/
常量表达式改进
Dart 一直以来都支持创建常量和值;它们都能确保是编译时常量,因此性能表现出色。在以前的版本中常量表达式有一些局限。从 Dart 2.5 开始,我们支持更多定义常量表达式的方法,包括使用强制转换以及 Dart 2.3 中提供的新控制流和集合扩展功能:
总结
我们在接下来的几个季度有激动人心的规划,包括扩展方法、强制引用非空,以及一些早期的语言规划等工作。我们还在研究增强的并发支持——例如在现代手机上更好地使用多核处理器的能力。
我们的工作重点就是默认非空(non-nullable)。我们为此功能制定了雄心勃勃的计划,正在着手开展一系列工作。最近诞生的几种语言从一开始就支持非空,而大多数在新版中添加非空支持的老语言使用的方法仅限于额外的静态分析。我们的方法的一个主要不同是我们要做到完整的非空支持。简而言之,这意味着我们对非空性的理解将扩展到类型系统的核心,一旦我们的类型系统知道某些东西是非空的,我们就可以完全信任这些信息,并且后端编译器可以自由地优化这些代码。这种稳健性有很大优势,可以提供持久的“无异常体验”、减小代码体积并提升运行时性能。
每当我们更改语言时,我们都会意识到这种做法给我们的生态系统带来的负担。因此我们还付出了大量努力为现有代码提供丰富的迁移工具。我们希望这些工具能够抵消大部分迁移成本。我们还添加了一些支持逐步迁移的专用语言和工具功能,并努力合并我们自己的代码和 https://pub.dev/ 上共享的代码。
我们期待在今年晚些时候带来更多好消息!
英文原文:https://medium.com/dartlang/announcing-dart-2-5-super-charged-development-328822024970
领取专属 10元无门槛券
私享最新 技术干货