目次
シンボル
シンボルはコードをデータとして扱うための実装である。私もよく分からないし使いこなせていないので詳しくは触れない。
簡単な説明は以下の通り。
名前(識別子)を表し、かつ、参照先を示す。
下記の様に関数を定義すると、my-func
という関数名はシンボルとなる。コード中に呼び出せる。
また、symbol
関数を使用して意図的にシンボルを作ることもできる。
シンボルは名前空間と連動するもので、他の名前空間のシンボルを使用したい場合はモジュールの先頭にインポートを記述する必要がある。
データとしてシンボルを扱う
シンボルをデータにするためには、先頭にシングルクォートをつけるだけで良い。
キーワードとの違い
Clojureには、よくシンボルと似た記法で表される「キーワード(Keyword)」もある。キーワードは先頭にコロンが付き(例: :key)、シンボルとはやや用途が異なる。
シンボル (Symbol):
キーワード (Keyword):
- データとしてのタグ付けやラベル付けなどに使われる
- 名前空間を持てるが、基本的に参照(バインド)は行わない
- :my-keyのようにコロン付きで記述
キーワードはデータ構造のフィールド名や、関数のオプション指定など「識別子としての文字列を固定で扱いたい場合」に多用される。シンボルは主に、変数名や関数名などコード上で評価対象として使用したい場合に用いる。
シンボルをデータとして扱う利点と方法
ここまで簡単にシンボルについて述べたが、私には正直分からん。調べた限りではマクロに関係しているらしい。私はほとんどマクロを書いたことがないので分からないのも当然。当然なので安心である。
安心したところで、調査結果をまとめておきたい。以下にこれを記すが、活かす日が来るのかは全く分からん。
利点
メタプログラミング(マクロ等)でのコード生成・変換
Clojureのマクロは、リストやシンボルなどのS式データを操作して、新しいコード(S式)を生成するための仕組みである。シンボルをデータとして受け取り、動的に別のシンボルを生成してコードを組み立てることで、柔軟なプログラミングが可能になる。
動的に名前を構築・参照できる
文字列からシンボルを生成して、そのシンボルが指し示す関数や変数をevalなどで呼び出すことができる。これにより、「ユーザが入力した文字列を使って、コード上の何かを参照する」ような処理を実装できる(ただしセキュリティリスクや可読性低下を招きやすいため、多用は非推奨)。
コードの一部をそのまま「データとして」受け渡せる
Clojureではクオート(')を使ってシンボルを評価せずに“生のデータ”として渡すことができる。たとえばマクロ定義時にユーザが指定したシンボルをそのまま受け取り、別の文脈で再利用するといったことが簡単にできる。
方法
マクロで動的にシンボルを生成してdefする例
マクロでは、受け取った引数やマクロ内部で生成したシンボルを使って、実際のコードを組み立てることができる。以下は、マクロ内でランダムなシンボルを生成し、それにvalueをバインドする例である。
上記ではgensymを使って動的にシンボルを作り、そのシンボルをdefに渡している。生成されたシンボルはデータの一種としてマクロ内で組み立てられたあと、最終的には“定義する名前”として働く。マクロ展開後にどんなシンボルができるか調べると、myvar_11380 などの形になっていることが分かる(数字部分は毎回異なる)。
文字列からシンボルを作って、evalで呼び出す例
あまり推奨されるやり方ではないが、シンボルを使って文字列からコードの一部を動的に組み立てて呼び出すことも可能である。以下のように、ユーザが入力した関数名を元に計算を行う例を考えます。
- symbol関数で文字列からシンボルを生成
- listでシンボルと引数をまとめてリスト化
- evalに渡して実行
この方法は、ユーザの入力により任意のコードが実行されてしまう危険性があるため注意が必要である。とはいえ、「シンボルをデータとして受け取り、何かの“参照”として使う」というClojureの仕組みを理解するための例としてはわかりやすいだろう。
シンボルをデータとして格納・加工する例
シンボルをマップやベクターなど、他のデータ構造に格納しておき、あとでまとめて処理することもできる。たとえば「定義すべき変数名のリスト」をシンボルとして保持しておいて、一括でdefに展開するといったことが可能である。
上記ではsymbols-listというベクターにシンボルを格納してある。マクロdefine-varsは、受け取ったシンボルのコレクションをもとに動的にdefフォームを生成する。ここでも、「シンボルはあくまでただのデータ」としてマクロ内で扱っている」ことがポイントである。
難しく考えなくても良さそう
シンボルの利点が最大限活かされるような要件のシステムを作ることがどれだけあるのだろうか?そう考えると、とりあえずClojureに習熟するにあたっては最優先ということでもないと思える。なんにも分からんが、とりあえずコードを書こう。そうしよう。