3

HyperSpecの #' adjoin のドキュメントを見ると、例のセクションに次のように表示されます。

(setq slist '()) =>  NIL
(setq slist (adjoin '(test-item 1) slist)) =>  ((TEST-ITEM 1))
(adjoin '(new-test-item 1) slist :key #'cadr) =>  ((TEST-ITEM 1))

代わりに、次のことを期待していました。

(adjoin '(new-test-item 1) slist :key #'cadr) =>  ((NEW-TEST-ITEM 1) (TEST-ITEM 1))

私の予想は、HyperSpec (17.2.1)の次のテキストによるものです。

オブジェクト O が、次の図にリストされている演算子 F によって、シーケンス S の各要素 Ei に対して反復的に考慮されている場合、S 内の O の存在が F によってテストされる方法を制御すると便利な場合があります。制御は、:test または :test-not 引数で指定された関数に基づいて提供されます。

そしてさらに:

オブジェクト O は Ei と直接比較できない場合があります。:key 引数が指定されている場合、これは各 Ei を引数として呼び出される 1 つの引数の関数の指定子であり、比較に使用されるオブジェクト Zi を生成します。(:key 引数がない場合、Zi は ​​Ei です。)

:key 引数で指定された関数は、O 自体では呼び出されません。ただし、関数が複数のシーケンスで動作する場合 (たとえば、set-difference で発生する場合)、O は、他のシーケンスの要素で :key 関数を呼び出した結果になります。

したがって、slist (シーケンス、S) as'((TEST-ITEM 1))と O as があり'(new-test-item 1)ます。O が隣接する必要があるかどうかを確認するために、関数#'cadrが S の要素に適用されます。最初の要素は'(test-item 1)です。したがって、そのテストは次のようになります。

(cadr '(test-item 1)) => 1

ここで、O, ,を S の E1 に( が指定されていない場合に使用される等価関数)'(new-test-item 1)で適用した結果と照合すると、結果はO が隣接していることを意味するはずです。少なくとも私はそう思います。私は何を誤解していますか?#'cadr#'eql:testfalse

4

1 に答える 1

6

これは HyperSpec のバグであり、問​​題 ADJOIN-SPECIFICATIONが CLIkiに書かれています。関連する部分は次のとおりです。

問題の説明:

CLHS は、セクション 17.2.1 2 つの引数のテストを満たすを参照して、:KEY 引数が存在する場合の ADJOIN の動作を指定します。セクション 17.2.1 ではキー関数は ITEM パラメータで呼び出されないと指定されていますが、pushnew で指定されているように ADJOIN では呼び出されるため、これは正しくありません。提案 (ADJOIN:CLARIFICATION):

交換:

test、test-not、および key は、item が list の要素と同じかどうかを判断する方法に影響します。詳細については、セクション 17.2.1 (2 つの引数のテストを満たす) を参照してください。

に:

item がすでにリストのメンバーであるかどうかは、:test または :test-not を使用した比較によって決定されます。:test または :test-not 関数の最初の引数は、:key 関数 (指定されている場合) によって返された結果であり、アイテムに適用されます。2 番目の引数は、:key 関数 (指定されている場合) によって返されるリストの要素です。:key が指定されている場合は、アイテムとリスト要素の両方からテストする部分を抽出するために使用されます。

根拠:

ADJOIN の仕様の明確化。

現在の習慣:

すべての実装は、adjoin で指定されたものではなく、pushnew で指定されたとおりに ADJOIN を実装します。

于 2014-03-12T18:20:40.377 に答える