왜 Lisp인가: 프로그래밍 가능한 프로그래밍 언어의 힘

왜 Lisp인가: 프로그래밍 가능한 프로그래밍 언어의 힘

Lisp는 프로그래머가 문제에 맞춰 언어를 성장시킬 수 있는 패러다임을 가능하게 합니다

Lisp는 개발자가 해결하려는 문제에 맞춰 언어 자체를 적응시킬 수 있도록 허용하기 때문에 대부분의 일반적인 프로그래밍 언어와 근본적으로 다릅니다. 문제를 미리 정의된 구문의 제약 조건에 맞추는 대신, Lisp는 프로그래머가 새로운 구조와 추상화를 생성하여, 최종 프로그램을 작성하기 전에 문제를 향해 언어를 효과적으로 성장시키는 워크플로우를 가능하게 합니다.

매크로를 통한 언어 확장성

Lisp는 그 자체 내에서 확장 가능하기 때문에 종종 "프로그래밍 가능한 프로그래밍 언어"라고 설명됩니다. 이는 주로 macro 연산자를 통해 달성되는데, 이는 C, Rust 또는 Swift와 같은 언어의 매크로와는 크게 다릅니다.

매크로 vs. 함수

함수는 실행하기 전에 인자를 평가(evaluate)하지만, Lisp 매크로는 인자를 순수한 데이터로 취급합니다. 이를 통해 매크로는 언어의 일부가 되는 완전히 새로운 구문 구조를 생성할 수 있습니다.

예를 들어, Common Lisp는 네이티브 while 루프를 제공하지 않습니다. 프로그래머는 매크로를 사용하여 이를 구현할 수 있습니다:

(defmacro while (condition &body body)
  `(loop while ,condition do
     (progn ,@body)))

매크로가 condition이나 body를 즉시 평가하지 않기 때문에, 코드를 컴파일러가 실행할 수 있는 loop 구조로 변환할 수 있습니다. 만약 이것이 함수로 구현되었다면, 인자들이 즉시 평가되어 함수가 표현식 자체가 아닌 표현식의 결과값을 받게 되므로 런타임 에러가 발생했을 것입니다.

Homoiconicity: 코드를 데이터로

Lisp의 힘은 homoiconicity에서 나옵니다. 이는 코드와 데이터가 동일한 구조, 즉 리스트(symbolic expressions 또는 s-expressions)를 사용하여 표현된다는 속성입니다.

  • Atoms: 데이터의 기본 단위 (숫자, 문자열, 심볼).
  • Lists: 원자(atoms) 또는 다른 리스트의 집합.

Lisp에서 리스트는 평가될 코드 또는 조작될 데이터로 취급될 수 있습니다. quote 연산자 (')는 인터프리터에게 리스트를 데이터로 취급하도록 지시합니다. 이러한 미묘한 차이는 Lisp 프로그램이 자신의 소스 코드를 조작할 수 있게 하여, "프로그램을 작성하는 프로그램"의 생성을 가능하게 합니다.

REPL 중심 개발과 라이브 시스템

Lisp는 컴파일하고 실행해야 하는 정적인 파일 세트가 아니라 라이브 시스템으로 작동합니다. 이 워크플로우의 핵심은 **Read-Eval-Print Loop (REPL)**입니다.

진화하는 워크플로우

전통적인 개발 방식은 작성-컴파일-실행-디버그의 사이클을 따릅니다. Lisp에서는 프로세스가 실행 중인 프로그램 그 자체입니다. 개발자는 라이브 프로세스에 직접 코드를 지속적으로 평가하며, 함수와 매크로를 즉석에서 재정의합니다. 이를 REPL-driven development라고 합니다.

라이브 시스템의 장점

Lisp 프로세스는 몇 주 동안 살아있을 수 있으므로, 프로그램은 점진적으로 진화합니다. 환경에서 재정의된 모든 심볼은 실행 중인 시스템에 즉시 반영되므로, 빈번한한번의 재시작이나 복잡한 주입 도구가 필요하지 않습니다.

DSL을 통한 확장 가능한 소프트웨어 생성

언어 확장성과 라이브 환경의 결합은 **Domain-Specific Languages (DSLs)**를 쉽게 생성할 수 있게 합니다. 도메인 특화적인 동작을 캡슐화하는 매크로를 작성함으로써, 개발자는 특정 작업에 맞춤춘 미니 언어를 만듭니다.

DSL의 실제 적용 사례

  • Web Development: 매크로를 사용하여 서버 측에서 HTML을 생성할 수 있으며, 이를 통해 사용자는 Jinja 또는 Liquid와 같은 별도의 템플릿 언어를 사용할 필요 없이 Lisp의 모든 기능을(루프, 변수 등) 활용하여 뷰를 작성할 수 있습니다.
  • Mathematical Rendering: 그래프 위의 곡선과 점을 정의하기 위해 DSL을 만들어, 복잡한 rendering logic을 단순하고 표현력이 풍부한 인터페이스 뒤에 숨길 수 있습니다.
  • Industry Examples: AutoCAD는 자동화를 위해 AutoLISP를 사용하며, Emacs는 대부분 자체 Lisp 방언언어를 사용하여 구현되어 있어, PDF 리더, 웹 브라우저, 또는 이메일 클라이언트 등으로 확장할 수 있습니다.

커뮤니티의 관점과 비판

Lisp는 그 우아함과 힘을에 대해 찬사를 받지만, practicality의 측면에서 현대적인 생태계에 대해 상당한 비판을 받기도 합니다.

Lisp에 대한 반대 의견

  • Readability and Syntax: 일부 개발자들은 과도한 괄호 사용과 전통적인 네임스페이스의 부재(일부 방언언어의 경우)가 진입 장벽이 되거나 구식 디자인의 n

  • **

  • DSL Maintenance: 비판론자들은 DSL이 상업적 환경에서 안티 패턴이 될 수 있다고 주장합니다. 문서화가 부족한 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스텀 커스ists 커텀 언어가 새로운 유지보수자가 해독하기 어려워질 수 있기 때문입니다.

  • Tooling and Ecosystem: 일부는 REPL이 많은 현대적 언어에서도 흔히 사용되지만, Lisp의 특정 장점은 현대적인 동시성 모델의 부재나 파편화된 구현체 생태계로 인해 상쇄될 수 있다고 주장합니다.

프로그래밍의 "Dark Side"

한 관점은 프로그래밍이 "Light Side" (정적 타입과 제약 조건을 통해 실수를 방지하는 것)와 "Dark Side" (매크로와 자기 수정 코드(self-modifying code)를 통해 프로그래머에게 최대의 권한을 부여하는 것) 사이의 긴장 관계 속에 존재한다고 제안합니다. Lisp는 프로그래머에게 언어 자체에 대한 절대적인 권한을 부여함으로써 궁극의 "Dark Side" 언어로 간주됩니다.

Sources