#:g1: (coerce "foo" 'cons)は合法か否か

Posted 2020-10-27 16:47:47 GMT

自作のライブラリで、(coerce "foo" 'cons)や、(coerce "" 'null)のようなコードがAllegro CLでエラーになるので、おやもしかして処理系依存だったかと思いANSI規格を確認してみましたが、

sequence

If the result-type is a recognizable subtype of list, and the object is a sequence, then the result is a list that has the same elements as object.

——ということなので、合法のようです。

ちょっと趣味的にAllegro CL 4.3(1996)で確認してみましたが、同様のエラーのようです。
そうなると時代的にCLtL1、CLtL2あたりでははっきり決まっていなかったかもしれないので確認してみましたが、明記されたのはANSI CL規格以降のようです。

無駄に深追いしてみる

とりあえず、Allegro CLのcoercedisassembleしてみると、excl::vector-to-list*という下請けに渡していることが分かります。

1023: 89 da       movl  edx,ebx
1025: 3b 56 26    cmpl  edx,[esi+38]     ; LIST
1028: 0f 85 1e 02 jnz   1576
      00 00 
1034: 8b 45 dc    movl  eax,[ebp-36]     ; EXCL::LOCAL-0
1037: 89 7d f0    movl  [ebp-16],edi
1040: c9          leave
1041: 8b 5e 2a    movl  ebx,[esi+42]     ; EXCL::VECTOR-TO-LIST*

このexcl::vector-to-list*自体は、適切にリストに変換できるようですが、前段では、consnullも出てこずにlistとしか比較していないので、すりぬけてエラーになっているように見えます。

(excl::vector-to-list* "")
→ NIL

(excl::vector-to-list* "foo")(#\f #\o #\o)

listのサブタイプはconsnull以外にも複合した指定があるので、別途サブタイプの判定をきっちりしないと

(coerce "foo" '(cons (eql #\f) (cons (eql #\o) (cons (eql #\f) *))))

のようなものを判定できなさそうです。
ちなみに上記は、LispWorksではエラーになりますが、SBCLではエラーになりません(SBCLのバグもみつけてしまったか?)

バグ報告

Allegro CLへのバグはどこに報告したら良いのかと探してみましたが、報告の仕方の解説ページがあったので、こちらに沿って報告してみました。

まとめ

Allegro CL 4.3(1996)でも同様なので、Allegro CL(ExCL)誕生時(1986)からこの仕様で来たような気がしないでもありません。
果してバグ認定されるのか、はたまたAllegro CLの仕様であるとして修正されないのか。

ちなみに、mapも変なところがありますが、話がややこしくなるので、今回は報告を見送りました。

#+Allegro
(map 'null #'identity "foo")
→(#\f #\o #\o)


HTML generated by 3bmd in LispWorks Personal Edition 7.1.2

comments powered by Disqus