多年前,Larry Wall 分享了他关于脚本性质的论文。最近 Java 也获得了“脚本”支持,因此重新审视这个主题是合适的,并且希望与 perl 和 raku 语言社区相关。
Larry 论述的弱点(公平地说,作者的意图更多是启发性而不是完整性)是将脚本与编程进行对比。这种对比无法明确区分,因为脚本就是程序。也就是说,无论长短,脚本都是机器执行的命令,这是对程序的一个相当不错的一般定义。
更有用的对比——我认为也是作者的本意——是在脚本和其他类型的程序之间,因为这使我们能够将脚本编写(编写脚本)与“编程”(编写非脚本程序)进行比较。要做到这一点,我们需要知道还有哪些其他类型的程序。
答案的简短版本是:系统和应用程序,以及其他与工作程序员不太相关的东西,如(嵌入式)控制算法、电子表格和数据库查询。(我上面提供的定义非常宽泛,旨在避免陷入边界问题)。大多数程序员编写应用程序,一些编写系统,几乎所有人都偶尔编写脚本,尽管许多非专业程序员也编写脚本。
我认为应用程序和系统的定义特征分别是:
- 应用程序向用户呈现模型(用于操作)
- 系统为其他程序提供功能
例如,邮件客户端(如 thunderbird)与邮件守护进程(如 sendmail)相比——一个提供读取和撰写电子邮件的界面(模型),另一个为将电子邮件发送到其他服务器提供功能。
注意,在这个(再次宽泛的)定义下,库也是系统软件,这是有道理的,因为它们的用户是开发者(就像 PostgreSQL 一样),他们关心性能、可靠性和正确性等问题。顺便说一下,库以及“典型”的系统软件(如数据库引擎和操作系统内核)倾向于用 C 和 C++等语言编写,原因大致相同。
那么,脚本、应用程序和系统之间的区别是什么?我认为以下是一个很好的列表:
- 脚本往往很短,特别是应用程序可以变得非常大。
- 脚本往往是临时的(为特定需求而编写),应用程序和系统往往是为一系列用例而设计的。(非常常见的例子:构建脚本)
- 脚本往往只在特定环境中运行;相比之下,许多应用程序是为一系列设备/客户端设计的;许多系统有特定要求,但目的是它们可以在多个不同的环境中设置。
- 由于脚本是临时的、短的且依赖环境的,许多软件工程标准最佳实践并不真正适用(实际上经常被忽视)。
显然,这些区别并不是真正的二元的——“短”与“长”、“临时”与“通用”——不能用来确定某事物是脚本还是应用程序。(如果确实出现了这个问题)更重要的是,在过去一年我编写的大约 10 个脚本中——有些是专业的,有些不是——所有或大多数这些特性都成立,我相信大多数读者也是如此。
最后,这些特性指向的是特定类型的程序,而不是特定的技术(或技术集)。确切地说,脚本(主要)是短的、定制的程序,用于自动化临时任务,这些任务要么太特定要么太小,不值得开发和分发另一个程序。
这对脚本语言的首选特性(指旨在支持脚本开发的语言)有进一步的影响。特别是:
- 它应该使程序简洁。经济上的理由是,由于脚本是临时的且依赖环境,其预期总寿命价值不是很高,所以编写它应该很便宜,这意味着脚本应该很短。
- 与此相关,类型系统提供的价值通常小于在较大的(应用程序)程序中,广泛的建模功能(类层次结构)的价值也类似较低,因此许多脚本语言的类型系统和数据建模功能非常弱,如果有这些功能的话。
- 另一方面,与环境的互操作性非常重要,因此 I/O 功能往往很完善。(与 C 对比,在 C 中 I/O 完全是由库提供的事后想法)。
- 以隐式方式依赖本地环境是可以接受的,因为这是你无论如何都会做的。
- 在另一种编程语言中可能是致命错误的情况下发出警告是可以接受的。
- 事实上,我认为与应用程序相比,正确性的考虑通常是不同的,即更宽松,因为脚本编写者不一定期望他们的脚本在每个环境和每个可能的输入下都能运行。
作为最后一点的例子——Python 3 要求用户精确指定输入的编码,当不知情的脚本编写者不小心将 ISO-8551 数据读取为 UTF-8 或反之亦然时,会导致各种麻烦。Python 2 没有这样做,对于大多数脚本——而不是应用程序——我认为这是正确的选择。
这个特定领域并不总是存在。在计算环境中,如果所有感兴趣的东西都已经由一个应用程序充分捕获,或者缺乏有效自动化临时任务的能力(我特别想到的是 PowerShell 出现之前的 Windows),脚本编写的实践往往不会发展。类似地,在现代“云”环境中,系统设置由另一个组织托管的状态机控制,脚本实际上没有太多未来。
换句话说,脚本只有在有很多“可脚本化”任务的环境中才能繁荣;意味着没有现成解决方案的任务,有强大的设施可供脚本访问的环境,以及其用户有权自动化这些任务的环境。这些特性在 Unix/Linux“工作站”上很常见,但在智能手机和(如前所述)云计算环境中则不太常见。
说实话,我对此发展有点担心。我可以指出像 go 和 rust 这样的语言的发展和流行,它们不是确切的脚本语言,或者用 TypeScript 替换 JavaScript 来进一步说明这一点,但我认为这不是必要的。同时,我可以指出数据科学作为一门学科的发展,以证明脚本编写仍然存在并且很好(实际上可能比以前更经济相关)。
对于 perl 5/7 和 raku 来说,结论应该是什么?我不太确定,主要是因为我不确定更广泛的 perl/raku 社区是否希望他们的姐妹语言是脚本语言还是应用程序语言。(如前所述,我认为 Python 社区选择让 Python 3 成为一种应用程序语言,这对他们的用户并非没有影响)。
Raku 添加了许多应用程序语言常见的功能(我特别想到它强大的类型系统),延续了 perl 5 可能开创的趋势。这确实是一个非常强大的策略——一种语言可以为脚本而引入,然后其中一些脚本被扩展为应用程序(甚至系统),从而确保其持续使用。但要使其奏效,新的 perl 家族语言必须基于其脚本编写的优点引入,并且必须有大量可脚本化的任务可供自动化,其中一些——或它们的组合——成长为应用程序。
就我个人而言,我希望看到脚本编写有一个光明的未来。不仅仅是因为脚本是最容易访问的编程形式,还因为允许甚至要求脚本编写的环境是一个并非所有有趣问题都已解决的环境,一个用户要求它执行如此多样化的任务以至于没有一个应用程序可以满足的环境,一个可以探索周围奇妙设备真正潜力的环境。
在这样的世界中,脚本编写可能会有一个光明的未来。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。