맨위로가기

이맥스 리스프

"오늘의AI위키"는 AI 기술로 일관성 있고 체계적인 최신 지식을 제공하는 혁신 플랫폼입니다.
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.

1. 개요

이맥스 리스프는 텍스트 편집기인 이맥스(Emacs)에서 사용되는 리스프(Lisp) 방언으로, 맥리스프(Maclisp)와 유사하며 Common Lisp의 영향을 받았다. 함수를 데이터로 취급하는 강력한 기능을 제공하며, 절차적 프로그래밍과 함수형 프로그래밍 방식을 지원한다. 이맥스 리스프는 동적 스코프를 기본으로 사용하며, 꼬리 재귀 최적화를 수행하지 않는 특징이 있다. 바이트 코드 컴파일을 통해 실행 속도를 향상시킬 수 있으며, cl-lib 패키지를 통해 Common Lisp의 기능을 사용할 수 있다. Emacs 24부터는 어휘적 스코프를 옵션으로 제공한다.

2. 다른 리스프 방언과의 비교

이맥스 리스프는 맥리스프(Maclisp)와 가장 밀접한 관련이 있으며, 이후 Common Lisp의 영향을 받았다.[5] 이는 명령형함수형 프로그래밍 방식을 지원한다. 리처드 스톨만은 Gosling Emacs를 GNU Emacs로 포크할 때, 함수를 데이터로 취급하는 기능을 포함한 강력한 기능 때문에 리스프를 확장 언어로 선택했다. 당시 Scheme도 존재했지만, 스톨만은 워크스테이션에서의 성능 문제와 더 쉽게 최적화할 수 있는 방언을 개발하고자 하는 의도로 이맥스 리스프를 선택했다.[6]

이맥스 리스프는 애플리케이션 프로그래밍에 사용되는 현대적인 Common Lisp 및 Scheme 방언과는 실질적으로 다르다. 이맥스 리스프의 두드러진 특징은 기본적으로 렉시컬 스코프가 아닌 동적 스코프를 사용한다는 것이다. 즉, 함수는 호출된 스코프의 지역 변수를 참조할 수 있지만, 정의된 스코프의 지역 변수는 참조할 수 없다. 최근에는 렉시컬 스코핑을 사용하도록 코드를 업데이트하려는 노력이 진행되고 있다.

2. 1. 리스프 방언 타임라인

리스프 방언 타임라인
19581960196519701975198019851990199520002005201020152020
LISP 1, 1.5, LISP 2colspan="11" |
colspan="2" |맥리스프colspan="7" |
colspan="3" |인터리스프colspan="6" |
colspan="3" |MDLcolspan="9" |
colspan="4" |Lisp Machine Lispcolspan="5" |
colspan="4" |SchemeR5RSR6RSR7RS small
colspan="4" |NILcolspan="8" |
colspan="5" |ZIL (Zork Implementation Language)colspan="7" |
colspan="5" |Franz Lispcolspan="7" |
colspan="5" |Common LispANSI 표준
colspan="5" |Le Lisp
colspan="5" |MIT Scheme
colspan="5" |XLISPcolspan="5" |
colspan="6" |Tcolspan="5" |
colspan="6" |Chez Scheme
colspan="6" |이맥스 리스프
colspan="6" |AutoLISP
colspan="6" |PicoLisp
colspan="6" |Gambit
colspan="7" |EuLisp|
colspan="7" |ISLISP
colspan="7" |OpenLisp
colspan="7" |PLT SchemeRacket
colspan="7" |newLISP
colspan="7" |GNU Guile
colspan="9" |Visual LISP
colspan="10" |Clojure
colspan="10" |Arc
colspan="10" |LFE
colspan="11" |Hy


3. 예시

이맥스 리스프는 다재다능한 텍스트 편집기를 만들기 위한 데이터 구조와 기능을 제공하는 데 목표를 두고 있다.[7] 예를 들어, 모드에 의해 정의된 문장, 단락 또는 더 높은 구문 수준에서 버퍼 텍스트를 탐색하고 수정하는 많은 기능을 제공한다.

이맥스 리스프 코드는 평가되는 즉시 적용된다. 재컴파일하거나, 이맥스를 다시 시작하거나, 구성 파일을 재해시할 필요가 없다. 코드가 이맥스 초기화 파일에 저장되면 이맥스는 다음에 시작할 때 확장을 로드한다. 그렇지 않으면 이맥스를 다시 시작할 때 변경 사항을 수동으로 다시 평가해야 한다.[7]

3. 1. 창 분할 예제

이맥스에서 편집 영역은 '버퍼'를 표시하는 여러 '창'으로 분할할 수 있다. `C-x 2` 키 바인딩을 누르면 새 창을 열 수 있는데, 이 때 이맥스 리스프 함수 `split-window-below`가 실행된다.[7] 새 창에는 보통 이전 창과 같은 버퍼가 표시된다.

다음은 새 창에 다른 버퍼를 표시하는 이맥스 리스프 코드 예제이다.

```emacs-lisp

(defun my-split-window-func ()

(interactive)

(split-window-below)

(set-window-buffer (next-window) (other-buffer)))

(global-set-key (kbd "C-x 2") #'my-split-window-func)

```

`defun` 키워드는 `my-split-window-func`라는 새 함수를 정의한다. 이 함수는 `split-window-below`를 호출하여 창을 분할하고, `set-window-buffer`와 `next-window`, `other-buffer`를 통해 새 창에 다른 버퍼를 표시한다. `global-set-key`는 "C-x 2" 키 입력을 이 함수에 연결한다.[7]

이 코드는 어드바이스 기능을 사용하여 작성할 수도 있다. 어드바이스를 사용하면 키 바인딩을 변경하지 않고도 기존 함수를 둘러싸는 래퍼를 만들 수 있다.[7]

3. 2. 어드바이스(Advice) 기능

이맥스 리스프는 기존 함수를 둘러싸는 래퍼를 만들 수 있게 해주는 '어드바이스(Advice)' 기능을 제공한다.[7] 이 기능을 사용하면 사용자가 자체 함수를 정의하는 대신, 기존 함수의 동작을 변경할 수 있다.

예를 들어, 사용자가 기본 C-x 2 키 바인딩을 통해 새 창을 열 때, 새 창에 이전 창과 동일한 버퍼가 아닌 다른 버퍼를 표시하도록 만들 수 있다. `defadvice` 매크로를 사용하여 `split-window-below` 함수 실행 후에 다음 코드를 실행하도록 할 수 있다.

```emacs-lisp

(defadvice split-window-below

(after my-window-splitting-advice first () activate)

(set-window-buffer (next-window) (other-buffer)))

```

이 코드는 `split-window-below` 함수가 실행된 *후* (`after`)에 `my-window-splitting-advice`라는 이름의 사용자 정의 코드를 실행한다. 이 코드는 새 창(`next-window`)의 버퍼를 다른 버퍼(`other-buffer`)로 설정한다. 어드바이스는 원래 함수 *전*에 실행되거나, 원래 함수를 감싸거나, 어드바이스 결과에 따라 원래 함수를 조건부로 실행하도록 지정할 수도 있다.

이맥스 24.4부터는[8] `defadvice` 매크로 대신 `advice-add` 함수를 사용하는 새로운 방식이 도입되었다.[9] 새로운 시스템을 사용하면 위와 동일한 기능을 다음과 같이 구현할 수 있다.

```emacs-lisp

(defun switch-to-next-window-in-split ()

(set-window-buffer (next-window) (other-buffer)))

(advice-add 'split-window-below :before #'switch-to-next-window-in-split)

```

이 코드는 `split-window-below` 함수가 실행되기 *전* (`:before`)에 `switch-to-next-window-in-split` 함수를 실행한다.

4. 소스 코드

이맥스 리스프 코드는 보통 "`.el`" 확장자를 가진 텍스트 파일로 파일 시스템에 저장된다.[1] 사용자 초기화 파일은 예외적으로 "`.emacs`", "`.emacs.el`", ".emacs.d/init.el" 등으로 나타난다.[1] 이맥스 프로그램의 인터프리터는 함수와 변수를 읽고 구문 분석하여 메모리에 저장하며, 이들은 편집기나 구성 파일을 다시 시작하거나 다시 로드하지 않고도 자유롭게 수정 및 재정의할 수 있다.[1]

이맥스의 많은 기능은 필요할 때만 로드되는 패키지 또는 라이브러리 형태로 제공된다.[1] 예를 들어, 프로그램 소스 코드에서 키워드를 강조 표시하는 라이브러리와 테트리스 게임을 하는 라이브러리가 있다.[1] 각 라이브러리는 하나 이상의 이맥스 리스프 소스 파일을 사용하여 구현된다.[1]

4. 1. 원시 함수

Emacs 개발자는 특정 함수를 C로 작성하는데, 이를 ''원시 함수''(''내장 함수'' 또는 ''subrs''라고도 한다)라고 부른다.[1] 원시 함수는 Lisp 코드에서 호출할 수 있지만, 수정하려면 C 소스 파일을 편집하고 다시 컴파일해야 한다.[1] GNU Emacs에서 원시 함수는 외부 라이브러리로 사용할 수 없으며, Emacs 실행 파일의 일부이다.[1] XEmacs에서는 운영 체제의 동적 링크 지원을 사용하여 이러한 원시 함수를 런타임에 로드할 수 있다.[1] 원시 함수는 Emacs Lisp에서 사용할 수 없는 외부 데이터 및 라이브러리에 접근해야 하거나, C와 Emacs Lisp 간의 속도 차이가 중요할 만큼 자주 호출될 때 작성된다.[1]

하지만 C 코드의 오류는 세그멘테이션 오류나 편집기를 충돌시키는 더 미묘한 버그를 쉽게 유발할 수 있다. 또한 Emacs Lisp 가비지 수집기와 올바르게 상호 작용하는 C 코드를 작성하는 것은 오류가 발생하기 쉽다. 따라서 원시 함수로 구현된 함수의 수는 필요한 최소한으로 유지된다.[1]

5. 바이트 코드

'바이트 코드 컴파일'은 이맥스 리스프 코드의 실행 속도를 향상시킬 수 있다. 이맥스에는 이맥스 리스프 소스 파일을 바이트 코드라는 특수한 표현으로 변환할 수 있는 컴파일러가 포함되어 있다. 이맥스 리스프 바이트 코드 파일은 파일 이름 확장자 "`.elc`"를 갖는다. 소스 파일에 비해 바이트 코드 파일은 더 빠르게 로드되고 실행되며, 더 적은 디스크 공간을 차지하고, 로드 시 더 적은 메모리를 사용한다.

바이트 코드는 여전히 원시 함수보다 느리게 실행되지만, 바이트 코드로 로드된 함수는 쉽게 수정하고 다시 로드할 수 있다. 또한, 바이트 코드 파일은 플랫폼에 독립적이다. 이맥스와 함께 배포되는 표준 이맥스 리스프 코드는 바이트 코드로 로드되지만, 사용자의 참조를 위해 일치하는 소스 파일도 일반적으로 제공된다. 사용자가 제공하는 확장 기능은 크기가 크거나 계산 집약적이지 않기 때문에 일반적으로 바이트 코드 컴파일되지 않는다.

6. 언어 기능

이맥스 리스프는 맥리스프(Maclisp)와 가장 관련이 깊으며, 이후 Common Lisp의 영향을 받았다.[5] 명령형함수형 프로그래밍 방식을 모두 지원한다. 리스프는 EINE 및 ZWEI와 같은 이맥스 파생 제품의 기본 확장 언어였다. 리처드 스톨만은 Gosling Emacs를 GNU Emacs로 포크했을 때, 함수를 데이터로 취급하는 기능을 포함한 강력한 기능 때문에 리스프를 확장 언어로 선택했다. 당시 Common Lisp 표준은 아직 제정되지 않았고, Scheme이 존재했지만, 스톨만은 워크스테이션에서 성능이 떨어져 사용하지 않기로 결정하고, 더 쉽게 최적화할 수 있는 방언을 개발하고자 했다.[6]

이맥스에서 사용되는 리스프 방언은 애플리케이션 프로그래밍에 사용되는 보다 현대적인 Common Lisp 및 Scheme 방언과 실질적으로 다르다. 이맥스 리스프의 두드러진 특징은 기본적으로 렉시컬이 아닌 동적 스코프를 사용한다는 것이다. 즉, 함수는 함수가 호출된 스코프의 지역 변수를 참조할 수 있지만, 정의된 스코프의 지역 변수는 참조할 수 없다. 최근에는 렉시컬 스코핑을 사용하도록 코드를 업데이트하려는 노력이 진행되고 있다.

"cl-lib" 패키지는 Common Lisp의 상당 부분을 구현하며, 기존 "cl" 패키지를 대체한다. "cl-lib" 패키지는 Emacs Lisp 스타일 가이드라인을 따르며, "cl-" 접두사를 사용하여 이름 충돌을 피한다. Emacs 24에서는 정적 스코프를 사용할 수 있게 되었다.

6. 1. 꼬리 재귀 최적화

Emacs Lisp는 다른 일부 Lisp 구현과 달리 꼬리 호출 최적화를 수행하지 않는다.[10] 이 때문에 꼬리 재귀는 스택 오버플로우를 일으킬 수 있다.

6. 2. 이식성

apel 라이브러리는 폴리실라비(polysylabi) 플랫폼 브리지의 도움을 받아 이식 가능한 Emacs Lisp 코드를 작성하는 데 도움을 준다.

6. 3. 함수 네임스페이스

이맥스 리스프는 Lisp-2와 유사하게 함수 네임스페이스가 다른 변수에 사용하는 네임스페이스와 별개이다.[11]

7. 동적 스코프에서 어휘적 스코프로의 전환

이맥스 리스프는 맥리스프(Maclisp)와 마찬가지로 동적 스코프를 사용하며, 버전 24부터 정적(또는 어휘적) 스코프를 옵션으로 제공한다.[12] 파일 로컬 변수 `lexical-binding`을 설정하여 어휘적 스코프를 활성화할 수 있다.[13][14]

원래 동적 스코핑은 최적화를 위한 의도였다. 당시에는 어휘적 스코핑이 흔하지 않았고 성능도 불확실했다. 컴퓨터 과학자 올린 시버스(Olin Shivers)에 따르면, 리처드 스톨만(RMS)은 이맥스 리스프에 동적 스코핑을 사용한 이유로 "어휘적 스코핑은 너무 비효율적"이라고 답했다고 한다.[16] 또한 동적 스코핑은 사용자 정의에 더 큰 유연성을 제공하는 목적도 있었다.

그러나 동적 스코핑에는 몇 가지 단점이 있었다. 첫째, 서로 다른 함수 내 변수 간의 의도하지 않은 상호 작용으로 인해 대규모 프로그램에서 버그가 쉽게 발생할 수 있었다. 둘째, 동적 스코핑 하에서 변수에 접근하는 것은 일반적으로 어휘적 스코핑 하에서보다 느렸다.[17] 이러한 단점을 해결하기 위해 어휘적 스코프로의 전환이 이루어졌다.

참조

[1] 웹사이트 Byte compiling Emacs Lisp https://www.gnu.org/[...] 2024-06-14
[2] 웹사이트 Compilation of Emacs Lisp to native code https://www.gnu.org/[...] 2024-06-14
[3] 편지 https://www.cs.cmu.e[...] 1981-12-18
[4] 간행물 Ad for CCA EMACS 1984-12
[5] 문서
[6] 문서 "My Lisp Experiences and the Development of GNU Emacs" https://www.gnu.org/[...]
[7] 웹사이트 Re: [Emacs-diffs] /srv/bzr/emacs/trunk r111086: gmm-utils.el (gmm-flet https://lists.gnu.or[...] Lists.gnu.org 2012-12-05
[8] 웹사이트 NEWS.24.4 https://www.gnu.org/[...]
[9] 웹사이트 Porting old advice https://www.gnu.org/[...]
[10] 웹사이트 Appendix C Porting Common Lisp https://www.gnu.org/[...] Gnu.org 2019-10-28
[11] 웹사이트 Google Groups https://groups.googl[...]
[12] 웹사이트 Emacs 24.1 released http://lists.gnu.org[...] Lists.gnu.org 2013-08-18
[13] 웹사이트 Lexical binding http://lists.gnu.org[...] Lists.gnu.org 2011-04-01
[14] 웹사이트 Dynamic Binding Vs Lexical Binding http://www.emacswiki[...] EmacsWiki 2013-05-17
[15] 웹사이트 Obsolete Lexical Binding https://www.gnu.org/[...] GNU Press 2021-05-27
[16] 웹사이트 T http://people.csail.[...] People.csail.mit.edu 2013-08-18
[17] 서적 Process https://books.google[...] Walter de Gruyter 2009-06-02
[18] 웹사이트 Emacs Lisp https://www.gnu.org/[...] FSF 2023-09-27
[19] 문서
[20] 문서 "My Lisp Experiences and the Development of GNU Emacs" http://www.gnu.org/g[...]
[21] 편지 https://www.cs.cmu.e[...] 1981-12-18



본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.

문의하기 : help@durumis.com