Emacs Lisp에서 인용된 리스트 요소들 현실화(?) 하기

Emacs // 2024년 06월 25일 작성

작은따옴표 글에서 정리했다시피 Emacs Lisp에서 인용(quote) 즉 작은따옴표(') 등을 이용해 리스트를 표현하면 내부의 값들이 입력된 그대로 들어가 있게 된다. 예를 들자면 아래와 같다.

(defun doubled (v)
  (* v 2))

(setq mylist '((doubled 2) (doubled 4) (doubled 8)))

;; mylist = ((doubled 2) (doubled 4) (doubled 8))

이 경우 예시 하단의 주석에서 처럼 mylist에는 (2 4 8)과 같은 값으로 구성된 리스트가 아니라 각 요소로 지정된 함수가 실행되기 전 상태로 그대로 구성되어 있는 모습을 볼 수 있다.

의도에 따라 다르겠지만, 만약 각 요소에 배정된 명령이 실행된 값으로 리스트를 구성하고자 한다면 어떻게 해야 할까? 왜냐하면 이런 리스트의 요소들은 하나씩 꺼내서 eval로 돌려보지 않으면 실제 값을 알 수가 없으니 말이다.

해결하기

이럴 때를 위해 역따옴표(`)와 쉼표(,) 기호를 활용할 수 있다. 역따옴표도 작은따옴표과 같이 인용(quote) 용도이며 리스트를 구성할 때 작은따옴표 대신 동일하게 사용할 수 있으나 쉼표와 조합되면 조금 특수한 능력을 발휘할 수 있다.

(defun doubled (v)
  (* v 2))

(setq mylist `(,(doubled 2) ,(doubled 4) ,(doubled 8)))

;; mylist = (4 8 16)

이렇게 역따옴표로 구성되는 각 요소들은 앞에 쉼표가 붙어있는 경우 원본 코드가 아닌 그 코드가 실행(eval)된 형태로 구성된다.

앞서 이야기 했다시피 쉼표가 앞에 붙은 요소만 실행되며 따라서 일부만 실행되기 전의 값으로 구성하는 것도 가능하다. 예를 들어 아래와 같이 가운데 요소에서만 쉼표를 빼보자.

(setq mylist `(,(doubled 2) (doubled 4) ,(doubled 8)))

;; mylist = (4 (doubled 4) 16)

이런 식으로 역따옴표로 구성한 리스트에서 쉼표가 빠진 요소는 실행되기 전의 코드로 그대로 리스트에 포함된다. 즉 역따옴표는 쉼표를 안 쓰면 기존 작은따옴표를 이용한 인용과 동일하게 동작한다.

대안

인용(quote)과 리스트 함수(list)가 무엇이 다른지 알고 있다면 다른 선택지를 선택할 수도 있다. 인용 형식이 아니라 list 함수를 이용해 구성하면 알아서 실행된 값을 리스트 구성에 그대로 이용할 수 있기 때문이다.

(setq mylist (list (doubled 2) (doubled 4) (doubled 8)))

;; mylist = (4 8 16)

다만 이 경우는 직접 리스트를 구성할 수 있는 경우일 테고 다른 함수의 결과에서 리스트를 받아와야 할 때는 이런 경우가 아닐 수도 있다. 따라서 역따옴표와 쉼표를 활용하는 방법은 꼭 알아둬야 할 지도 모른다.

관련된 글들