이제는 귀찮다. yes/no 대신 y/n을 쓰자

1 minute read

(defalias 'yes-or-no-p 'y-or-n-p)

shell 종료를 하려니 물어본다. yes/no. 단어를 전부 쳐넣어야 하네. 귀찮다. y/n으로 바꾸자.

yes/no

상대적으로 중요한 동작일 경우 단어 전체를 넣도록 유도한 것 같다. 뉴비일 때는 꼬박꼬박 쳐넣었지만, 이제는 귀찮다. 좀 썼잖아? 쉽게 가자.

-p

yes-or-no-p. 끝에 -p 가 붙었다. elisp에선 술어(predicate)-p 를 붙이는 게 코딩 관례(Coding Conventions).

fset, defalias

많이 바꾼다. 어디 귀찮은 게 나 뿐이랴. 그래서 yes-or-no-p관련글을 쉽게 찾을 수 있다. 찾다보면 사용함수가 두 가지인 걸 발견할 수 있다. 어떤 곳은 fset 을 사용하고 다른 곳은 defalias 를 사용한다.

함수 이름만 보면 별칭을 만들고 싶은 거라 fset 보다는 defalias 가 적합해 보인다.

defalias 를 사용하면 뭐가 다른가? 히스토리를 기록하는 게 다르다. unload-feature 를 통해 되돌릴 수 있는 기능을 제공한다.

그래서 사용하는 입장에선 defalias피처(feature)에 사용하는게 아니라면 fset 과 별 차이가 없다.

defalias와 피처(feature)

피처는 함수와 변수 컬렉션을 의미한다. 단위는 파일. 파일에서 반 쪼개서 피처 반반 이런 거 안 된다.

;;; my-alias.el
(provide 'my-alias)

(defalias 'yes-or-no-p 'y-or-n-p)
(defalias 'sh 'shell)

my-alias라는 피처를 만들어서 편하게 치고 싶은 심볼을 정의한다. 여기서 yes-or-no-p는 emacs에서 할래 말래 물어볼 때, 사용하는 심볼이다. 반면 sh는 새롭게 정의하는 심볼.

;;; init.el
(add-to-list 'load-path "~/.emacs.d/")
(require 'my-alias)

load-path에 추가가 안 됐다면 추가해주고 require로 로드한다. require는 인자로 넘기는 피처가 로드됐는지 확인해서 그냥 편하게 사용하면 된다.

(featurep 'my-alias)
(member 'my-alias features) ;; or

둘 중 하나로 피처가 로드됐는지 확인할 수 있다.

(symbol-function 'yes-or-no-p)
;;=> y-or-n-p
(symbol-function 'sh)
;;=> shell

symbol-function으로 function cell에 있는 오브젝트를 확인할 수 있다. 리턴 값을 보니 alias가 제대로 설정됐다.

(unload-feature 'my-alias 'FORCE)

피처를 언로드한다. init.el에 정의해 종속성이 걸려 FORCE 를 빼면 실패한다.

(featurep 'my-alias)
;;=> nil
(symbol-function 'sh)
;;-> symbol's function definition is void
(symbol-function 'yes-or-no-p)
;;-> symbol's function definition is void

피처를 언로드하면 피처 안에서 defalias로 정의한 심볼이 싹 제거된다. 히스토리 기록이라길래 이전 함수 정의를 복원시키는 줄 알았다. 하지만 아니네. 그냥 함수 정의를 날려버린다. emacs에서 기본으로 정의하는 yes-or-no-p 가 날아갔다.

참고

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