1 minute read

<#orgmode org block 배경 색상> 바꾸면서 배웠다. emacs lisp에서 backquote를 처음 써봤다.

(custom-theme-set-faces
 'solarized-light
 '(org-block ((t (:background "#eee8d5"))))
 '(org-block-begin-line ((t (:background "#eee8d5"))))
 '(org-block-end-line ((t (:background "#eee8d5")))))

리팩토링 전 코드다.

(defconst my/solarized-base2 "#eee8d5")
(custom-theme-set-faces
 'solarized-light
 '(org-block ((t (:background my/solarized-base2))))
 '(org-block-begin-line ((t (:background my/solarized-base2))))
 '(org-block-end-line ((t (:background my/solarized-base2)))))

컬러값을 상수로 뺐다. evaluation 해보니 실패.

(wrong-type-argument stringp my/solarized-base2)

이런 에러가 난다.

’ 문자는 quote 특수 형식(special form)을 만들어 준다. 즉, ’foo 표현식(expression)은 (quote foo) 표현식과 같다.

그럼 quote는 어떤 역할을 하는가? 우선 emacs lisp에서 리스트를 evaluation 하는 방식을 알아야 한다. 리스트를 evaluation 하면 리스트 첫 번째 원소(element)를 함수로 호출하고 나머지를 인자로 넘긴다.

(org-block ((t (:background "#eee8d5"))))

그냥 이렇게 쓰면 ((t (:background "#eee8d5"))) 인자로 org-block 함수를 호출한다. 함수 호출 안 하고 통째로 넘기고 싶다면? 그럴 때, quote를 사용한다.

'(org-block ((t (:background "#eee8d5"))))
;;=> (org-block ((t (:background "#eee8d5"))))

evaluation 하면 함수를 호출하는 게 아니라 quote만 날아간다. evaluation 한 번 방지권이다. 까방권 한 번 획득한 거랑 비슷하다.

'(org-block ((t (:background my/solarized-base2))))
;;=> (org-block ((t (:background my/solarized-base2))))

이제 에러가 왜 났는지 보인다. 이 리스트를 인자로 받은 함수에서는 my/solarized-base2 심볼에 뭐가 바인딩 됐는지 찾질 못한다. 함수로 evaluation을 하는 건 방지해야겠으니 quote는 써야 한다. 대신 my/solarized-base2 변수는 evaluation을 해서 “#eee8d5” 문자열이 들어갔음 좋겠다.

함수로 evaluation을 방지하는데, 일부분은 evaluation을 하고 싶다. 이럴 때는 backquote를 사용하면 된다.

`(org-block ((t (:background ,my/solarized-base2))))
;;=> (org-block ((t (:background "#eee8d5"))))

, 문자를 앞에 붙인 심볼은 evalution을 한다.

(defconst my/solarized-base2 "#EEE8D5")
(custom-theme-set-faces
 'solarized-light
 `(org-block
   ((t (:background ,my/solarized-base2))))
 `(org-block-begin-line
   ((t (:background ,my/solarized-base2))))
 `(org-block-end-line
   ((t (:background ,my/solarized-base2)))))

최종 결과물이다. 상수로 빼고 싶다는 욕구 덕에 backquote를 배우네.

C-x C-s C-x C-c