不完全文字列

昨日の make-byte-string の項で出てきた #*”aaaaa” というのは不完全文字列(incomplete string)というものらしい。#*”…” というのが不完全文字列のリテラルね。

文字列について – Gauche – A Scheme Implementation から引用すると、

不完全文字列

全てのバイト列が可変長エンコーディングとして正しく解釈できるわけではない。 定義されていないコードポイントを指している場合はまだ可変長文字列として扱えるが、 そのエンコーディングではどうにも解釈しようの無いバイトシーケンスというのが 外部から入って来る可能性がある。

Gaucheではこのような文字列をincomplete stringと呼び、そのようにマークされる。 文字列操作系の関数は、incomplete stringを可能な限りあたかも1バイト固定長文字列のように扱う。 incomplete stringとcomplete stringが接合された場合、 結果はincomplete stringになる。

要するに、文字として解釈できない可能性のある文字列(バイト列)を不完全文字列と呼ぶようだ。

文字列が不完全文字列かどうかは string-incomplete? で判断できる。

gosh> (string-incomplete? "abc")
#f
gosh> (string-incomplete? #*"abc")
#t

フツウの文字列 “abc” では #f が、不完全文字列 #*”abc” では #t が返ってきた。なるほど。

「外部から入って来る」というのは、例えばコマンドライン引数なんかだろうか。

(define main
  (lambda (args)
    (print (string-incomplete? (cadr args)))))
takatoh@nightschool $ gosh string-incomplete.scm foo
#f

あれ、#f が返ってきた。てことは不完全文字列じゃないってことだ。
ファイルから入力した場合はどうだろう?

(define main
  (lambda (args)
    (print (string-incomplete? (call-with-input-file (cadr args) port->string)))))
takatoh@nightschool $ gosh string-incomplete2.scm input.txt
#f

これも #f だ。
どういう時に不完全文字列になるんだろう?