工具箱语言
原文由 Hillel Wayne 于 发布,订阅该博客
工具箱语言是指无需依赖第三方包就能高效解决问题的编程语言。我默认的工具箱语言是 Python 和 shell 脚本,你大概都已经很熟悉了。下面介绍一些我用的比较冷门的选择。
AutoHotKey
必须得有它!AutoHotkey 基本上就是“面向图形界面的 shell 脚本”。它是填补那些不可编程应用空白的绝佳工具,用起来非常顺手。它只支持 Windows,不过 Mac 和 Linux 上也有类似的工具。
实用特性:
- 可以配置仅在特定程序中生效的快捷键,或根据全局标志是否开启、屏幕上是否出现特定文本等条件来触发。
- 能轻松调用大量基础的 Win32 功能。比如打开文件选择对话框,只需
f := FileSelect()。 - GUI 框架真的非常、非常好用。说实话,至少对于做些小工具而言,是我用过的所有语言里最好的。
示例:
Audacity 不支持自定义鼠标快捷键,所以我用 AutoHotKey 把中键映射到了一个键盘快捷键上。
#HotIf WinActive("ahk_exe audacity.exe")
MButton::Send "^l" ; silence selection
#HotIf我让输入 ;iso 就能自动填入当前日期。
:R:;iso::
{
Send(FormatTime(,"yyyy-MM-dd"))
}这是我用来做带时间戳笔记的小工具。
; right-ctrl + d
>^d::
{
TimeString := FormatTime(,"MM/dd hh:mm tt")
t_msg := InputBox(,TimeString,"w200 h100")
if t_msg.Result = "OK" {
timestampfile := A_WorkingDir . "\Config\timestamps.txt"
FileAppend(TimeString . "`t" . t_msg.Value . "`r`n", timestampfile)
}
}其他用途:为各种工具箱语言启动 REPL。输入通关某个游戏所需的那一长串 100 次按键(懂的都懂)。
延伸阅读:
J
一种数组语言,和 APL 类似。做数组运算极其出色,处理字符串或结构化数据时却让人抓狂。我以前用得很多,但现在大多换成了其他工具,比如 Excel 和 Raku。不过在它擅长的领域里,依然非常强大。
实用特性:
- 极度简洁。在大多数语言里需要好几行的事,在 J 里用几个字符就能搞定,所以我喜欢用它快速做大量数学计算。
- 一等公民的多维数组。
+既能把两个数相加,也能对两个数组逐元素相加,还能把一个数加到数组的每个元素上,或把一个数组加到高维数组的每一行(或每一列)上。 - 有大量顶层原语专门处理各种数学特殊情况,比如把一个数分解成质因数。
示例:
求一个数的所有质因数:
q: 2520
2 2 2 3 3 5 7假设有两个进程,各执行一个四步算法,一共有多少种可能的交错执行方式?
ni =: !@:(+/) % */@:!
ni 4 4
70如果我想列出一张表,展示 1 到 3 个处理器、每种 1 到 3 步情况下的交错数量呢?
(ni@:$)"0/~ >: i. 3
1 1 1
2 6 20
6 90 1680延伸阅读:
- 把 J 记法作为思维工具
- 把 J 当桌面计算器用
- 如何解数独(主要是附录部分)
Frink
可能是这份清单里最冷门的语言。Frink 专为量纲分析(带单位的数学运算)而设计,但也加入了开发者觉得有趣的各种功能——而且数量还不少!在我见过的所有编程语言里,它大概最接近“更好的计算器”:上手容易、功能强大,又没有 J 或 Raku 那样陌生的语法。
实用特性:
- 内置了大量单位和单位修饰符。
calendaryear严格等于 365 天,tropicalyear是 365.24 天,而half nanocentury大约是 1.6 秒。 - 日期字面量表示法:
# 2000-01-01 # - # 200 BC #的结果是 2199.01 年。 - 内置了用于处理不确定性的区间类型。虽然有点笨拙,但能用。
示例:
如果一个人出生于 1970 年 1 月 1 日午夜,他会在什么时候满十亿秒?
# 1970 # + 1 billion seconds
AD 2001-09-09 AM 02:46:40.000 (Sun) Central Daylight Time如果我以一定时间跑完一定距离,平均配速是多少?
// In miles per hour
2.5 miles / (27 minutes + 16 seconds) -> mph
5.5012224938875305623
// In meters per hour
2.5 miles / (27 minutes + 16 seconds) -> meters / hour
8853.3594132029339854
// In (minutes, seconds) per mile
1 / (4.5 miles / hour) -> [minutes/mile, seconds/mile, 0]
13, 19(6 ± 2) * (8 ± 1) 是多少?
x = new interval [2, -2]
(6 + x) * (8 + x/2)
[28, 72] // range is between 28 and 72延伸阅读:
Raku
Raku(原名 Perl 6)是一门非常古怪的语言,充满了各种黑魔法。它很强大,但也很容易出错。我还不太敢用它来跑生产环境程序。但作为个人脚本和工具箱语言,它非常出色。
实用特性
- 你可以自定义中缀运算符!还有后缀运算符。以及环缀运算符。
- 大量、多到让我担心的语法糖。比如不用写
[1, 2],可以直接写<1 2>。不用写["a", "bc"],可以直接写<a bc>。Raku 就是懂™该怎么做。 - 只要定义一个
MAIN函数,它的参数就会自动变成命令行参数。 - 基于运行时值的多方法与多分派。把它和
MAIN结合起来,写小型命令行工具会非常轻松。 - 许多数学运算符都有对应的 Unicode 符号(比如用 ∈ 代替
(elem)),和我的各种 AutoHotKey 热字串配合得很好。
示例
生成三个随机的 10 字符小写字符串。
> for ^3 {say ('a'..'z').roll(10).join}
fflqymxapa
znyxehaqvo
qwqxusudqw用文法解析不常见的结构化数据格式(见链接)。
把一堆 SVG 的 id 批量复制到 Inkscape 标签里。
use XML;
my $xml = from-xml-file("file.svg");
for $xml.elements(:NEST, :RECURSE<99>) -> $e {
with $e<id> ~~ /k\w/ {
say $_.target;
$e.set("inkscape:label", $_.target);
}
}
$xml.save()编写一个带几种繁琐选项组合的命令行工具(示例)。
延伸阅读:
Picat
我最新的工具箱语言,也是让我开始思考“工具箱”这个概念本身的语言。它是逻辑编程、约束求解和命令式逃生舱的奇妙混合体。我一开始只是把它当作更强的约束求解器来用,后来却不断发现它的新用途。
实用特性:
- 可以给变量赋值。在一门逻辑语言里,这出奇地有用。很多问题感觉几乎适合用逻辑编程来解决,但总有一小部分算法不知道该怎么用纯逻辑来表达。命令式就提供了我需要的逃生舱。
planner模块。我超爱planner模块。它是我最好的朋友。只要给它一个目标和一组可能的动作,Picat 就会找出能达成目标的动作序列。非常酷。
示例:
如果我以 4.5 英里/小时跑 X 分钟,以 5.1 英里/小时跑 Y 分钟,要想在 38 分钟内跑完 3.1 英里,X 和 Y 各应该是多少?
import cp.
[X, Y] :: 1..60, 45*X + 51*Y #= 31*60, X+Y #= 38, solve([X,Y]).
X = 13
Y = 25
yes给定一堆活动、时间限制和互斥关系,规划一个度假行程。
检查一个逻辑谜题是否有多解。检查谜题的线索是否冗余,或者去掉某一条线索后是否仍能保持唯一解。
快速搭建一个 Petri 网可达性求解器。
延伸阅读:
什么样的语言才算是好的工具箱语言?
我见过的大多数优秀工具箱语言都是用于计算的。我觉得用于副作用和自动化的工具箱语言也是可行的(比如 AutoHotKey),只是这个领域还没被充分探索。
一门工具箱语言一定要写起来非常、非常快。至少要比 Python 快。对比一下“生成十对随机数”:
# python
from random import randint
[(randint(10), randint(10)) for _ in range(10)]
# Raku
^10 .roll(2) xx 10
# J
10 2 ?@$ 10有几个因素决定了这一点:简洁的语法意味着少打字。内置功能多,就不用自己写基础的东西。从标准库导入虽然不算最理想,但可以接受。而需要安装第三方包则让我很烦。Raku 在这方面做得很酷;Rakudo Star Bundle 就预装了一堆实用的社区包。
如果一件事能用一行搞定,你就可以直接丢进 REPL 里跑。所以你会想要一个好用的 REPL。我用的大多数语言 REPL 都不错,不过我想我的 Lisp 和 Smalltalk 读者们对于什么叫“好用的 REPL”应该会有不同看法。
理想情况下,这门语言应该有平缓的上手曲线。Raku 虽然很复杂,但只学一点点就能派上用场,而 J 的学习曲线太陡,不太适合推荐给大多数人。不过,这一点往往会和“写起来快”相冲突。
我还想加入工具箱的其他工具
- jq,用于处理 JSON
- JavaScript,这样我就能通过开发者控制台修改别人的网站
- 某种能提供 J 的好处、但又没有那些一直困扰我的问题的 APL
- 一种 concatenative 编程语言,如果我能搞清楚 CPL 到底适合解决哪些小问题的话
- 某种能让网页抓取和解析像计算一样简单的工具。Requests 和 bs4 都不行。
感谢 Saul Pwanson 提供的反馈。如果你喜欢这篇文章,欢迎订阅我的 newsletter!我每周都会在上面发布新文章。
我为企业提供形式化方法培训,帮助软件开发变得更快、更便宜、更安全。了解更多请点击这里。
我的新书 Logic for Programmers 现已开启抢先体验!点击这里查看。
随机一篇博客
评论
登录后参与讨论