LLM時代におけるCommon Lispのリファレンス
LLM時代におけるCommon Lispのリファレンス
プログラミングにおいてもLLMの活用は急速に進んでいます。
コーディングではコードそのものも生成させるという動きが活発ではありますが、ここではコードは人間が書くという前提で文献の参照等の効率化にLLMを活用するという視点で眺めてみましょう。
LLM時代の到来で言語の壁がほぼ解消した
マニュアルは主に英語で書かれており、英語が苦手な人は翻訳されるのを待つという状況でしたが、ソースとなる文献が何語で書かれているかは、ほぼ関係なくなりました。
何語で書かれているかというよりは、利用しやすい構成や内容であるかが問われる時代になったようです。
具体的な例でいうと、日本語で記述された文献であるという理由で長年正式なANSI Common Lisp規格を参照せず、共立出版の「COMMON LISP 第2版」という規格の草稿のようなものを参照するような人や文献がありましたが、遂に歴史の遺物と化しそうです。
LLMで活用しやすいドキュメントの形式
Common Lisp界ではHyperSpec等が有名で活用されていますが、数百のファイルで構成されているためLLMに読み込ませるのが簡単ではありません。
一つのPDFファイルにまとまっているANSI Common Lispの規格のドラフトなどがありますが、主要部分の内容は基本的に同じなので、これを活用するとよさそうです。
これまではドキュメントをHTML化してまとめ、それを検索するという方式が多かったと思いますが、これからは一つのファイルにまとめるという書籍の方式に回帰しそうな雰囲気があります。
LLMに読み込ませると便利に活用できそうな文献
基本的にこれまで活用されてきた文献がそのまま使えそうです
LLM時代に定番となりそうなドキュメントソース
- PDF化されたANSI Common Lisp規格
- Common Lisp Recipes — A Problem-Solution Approach / Edmund Weitz
- 利用しているCommon Lisp処理系のPDF化されたマニュアル
- PDF化されたクックブック等のレシピ
- PDF化されたFAQ集や落とし穴集
PDF化されたANSI Common Lisp規格のドラフトはネットに転がっていることもありますが、原稿から生成することも可能です。
なお、ANSI Common Lisp規格のドラフトが流通して活用されているのは、言語仕様をコミュニティで自由に利用可能にするための方策です。ANSIの著作権はANSI Common Lisp規格という文献の表紙や体裁にのみ発生するものとし、仕様の内容自体は自由に配布可能という立て付けになっています。
この先数年は、巨大な一つのPDFなどのファイルにリファレンスになるドキュメントをまとめて配布するようなサイトが重宝されるのかもしれません。
LLMとのセッションの例
下記はNotebookLMに
- Common Lisp Recipes
- Common Lisp: The Reference(古い)
- Lisp Style and Design(古い)
- ANSI Common Lisp Standard Draft
- Alexandria Library Reference
- LispWorksのマニュアル
を読み込ませて調べ物をした例です。
下記では単発の質問となっていますが、QA形式で一覧するように指示すれば、逆引きのレシピのようなものはソースから簡単に生成することが可能です。
質問内容: utf8の文字列をuint8の配列に変換するには
回答形式は下記のようにしてください。
- Q. ○○するには
- A. 〜を利用します。
サンプルコード
...
uint8
の配列を作成するには
Q.
make-array
関数と、要素型指定(unsigned-byte 8)
を利用します。
A. Common LispのCommon Lispで配列(ベクトルも含む)を作成する最も一般的な方法は、make-array
関数を使用し、:element-type
引数で配列の要素の型を指定することです。uint8
に相当する型は、Common Lispでは**(unsigned-byte 8)
**です。この型指定子は、0から255までの符号なし8ビット整数を表します。
サンプルコード
;; 長さ10のunsigned-byte 8の配列を作成
(make-array 10 :element-type '(unsigned-byte 8))
詳細な説明
-
Common Lispの数値型について
Common Lispの整数(INTEGER
)は、数学的な意味での任意精度を持つことができます。これは、他の多くのプログラミング言語のように固定ビット幅でのオーバーフローを心配する必要がないことを意味します。
INTEGER
型は、マシンレジスタに収まる「小さな」整数であるFIXNUM
と、任意に大きな整数であるBIGNUM
という2つの排他的な集合に分かれています。Lispシステムは、必要に応じて自動的にFIXNUM
とBIGNUM
を切り替えます。
しかし、特定のサイズの整数(例: 8ビット整数)が必要な場合は、特定の型指定子を使用します。uint8
は、0から255までの非負の整数を表すため、Common Lispの標準では(unsigned-byte 8)
として表現されます。 -
(unsigned-byte 8)
型の詳細
unsigned-byte
は、非負の整数を特定のビット幅で表現するためのCommon Lispの型指定子です。例えば、(unsigned-byte 1)
は0と1のみを表すbit
型に相当します。同様に、(unsigned-byte 8)
は8ビットで表現可能な符号なし整数(0から255まで)を意味します。これは(mod 256)
や(integer 0 255)
と同じ意味を持ちます。
対照的に、符号付き整数には(signed-byte N)
という型指定子が使用され、例えば(signed-byte 8)
は-128から127までの整数を表します。 -
効率と「アップグレード」
Common Lispの処理系は、効率のために指定された要素型を「アップグレード」する場合があります。例えば、(unsigned-byte 3)
のような小さいビット幅を指定しても、実際には(unsigned-byte 4)
や(unsigned-byte 8)
(オクテット、つまり8ビットバイト)にアップグレードされる可能性があります。これは、現代のマイクロプロセッサが通常、RAMの内容を一度に複数のビット(通常はオクテット単位)で読み取るためです。このような内部的な最適化は、ビットベクトル(bit-vector
)や文字列(character
)の要素を除いて、コンパイラに多くの自由度を与えます。 -
バイナリデータとストリーム
(unsigned-byte 8)
は、バイナリデータの読み書きを行うストリームの要素型として広く使用されます。read-byte
やwrite-byte
といった基本的なI/O操作は、このようなバイナリストリームの要素(「バイト」と呼ばれる)に適用されます。LispWorksのCORBAライブラリでは、IDLのoctet
型がCommon Lispの(unsigned-byte 8)
にマッピングされると定義されています。 -
Foreign Language Interface (FLI) の利用 (LispWorksの例)
一部のCommon Lisp処理系(LispWorksなど)では、C言語などの外部言語との連携を目的としたForeign Language Interface (FLI) を提供しており、C言語の固定サイズ整数型に直接対応する型が提供されています。
LispWorksのFLIでは、:uint8
という型がISO C99のuint8_t
に相当し、8ビット符号なし整数型として定義されています。これらのFLI型は、外部のCデータ構造を扱う際や、特定のビット幅を持つデータをLisp側で厳密に表現する必要がある場合に特に有用です。また、FLIにはvector-uint8
のような特定の要素型を持つベクトルを扱うための型も提供されています。例えば、:unsigned
と:byte
を組み合わせた(:unsigned :byte)
はCのunsigned char
に変換されます。
これでuint8
の配列を作成する方法についてご理解いただけたでしょうか。
もし、この情報についてさらに詳しく知りたい場合は、Common Lispで符号付き8ビット整数(int8
に相当)の配列を作成する方法について確認したり、あるいは配列の要素へのアクセスや操作について掘り下げたりすることも可能です。また、この内容の理解度を確認するために簡単なクイズを試してみたい場合も、お気軽にお申し付けください。
Discussion