0

のこのコードの出力に矛盾があることに気付きましたClisp:

(defvar str "Another")
(setf (char str 3) #\!)

repl から実行すると、目的の結果が得られます。

[1]> (defvar str "Another")
STR
[2]> (setf (char str 3) #\!)
#\!
[3]> str
"Ano!her"
[4]>

ただし、スクリプトから実行すると、読み取り専用文字列の変更に関する警告が表示されます。

*** - Attempt to modify a read-only string: "Another"

このコードを実行すると、次のエラーが発生しました。

(print (do ((str "foobar")
            (i 0 (+ i 1)))
           ((= i (length str)) str)
         (setf (char str i) #\!)))

ブロックが終了するとバインディングが消えるときに、文字列を作成するポイントは何ですかread-only(これは と同じであると想定しています)。immutable

そして、なぜ 2 つの出力が一致しないのでしょうか?

最後に、それをオフにする方法はありますか?警告が特に役立つとは思いません。

4

1 に答える 1

3

解決

まず第一に、あなたが見ているのはerrorではなくwarningです。

次に、無効にすることはできませんが、不変の文字列をコピーすることで回避できます。

(print (do ((str (copy-seq "foobar"))
            (i 0 (+ i 1)))
           ((= i (length str)) str)
         (setf (char str i) #\!)))

動機

一部のデータが不変になる理由は、Web 上でよく議論されているトピックです。

基本的な理由は次のとおりです。

  • マルチスレッド環境での安全性と
  • より良いコンパイラ

正当化

マニュアルに従って:

読み取り専用データを変更しようとすると、エラーが発生します。ファイルから読み込まれたプログラム テキストと引用符で囲まれた定数は、読み取り専用データと見なされます。このチェックは、cons、他の種類の配列、およびユーザー定義のデータ型ではなく、文字列に対してのみ実行されます。

これは、 ANSI CL 仕様で明示的に許可されています。

実装は、不変オブジェクトまたはセルを変更しようとする試みを検出する必要はありません。そのような変更を試みた場合の結果は未定義です

于 2013-11-14T16:13:45.500 に答える