简介
大家好!希望你们一切都好。
对 Exercism 来说,八月是非常忙碌的一个月。我们合并了 Premium 和 Insiders,把自动反馈直接加进了编辑器,推出了学习轨道奖杯,还对网站做了大量小改进!如果你还没查看自己的学习轨道、看看能拿到哪些奖杯,一定要去看看。我们已经给获得一个或更多奖杯的所有人发了邮件,也请留意查收。 八月里,我们在 #12in23 中也玩得很开心,探索了人们通常用来开发应用的语言。
这个月是 Slimline September,我们要探索的是那些语法往往非常简洁凝练的语言。具体来说,我们会看 8th(Forth 的后代)、AWK、Bash、jq、Perl 和 Raku(以前叫 Perl 6)。
徽章
要获得 Slimline September 徽章,你需要在九月里完成这些语言中任意一种的五个练习。
还有一个贯穿全年的 12in23 徽章。要获得它,你需要用该语言解决五个精选练习。
- Gigasecond:处理日期
- Atbash Cipher:处理字符串
- Darts:处理数字和条件
- Luhn:处理字符串、条件和数字
- Series:处理字符串和序列
这些练习以及前几个月的练习都可以在 #12in23 页面上找到。
概览
我们来深入了解一下这些语言,先看看每一种的概览。
8th
- 由 Ron Aaron 开发。
- 名字是 Forth 语言的双关,Forth 是它的主要灵感来源。不过它和 Forth 有很多不同:
- 强类型
- 跨平台
- 更高的安全性(没有直接内存访问,也没有内置汇编器)
- 提供免费版和商业版,后者功能更多。
- 闭源,但购买企业许可证后就可以查看源代码
AWK
- AWK 是 20 世纪 70 年代由 Alfred Aho、Peter Weinberger 和 Brian Kernighan 在贝尔实验室创造的。这个名字是三位作者姓氏的首字母缩写。
- 它是一种领域特定语言,专为文本处理而设计,但也可以用于其他用途
- AWK 和 sed、grep 一样是一种 Unix 过滤器,适合在管道中使用
- Single UNIX Specification 和 Linux Standard Base 规范都要求任何实现都必须包含它,所以大多数 *nix 机器上都能见到它
- AWK 语言有多种实现:
- awk(原版 AWK 也叫 oawk):最初的实现
- GNU AWK(gawk),1988 年发布,对语言做了大幅修改和扩展
- BWK AWK(又叫 nawk),90 年代末发布
- mawk:快速的字节码解释实现
- 在很多 *nix 系统上,
awk命令是指向gawk或nawk的符号链接
Bash
- Bash 是由 Brian Fox 开发的 Unix shell,于 1989 年发布。
- 它被设计成 Bourne shell 的免费替代品,如今已成为大多数 Linux 发行版的默认登录 shell。它是 Bourne shell 命令语法的超集,因此过渡起来更容易
- 它在很多方面扩展了 Bourne shell:花括号展开、命令行补全、信号处理等等
jq
- 由 Stephen Dolan 开发,2012 年发布
- 旨在让你轻松地查询、转换和操作 JSON 文档(“JSON 版的 sed”)
-
jq工具(也就是该语言的实现)最初用 Haskell 实现,后来移植到了 C。另外还有基于 Go 和 Rust 的移植版本
Perl
- Perl 由 Larry Wall 在 20 世纪 80 年代末开发,1987 年首次发布。
- 它被设计成一种通用脚本语言,让报表处理更容易
- 影响非常大,尤其是它的正则表达式支持(稍后我们会再聊到)
Raku
- 由 Larry Wall(Perl 的创造者)设计,2015 年发布
- 它最初叫 Perl 6,本意是清理这门语言,去掉一些被认为没什么用或令人困惑的特性(Larry Wall 有个有趣的说法:“在 Perl 6 中,我们决定与其修正用户,不如修正语言。”)。结果 Perl 6 与 Perl 5 并不源码兼容,于是改名为 Raku
- 设计理念的核心是让编程愉快而高效,同时提供各种工具来应对各种各样的编程挑战(通用)
- 由于 Raku 是一份规范,所以可以有(也确实有)多种实现。目前唯一在积极开发的实现是 Rakudo,但也有一些较老的实现,比如 Pugs(用 Haskell 编写)、v6-KindaPerl6 和 Niecza(面向 CLR)
这些语言都用在哪里?
8th
- 很遗憾,我们没能找到它在哪些地方被使用
AWK
- 用于数据提取和报表,以及一般的脚本编写
Bash
- 主要用于系统管理,也用来提供 CLI 工具或包装其他工具。我们在批量处理 Exercism 代码仓库时大量使用它
jq
- 用于查询、转换和操作 JSON 文档,通常以 shell 脚本的形式出现
Perl
- 用于数据操作、文件解析、Web 编程和系统管理任务。凭借字符串处理能力和庞大的模块生态,它在互联网早期就流行起来。
Raku
- 用于文本处理、系统管理等等
从编程的角度看,这些语言有什么有趣之处?
这些语言大多是动态类型、解释型的,这和它们的脚本语言本质很契合。不过也有一些例外,特别是在支持的编程范式方面。
8th
- 强类型
- 多范式:过程式,但更有意思的是基于栈(基于栈的执行模型)、反射(能够检查和修改自身的结构和行为)以及串接式(所有表达式都是函数,函数的并置表示函数组合)
- 可以编译成本地代码,也可以在 REPL 中解释执行
AWK
- 动态类型,通常为解释型(取决于所用的实现)
- 主要范式是数据驱动,你把程序写成一组语句,描述要匹配的数据和所需的处理,而不是明确地定义一系列要执行的步骤。AWK 也支持过程式编程
Bash
- 动态、解释型语言
- 支持命令式和过程式编程
jq
- 动态、解释型语言
- 纯函数式语言(所有值都不可变),强调“管道”。很有 Unix 的味道
Perl
- 动态类型、解释型
- 多范式,支持函数式、面向对象和命令式编程
Raku
- 动态类型,但支持渐进式类型,可以在需要的地方加上静态类型(Perl 是动态的)
- 多范式语言:命令式、过程式、面向对象和函数式
它们好在哪里?
8th
- 语法极少,让这门语言更容易学习和理解。用 JSON 来描述数据(比如对象和数组)。还支持栈、队列、堆等其他容器
- 没有保留关键字。子程序被称为“word”,而且很容易定义新的 word。不管是内置的还是用户定义的,所有 word 都可以在运行时重新定义
- 跨平台。可以轻松为任何受支持的平台生成可执行文件
- 安全。内置安全特性,能防止各种 bug(没有直接内存访问,运行时也不链接动态库)
AWK
- 语法简单,AWK 代码结构非常一致,因此容易学习和阅读。它的数据结构也简单而灵活
- 表达力很强,用很少的代码就能做很多事。非常适合写单行脚本
- 安装在大多数 *nix 机器上,这意味着你能在很多地方用到 AWK 技能(和 /bin/sh 一样,是标准 Unix 中仅有的脚本语言)
- 在管道和 shell 脚本中表现出色,AWK 可以处理其他工具的输出,反之亦然
Bash
- 可以在大多数平台上使用。几乎所有 *nix 机器上都装了它,包括 macOS。有了 Windows Subsystem for Linux(WSL),bash 现在也能在 Windows 系统上使用。
- 可以把它当作 RE(P)L 来用:既可以逐条运行命令,也可以从文件(即 shell 脚本)中读取并执行代码。如果你用过 Linux 终端,那你说不定已经写过 bash 代码了,因为终端通常就是一个 bash RE(P)L
- Bash 和 shell 脚本广泛用于系统管理、devops 和计算机管理。
- 极其通用、灵活
- 强大的字符串处理能力,包括非常直接的字符串插值
jq
- 处理 JSON 的语法简单、简短,容易学习
- 允许自定义函数,以应对更复杂的操作。
- 支持尾递归优化,非常适合递归处理数据
- jq 工具以单个二进制文件分发,体积只有 30 KB 左右
-
yq工具封装了jq,让你可以用同样的语法操作 XML、TOML 和 YAML 文件(它在底层会把这些数据类型转换成 JSON) - C 和 Go 两种实现都支持嵌入到其他应用程序中
Perl
- 能在大多数平台上运行。非常适合编写跨平台脚本
- 灵活性是 Perl 设计理念的基石。它著名的口号是:“做同一件事的方法不止一种”(TMTOWTDI)。可以根据手头的任务选择不同的做法
- 社区强大,留下了许多有影响力的项目。很多脚本、工具和应用都是用 Perl 开发的。它曾被称为“把互联网粘在一起的胶带”
- 模块和库的生态丰富,可以通过 Comprehensive Perl Archive Network(CPAN)获取
Raku
- 庞大、复杂、强大,但它的设计也让你不必一次性学会全部。上手很容易,之后可以再慢慢接触更强大的特性
- 类型系统强大且可扩展,还包含渐进式类型。这意味着你可以指定想要的类型检查程度,从而在动态类型和静态类型之间取得平衡
- 支持多重分派,让你不用继承也能使用多态
- 在 Raku 里,Unicode 是一等公民。它原生支持处理不同的字符编码
- 提供高级的并发和并行特性。它内置支持异步编程、响应式编程和并行执行
它们各有什么突出特性?
8th
- 需要不同的思维方式。它独特的范式组合与其他语言很不一样,会挑战你想出不同的处理办法
- 基于栈和逆波兰表示法(RPN)的语法,让程序执行的思维模型非常简单。值被放到栈上,大多数 word 都是按它们对栈的影响来定义的
AWK
- 数据驱动范式非常强大。它需要一种不同的思维方式:程序被定义为一组“条件/动作”对,文本被拆分成记录(通常一行一条记录),每条记录又被拆分成字段(比如 CSV 的字段,或者一个字段一个词)。一旦习惯了这种思路,你就会体会到这种方法的优雅和表达力,并开始到处发现它的用武之地
- 处理文本的完美选择。无论是解析文本、转换文本还是生成报表,AWK 都能应付。像打印系统上每个用户的 shell、或者给 CSV 的某一列求和这样的任务,你会惊讶于所需代码之少
Bash
- 自动化的完美选择。shell 脚本非常适合自动化重复性任务。
- Bash 脚本使用管道,让你轻松地把其他程序粘合起来。写一个把某条命令的输出传给另一条命令的脚本轻而易举,也可以让脚本在执行到任何一条命令失败时就中止。
- 强大。能如此轻松地使用其他工具,让 bash 成为一件极其强大的工具
jq
- 非常适合轻松、干净地提取和操作 JSON 数据(如今这种数据多得是)。它已经成为转换 JSON 数据的事实标准工具。你甚至可以用 jq 创建 JSON 数据
- 支持流式数据,也就是说你可以处理“无限”的数据而不会遇到内存问题
- 对管道的强调,对熟悉流(比如 Unix 工具)的人来说很容易上手。这也让 jq 代码相当容易分析和理解
Perl
- 以简洁和表达力著称。用很少的代码就能做很多事
- 特别适合处理文本,很大程度上得益于它强大的正则表达式支持。尤其是 Perl 5 引入了很多新特性(比如反向引用、命名捕获组和惰性量词)。Philip Hazel 开发了 PCRE(Perl Compatible Regular Expressions),这是一个实现 Perl 5 兼容正则引擎的 C 库。即使是不基于 PCRE 的语言,也常常把自己的正则表达式支持设计成与 PCRE 兼容(因而使用 Perl 5 的语法)
Raku
- 支持自动线程化的 junction,让并行处理容易得多
- 支持惰性求值,让你能处理无限列表和序列而不遇到内存问题。这在处理大型数据集,或者涉及无限数据流的算法时特别有用
- 非常适合文本处理,提供了更简单、更易读、更强大的正则语法
- 内置支持用 grammar 定义自定义的领域特定语言(DSL)。这样你就能为特定的数据格式或语言创建解析器,更容易处理复杂的文本数据
该试哪一个?
- 如果你主要使用 Unix 系统,或者做 devops 相关工作,那 Bash 是一门非常值得学的语言。学 AWK、Perl 或 Raku 也很有好处,而且前两者在很多系统上都是预装的
- 如果你要处理 JSON(或 XML/YAML/TOML),jq 是显而易见的选择
- 如果你想处理文本,AWK、Perl 和 Raku 是显而易见的选择。
- 如果你想尝试点不一样的东西,8th 是个很好的选择
2023年09月01日
·
觉得有用吗?
作者:
Erik Schierboom