pushnew — 중복 없이 리스트 앞에 넣기
pushnew — 중복 없이 리스트 앞에 넣기
리스트에 요소를 넣되, 이미 같은 값이 있으면 넣지 않으려 할 때가 있어요. pushnew는 매크로로, item이 리스트에 없을 때만 앞에 추가하고, 있으면 그대로 둬요.
시그니처
pushnew item place &key key test test-not
=> new-place-value
본문
인자와 값
item— 객체예요.place— place이고, 그 값은 proper list예요.test— 두 인자를 받아 일반화된 불리언을 돌려주는 함수의 지정자(designator) 예요.test-not— 두 인자를 받아 일반화된 불리언을 돌려주는 함수의 지정자예요.key— 한 인자를 받는 함수의 지정자, 또는nil이에요.new-place-value— 리스트로,place의 새 값이에요.
설명
item이 place에 저장된 리스트의 어떤 기존 요소와 같은지 검사해요. 같지 않으면 item을 리스트 앞에 붙이고, 새 리스트를 place에 저장해요.
place에 저장될 새 리스트를 돌려줘요.
item이 place의 리스트에 이미 속해 있는지는 :test 또는 :test-not을 사용한 비교로 결정돼요. :test 또는 :test-not 함수의 첫 번째 인자는 item, 두 번째 인자는 (:key 함수가 주어졌다면 그것이 돌려준) place의 리스트 요소예요.
:key가 주어지면, adjoin에서처럼 item과 리스트 요소에서 검사할 부분을 추출하는 데 쓰여요.
:key 함수의 인자는 place에 저장된 리스트의 요소예요. :key 함수는 보통 그 리스트 요소의 일부를 돌려줘요. :key가 주어지지 않았거나 nil이면 리스트 요소 자체가 쓰여요.
place의 부분 폼(subform) 평가에 대한 내용은 Section 5.1.1.1 (Evaluation of Subforms to Places)을 참고하세요.
item이 이미 place가 가진 리스트의 요소인 상황에서 실제로 place의 저장 폼을 실행하는지 여부는 구현에 따라 달라요(implementation-dependent).
예제
(setq x '(a (b c) d)) => (A (B C) D)
(pushnew 5 (cadr x)) => (5 B C)
x => (A (5 B C) D)
(pushnew 'b (cadr x)) => (5 B C)
x => (A (5 B C) D)
(setq lst '((1) (1 2) (1 2 3))) => ((1) (1 2) (1 2 3))
(pushnew '(2) lst) => ((2) (1) (1 2) (1 2 3))
(pushnew '(1) lst) => ((1) (2) (1) (1 2) (1 2 3))
(pushnew '(1) lst :test 'equal) => ((1) (2) (1) (1 2) (1 2 3))
(pushnew '(1) lst :key #'car) => ((1) (2) (1) (1 2) (1 2 3))
Side Effects
place의 내용이 수정될 수 있어요.
Notes
(pushnew item place :test p)의 효과는 다음 코드와 대략 같아요:
(setf place (adjoin item place :test p))
다만 place의 부분 폼들은 한 번만 평가되고, item은 place보다 먼저 평가된다는 차이가 있어요.
더 알아보기
push— 리스트 앞에 넣기adjoin— 중복 없이 추가- Section 5.1 (Generalized Reference) — 일반화된 참조