Toolbox languages

Hillel Wayne

ツールボックス言語

原文は Hillel Wayne により に公開されました。 このブログを購読する

ツールボックス言語とは、サードパーティのパッケージに頼らなくても問題をうまく解決できるプログラミング言語のことだ。僕の定番のツールボックス言語はPythonとシェルスクリプトで、これは皆さんもよくご存じだろう。ここでは、もう少しマイナーなものをいくつか紹介したい。

AutoHotKey

外せないやつから! AutoHotKeyは一言でいえば「GUIのためのシェルスクリプト」だ。プログラムで操作できないアプリケーションの使い勝手を滑らかにしてくれる、とにかく素晴らしいツールだ。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なら数文字で済むので、ちょっとした計算を素早くやるのに気に入っている。
  • 多次元配列が第一級だ。+一つで、2つの数の足し算も、2つの配列の要素ごとの加算も、配列の各要素に単一の数を足すことも、高次元配列の各行(あるいは各列)に配列を足すこともできる。
  • 数を素因数分解するといった、特殊な数学的処理を行うトップレベルのプリミティブが豊富に用意されている。

使用例:

ある数の素因数をすべて求める:

    q: 2520
2 2 2 3 3 5 7

2つのプロセスがそれぞれ4ステップのアルゴリズムを実行するとき、考えられるインターリーブは何通りあるか

    ni =: !@:(+/) % */@:!
    ni 4 4
70

1〜3個のプロセッサと1〜3ステップのそれぞれの組み合わせについて、インターリーブの数を表にしたい場合は?

   (ni@:$)"0/~ >: i. 3
1  1    1
2  6   20
6 90 1680

さらに読む:

Frink

このリストの中ではおそらく最もマイナーな言語だ。Frinkは次元解析(単位付きの計算)のために設計された言語だが、開発者が面白いと思ったことをカバーするための機能もいろいろと備えている。そしてそれは、かなり幅広い! 僕が見た中では、どのプログラミング言語よりも「より良い電卓」に近い存在かもしれない。とっつきやすく、強力で、JやRakuのような馴染みのない構文もない。

便利な機能:

  • 組み込みの単位や単位修飾子が豊富にある。calendaryearはちょうど365日、tropicalyearは365.24日、half nanocenturyは約1.6秒だ。
  • 日付リテラル記法がある。# 2000-01-01 # - # 200 BC #は2199.01年になる。
  • 不確かさを扱うための組み込みの区間型がある。少し扱いにくいが、ちゃんと機能する。

使用例:

1970年1月1日午前0時に生まれた人が、生まれてから10億秒経つのはいつか?

   # 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関数を定義すると、その引数がそのままCLIの引数になる。
  • 実行時の値に基づいてディスパッチされる、多重ディスパッチによるマルチメソッド。これをMAINと組み合わせることで、小さなCLIツールを作るのが本当に簡単になる。
  • 数学演算子の多くにはUnicodeの同等物があり((elem)に対する∈のように)、これは僕のAutoHotKeyのホットストリングと相性が抜群だ。

使用例

ランダムな10文字の小文字文字列を3つ生成する。

> 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()

オプションの面倒な組み合わせをいくつか持つCLIを書く()。

さらに読む:

Picat

僕にとって一番新しいツールボックス言語であり、そもそもツールボックスという考え方を意識するきっかけになった言語だ。論理プログラミング、制約解法、そして手続き的な脱出口が混ざり合った、頭がクラクラするような言語である。最初は「より良い制約ソルバー」として手に取ったのだが、そこから次々と新しい使い道を見つけていった。

便利な機能:

  • 変数への代入。論理言語としては驚くほど便利だ。多くの問題がほぼ論理プログラミング向きに感じられるのに、アルゴリズムのほんの小さな一部だけをどうしても100%論理的に表現する方法が分からない、ということがよくあった。手続き的な記述が、僕に必要な脱出口を与えてくれたのだ。
  • 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

たくさんのアクティビティ、時間的制約、両立しない組み合わせがある中で、休暇の計画を立てる

論理パズルに複数の解があるかどうかをチェックする。論理パズルの手がかりが冗長かどうか、あるいは一つ取り除いても一意な解が保たれるかどうかをチェックする。

ペトリネットの到達可能性ソルバーをさっと作ってみる。

さらに読む:

良いツールボックス言語の条件とは?

僕が見てきた優れたツールボックス言語の多くは、計算や算術のためのものだ。作用や自動化のためのツールボックス言語も(AutoHotKeyのように)可能だと思うが、その領域はまだあまり開拓されていない。

ツールボックス言語は、とにかく、とにかく書くのが速くなければならない。少なくともPythonよりは速く。たとえば「ランダムな数のペアを10個」を比べてみよう:

# 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
  • 連結型プログラミング言語が本当に得意とする小さな問題が何なのか分かれば、それも
  • ウェブスクレイピングやパースを、計算と同じくらい簡単にしてくれる何か。Requestsやbs4は違う。

Saul Pwanson氏にフィードバックをいただいた。この記事が気に入ったら、ぜひ僕のニュースレターに参加してほしい! 毎週新しいエッセイを書いている。

僕は企業向けに形式手法のトレーニングを行い、ソフトウェア開発をより速く、安く、安全にしている。詳しくはこちら

僕の新著Logic for Programmersが現在アーリーアクセス中だ。こちらから入手できる。

この記事は「muse-spark-1.2-contributor」を使用して翻訳されました。

コメント