J言語の印象: その変態さと可能性

なんだか驚いた、というわけで、J言語を少し調べたり触ったりしました。このJ言語、2014年は絶対に … … 流行らないでしょう。

J言語のホームページは http://www.jsoftware.com/ です。必要なものはココに揃っています。J言語の入門的解説であるPrimerもあります。そのPrimerの冒頭に曰く:

J is a very rich language. You could study and use it for years, and still consider yourself a beginner.



J言語はとても奥深い言語です。何年もJ言語を勉強し使い続けても、それでも「自分はまだ初心者だ」と感じるかもしれません。

のっけから気力が萎えることを言ってくれますね。(人によっては挑戦意欲を刺激されるかもしれませんが。)

日本語の資料は少ないですが、次がまとまっていて良いと思います。

内容:

  1. 奇妙な構文と膨大な記号演算子
  2. 右から左に読んでいく言語
  3. 基本データは数値配列
  4. おおーっ、iPhoneで使える!

奇妙な構文と膨大な記号演算子

最初に立ちはだかる壁は:

  1. 奇妙な構文、
  2. 膨大な記号演算子

一番目は文法(グラマー)のことで、二番目は語彙(ボキャブラリー)のことです。文法は、奇妙とは言っても何かしら合理的なルールがあるでしょうから、まーなんとかなるかな、と思うのですが、記憶力が乏しい僕にとっての大きな障害は語彙です。

記号文字からなる組み込み演算子がイッパイ定義されています。常識的な演算子もありますが、大部分は見てもまったく見当がつかない記号列です。こりゃ根性で暗記するしかなさそう。

「<」は普通に不等号(比較演算子)です。「<.」「<:」は分かりますか? 分かるわけないですよね。「<.」は二項の小さい方を取る演算子(min)、「<:」は「≦」の意味です。

さらに、ほとんどの演算子がアリティ(項数)でオーバーロードされています。「<」「<.」「<:」が二項演算子として使われるときは上記の意味ですが、右側だけに引数(被演算子)を取る単項演算子のときは別な意味を持ちます。「<」がボックス化(Box)、「<.」が切り捨て(Floor)、「<:」がデクリメント(Decrement)となります。ボックス化は、今のところ意味不明です(調べがついてない)。

組み込み演算子の一覧は次のURLに一覧されています。ウエエエー、かんべんしてくれ。

右から左に読んでいく言語

J言語の対話型インタプリタであるjconsoleは、キーボードから入力された式(Jでは文と呼ぶ)を評価して結果を返します。10 - 3 なら、結果として 7 が返ります。では、jconsoleに 10 - 3 - 2 と入力するとどうなるでしょう?


10 - 3 - 2
9

jconsoleのコマンドラインプロンプトは空白3つなので、最初の行がユーザー入力、次の行が応答の行です。つまり、10 - 3 - 2 の計算結果は 9 なんですね。ハレェ?

J言語では、常に右から先に演算子の適用がされます。10 - 3 - 2 は 10 - (3 - 2) と解釈されるので、10 - 1 = 9 となります。演算子の優先順位の概念もないので、4 * 5 - 2 は 12 となります(18じゃないです)。

構文は右から左ですが、キーボードのタイプ入力は左から右に進みます。キーを打った文字が左に追加されるようなエディタで書くと都合がいいと思いますが、通常の環境ではカーソル(カレット)左移動を多用しそう。左から右なら日本語として読み下せて楽なんですが、右から左は辛いなー。

演算の優先順を明示するには括弧を使えばいいのですが、うかつに括弧を使うとハマリます。ブレイス(「{」、「}」)とブラケット(「[」、「]」)は演算子記号に割り当てられていて、括弧としては使えません。丸括弧(「(」、「)」)も特定の状況では演算子(高階の演算子)で、単なるグルーピングではありません*1

基本データは数値配列

J言語のアトミックなデータ型は数値型です。普通の整数と浮動小数点数だけでなく、多倍長整数(big integer)、有理数複素数も使えます。文字列型もありますが、おそらく、内部的には文字番号の配列でしょう。日本語も扱えないこともないですが、期待しないほうがいいようです。

複合データ型は配列です。配列に囲み記号はなく、項目のあいだの区切り記号は空白です。2 1 6 のように数値を単に並べると配列になります。配列を囲む記号がないので、配列の入れ子はできません。その代わり、複数の数値を多次元配列に編成できます。例えば、2行3列のマトリックスは、長さが6の1次元配列を2次元に整形したものだと捉えます。

多次元配列の構成には演算子$(Shape)を使います。


2 3 $ 1 3 5 2 4 6
1 3 5
2 4 6

$の左の 2 3 は「2行3列」を意味します。$の右側は、素材となる1次元配列です。右の配列の長さが足りないと、サイクリックに繰り返して補完します。


2 3 $ 1 2
1 2 1
2 1 2
2 3 $ 1
1 1 1
1 1 1

上記のマトリックスの例では、次元が2で、それぞれの次元のサイズが2と3でした。より一般に任意の次元の配列が定義できます。次元ごとのサイズを並べた配列が形状(shape)で、$演算子の左に置きます。


2 3 4 $ 1 2
1 2 1 2
1 2 1 2
1 2 1 2

1 2 1 2
1 2 1 2
1 2 1 2
5 $ 1 2
1 2 1 2 1

3次元配列の表示は、マトリックスを並べた形式です。1次元のときも、長さ指定として$演算子を使えます。4次元配列は次のような表示になります。


2 2 2 2 $ 1 2
1 2
1 2

1 2
1 2


1 2
1 2

1 2
1 2

よく見ると、マトリックスのグループを区切る空行の数が変わっているのが分かります。

おおーっ、iPhoneで使える!

J言語の修行(苦行?)を積めば、驚嘆すべき短いコードが書けるわけです。その一例が、「1から10までの整数を、ランダムに100個生成して、その標準偏差を求める」プログラム 0.5^~(+/%#)2^~(-(+/%#))1+?100$10 です。

しかし、ここまで可読性を犠牲にして短いコードを書いて、いったい何の意味があるのか? という疑問は禁じえません。学習の困難さを考えると、メリットが見えないなー、と。

ところが、モチベーションを上げる要因が見つかりました。J言語の処理系はiPhoneiPadAndroid端末でも使えるんです。

このテの小さな機器では、キーボード入力が快適には出来ません。なので、なるべくキータイプ数を減らしたいのです。J言語なら、同じことをするのに、他の言語に比べて圧倒的に少ないタイプ数で済みます。

J言語は、数値計算が主たる用途ではありますが、モーバイルデバイス上でストレスなく使えるインタプリタ言語です。超高機能電卓として意外とウケるかもな(ただし、一部の人に)、と思ったりもします。

*1:フック、フォーク、トレインと呼ばれる、演算子を複合する構文です。