Julia で下付き文字をインデックスに変換するマクロを書いてみた。


TL;DR

  • 誰も使わないような有用性のないパッケージを作ってしまいました。
  • この記事も自己満足なポエムでしかなく、Julia を便利な道具として使いたい方には役に立ちません。

以上をご理解の上、問題がなければ続きをご覧ください。

@_

こんなマクロを実装しました。

  • 下付き文字(例: Fₙ)をインデックス(例: F[n])として parse する。
    • @_ Fₙ = Fₙ₋₁ + Fₙ₋₂F[n] = F[n-1] + F[n-2] として解釈・評価される。
  • 多次元配列にも対応。
    • @_ Π₍ᵢ₎₍ⱼ₎ のように添え字のグループをかっこで括ると Π[i, j] のように解釈・評価される。

インストール

(v1.x) pkg> add https://github.com/antimon2/Sub2Index.jl.git

具体例

julia> using Sub2Index

julia> F = ones(Int, 10);
julia> @_ for n = 3:10 Fₙ = Fₙ₋₁ + Fₙ₋₂ end;
       # equivalent to `for n = 3:10 F[n] = F[n-1] + F[n-2] end`
julia> F
10-element Array{Int64,1}:
  1
  1
  2
  3
  5
  8
 13
 21
 34
 55

julia> Π = zeros(Int, (10, 10));
julia> @_ for i = 1:10 Π₍ᵢ₎₍₁₎ = Π₍ᵢ₎₍ᵢ₎ = 1 end;
julia> @_ for i = 3:10, j = 2:i-1 Π₍ᵢ₎₍ⱼ₎ = Π₍ᵢ₋₁₎₍ⱼ₋₁₎ + Π₍ᵢ₋₁₎₍ⱼ₎ end;
julia> Π
10×10 Array{Int64,2}:
 1  0   0   0    0    0   0   0  0  0
 1  1   0   0    0    0   0   0  0  0
 1  2   1   0    0    0   0   0  0  0
 1  3   3   1    0    0   0   0  0  0
 1  4   6   4    1    0   0   0  0  0
 1  5  10  10    5    1   0   0  0  0
 1  6  15  20   15    6   1   0  0  0
 1  7  21  35   35   21   7   1  0  0
 1  8  28  56   70   56  28   8  1  0
 1  9  36  84  126  126  84  36  9  1

動作例

Binder で動作するものを公開しました。

どんなときに使えるか?

有効な使い途はありません(重要)。

理由は以下の通り:

  • 通常のインデクシングの表記(例: F[n])の方がタイプ数が少なくて済みます。
  • 多次元の場合(例: @_ Π₍ᵢ₎₍ⱼ₎)は無駄に長くなり可読性も落ちます。
  • 何より、下付き文字として使用できる文字が非常に少ないです("₍₎₊₋₀₁₂₃₄₅₆₇₈₉₌ₐᵦᵪₑᵧₕᵢⱼₖₗₘₙₒₚᵩᵣᵨₛₔₜᵤᵥₓ" の全38文字のみ)。

じゃぁなんで作ったのか?

完全に自己満足です。

きっかけは、Twitterでの以下のやり取り↓を見て:

でそこで参照されていた以下のStack Overflowの質問を見て:

「できるよ」「いや無理じゃね?」とか書かれていて、具体的な実験例とか実装例がなかったので。

ないなら自分でやってみよう、と思ってやってみてできたのでついカッとなって公開してしまった、というわけです。
公開はしましたが後悔はしていません。

どうやって実装したのか?

詳細は Github リポジトリ のソースを見てみてください。DocString 込で96行(うちDocStringだけで半分以上使ってます)。

簡単に説明すると:

  • 識別子として評価される前の Symbol を文字列操作して下付き文字の塊をインデクシングに変換

これだけ。

もう少しだけ詳しく言うと、

  • Symbol を文字列に変換して変換して Meta.parse() に掛けて Expr に変換
  • esc() を通さないとスコープで参照できる識別子として識別できないので注意
  • 処理のメインは1つの関数(AbstractString/Symbol/Expr/その他のいずれかを受け取る各実装を多重定義)
  • macro _(src) は↑を呼ぶだけ

こんな感じです。
もし反応あればも少し詳しく解説します。

参照