ACONS — 연관 리스트에 새 항목 추가

ACONS — 연관 리스트에 새 항목 추가

ACONS는 함수예요. 연관 리스트(association list)에 새 항목을 하나 추가할 때 쓰죠. 이 함수를 처음 접하면 "리스트에 항목을 더하는 건데 왜 cons를 두 번 쓰지?"라는 생각이 들 수 있는데, 연관 리스트의 항목 자체가 (key . datum) 형태의 cons 쌍이라서 그래요. 즉 항목 하나를 만들 cons와, 그 항목을 맨 앞에 매달 cons가 각각 필요하거든요.

출처: CLHS Function ACONS

본문

시그니처는 이렇게 생겼어요.

acons key datum alist => new-alist

인자는 세 개를 받아요.

  • key — 객체. 새 항목의 키가 돼요.
  • datum — 객체. 새 항목의 값이 돼요.
  • alist — 연관 리스트.

그리고 새로운 연관 리스트인 new-alist를 돌려주죠.

동작은 간단해요. cdr이 alist인 새 cons를 만들고, 그 cons의 car 자리에 또 다른 새 cons를 얹는데 그 cons의 car가 key, cdr이 datum이에요. 쉽게 말하면 (key . datum)이라는 항목을 alist 맨 앞에 하나 더해 준다고 보면 돼요.

예제로 확인해 볼게요.

(setq alist '()) => NIL
(acons 1 "one" alist) => ((1 . "one"))
alist => NIL

acons는 새 리스트를 돌려줄 뿐 원본 alist는 바꾸지 않아요. 그래서 위에서 alist가 여전히 NIL인 거죠. 항목을 누적하려면 계속 그 결과를 다시 받아야 해요.

(setq alist (acons 1 "one" (acons 2 "two" alist))) => ((1 . "one") (2 . "two"))
(assoc 1 alist) => (1 . "one")
(setq alist (acons 1 "uno" alist)) => ((1 . "uno") (1 . "one") (2 . "two"))
(assoc 1 alist) => (1 . "uno")

마지막 예제를 보면 알 수 있듯, acons는 중복을 검사하지 않아요. 키 1이 이미 있어도 그냥 맨 앞에 새 항목을 추가하고, assoc는 가장 먼저 만나는 항목을 돌려주기 때문에 최근에 추가한 (1 . "uno")를 반환해요.

사실 이 함수는 다음처럼 cons를 두 번 쓰는 것과 완전히 같아요.

(acons key datum alist) == (cons (cons key datum) alist)

부수 효과는 없어요. 연관 리스트 이후로는 assocpairlis 같은 함수와 자주 함께 쓰이니 같이 알아두면 좋아요.