2016-04-30-01-CL-STLのシンボル衝突問題について
>> Site top >> weblog >> 月別アーカイブ >> 2016年04月のlog >> 2016-04-30-01-CL-STLのシンボル衝突問題について
最終更新日付:2016/04/30 01:00:00
CL-STLのシンボル衝突問題について
2016 年 04 月 30 日
さて、CL-STL のシンボル衝突問題。CL-STL は CL のシンボルといくつも衝突しているため、これまでは use-package しない前提になっていた。そのために全てのシンボルに stl: と付加せざえるをえなかったわけだ。
で、今回、衝突に対処するためのパッケージの機能をちゃんとおさらいして、どうにかしようと考えた。
とりあえずテストで書いてみたのは、以下の my-test パッケージ。こいつは foo と、あろうことか cons というシンボルを使用し、エクスポートしている(ほとんど冒涜だね!)。ユーザー定義パッケージは通常 common-lisp パッケージを use するから、この時点で cl:cons とバッティングする。それを解決するのが shadow だ。これによって、my-test パッケージ内部では cons といえば my-test:cons になり、標準の cons を使いたければ明示的に cl:cons と記述しなければならなくなる。
;;;;my-test.lisp (defpackage :my-test (:use :common-lisp) (:export :foo :cons) (:shadow :cons)) (in-package :my-test) (defun foo () :foo-from-my-test-package) (defun cons () :cons-from-my-test-package)
これは問題なくロードできるし使用もできる。ただ、これを use-package しようとしなければ、だ。use-package すると以下のように問題が起きる。これは use-package しようとした common-lisp-user パッケージの側で衝突が発生するからだ。
* (load "D:/tmp/my-test.lisp") T * (use-package :my-test) ; USE-PACKAGE #<PACKAGE "MY-TEST"> causes name-conflicts in ; #<PACKAGE "COMMON-LISP-USER"> between the following symbols: ; MY-TEST:CONS, COMMON-LISP:CONS ; [Condition of type NAME-CONFLICT]
CL-STL の現状は上記と同じだ。remove や count といったシンボルが標準と衝突している(実際にはもっとたくさんある)。パッケージシステムがこのような仕様になっていることに文句を言っても仕方がないし、それなりの理由もある。色々やってみて、とりあえずは以下の方法しかないと判断した(間違っていたら誰か教えてほしい)。
基本的な考え方は、緩衝材になるパッケージを作成し、衝突しないシンボルだけを取り込めるようにすることだ。以下のように、my-test-user パッケージを作成し、cons 以外のシンボルを export する。
;;;;my-test.lisp (defpackage :my-test-user (:use :my-test) (:export :foo)) (in-package :my-test-user)
これで common-lisp-user パッケージから両方のパッケージをロードし、my-test-user を use-package すればよい。 my-test:foo は取り込まれるから修飾なしで使用できるし、修飾なしで使用した cons は CL 標準のモノになる。my-test の foo を使いたければ、パッケージ名で修飾する必要がある、と。
* (load "D:/tmp/my-test.lisp") T * (load "D:/tmp/my-test-user.lisp") T * (use-package :my-test-user) T * (cons :a :b) (:A . :B) * (my-test:cons) :CONS-FROM-MY-TEST-PACKAGE * (foo) :FOO-FROM-MY-TEST-PACKAGE
ちなみに、CL-STL は現時点で 284個のシンボルをエクスポートしており、そのうち以下の 37個が common-lisp パッケージと衝突するために shadow されている。
- array
- bit-and
- bit-or
- bit-xor
- count
- count-if
- equal
- fill
- find
- find-if
- find-if-not
- first
- function
- get
- list
- map
- max
- merge
- min
- mismatch
- pop
- push
- remove
- remove-copy
- remove-copy-if
- remove-if
- replace
- replace-copy
- replace-copy-if
- reverse
- search
- second
- set
- set-difference
- sort
- stable-sort
- vector
つまり、前述の my-test-user 同様に cl-stl-user パッケージを導入する方法によって、247 種類のシンボルは stl: で修飾しなくて済むようになるわけだ。上記 37個のみ、stl:replace みたいな感じで修飾することになる。
ここで、37個をさらに減らすことを考える。これまで、Lisp の慣習に従ってシンボル名には - を使ってきたが、あえて STL にあわせるかたちに変更し、_ を使うようにするのだ。つまり、find-if でなく find_if にする。これによって、37個から以下の 24個にまで減らすことができる。
- array
- count
- equal
- fill
- find
- first
- function
- get
- list
- map
- max
- merge
- min
- mismatch
- pop
- push
- remove
- replace
- reverse
- search
- second
- set
- sort
- vector
上記のうち、5個はコンテナ名だ。大体において (new stl:vector) とかする場合にしか使用しないからこれはあまり問題にならないだろう。残る19個は、アルゴリズムまたはクラスのメソッドだ。これは残念だが明示的修飾をせざるをえないというのがひとまずのところ。
さて、とりあえずはこれでイケるのかどうか、実際に修正して確認する作業をしなければならない。その結果については後日報告ということで。
コメント
このページのタグ
Page tag : STLとその移植
Copyright(C) 2005-2021 project-enigma.
Generated by CL-PREFAB.