Scheme은 함수형 프로그래밍 스타일을 촉진하고 간단하고 깔끔한 구문을 강조하기 위해 설계된 Lisp 프로그래밍 언어의 미니멀리스트 방언입니다. 괄호의 사용, 강력한 매크로 시스템, 재귀 및 일급 절차에 대한 강한 강조가 특징입니다. 이 언어는 함수형 프로그래밍 패러다임을 장려하며 함수형, 명령형 및 논리 프로그래밍을 포함한 여러 프로그래밍 기법을 지원합니다.
Scheme은 1970년대에 매사추세츠 공과대학교(MIT)의 Gerald Jay Sussman과 Guy L. Steele Jr.에 의해 만들어졌습니다. 원래의 Lisp 언어가 시간이 지남에 따라 복잡해진 것을 단순화하고 개선하기 위한 시도로 개발되었습니다. Scheme의 동기는 구현과 교육이 더 쉬우면서도 복잡한 아이디어를 표현할 수 있을 만큼 강력한 언어를 만드는 것이었습니다.
수년에 걸쳐 Scheme은 다양한 수정 및 표준화 노력을 거쳤습니다. 이 표준 중 가장 주목할 만한 것은 언어와 그 기능을 공식화한 RnRS(개정n 보고서)입니다. 이후 Scheme 커뮤니티는 언어를 계속 발전시켜 R6RS 및 R7RS와 같은 새로운 표준을 도입하여 새로운 기능과 개선을 이루었습니다.
현재 Scheme은 그 우아함과 깔끔한 구문 덕분에 특히 컴퓨터 과학 교육에서 학문적 환경에서 인기가 있습니다. 그 영향은 많은 현대 프로그래밍 언어와 패러다임에서 볼 수 있습니다. Scheme은 종종 함수형 프로그래밍 커뮤니티와 연관되며, 그 원칙을 바탕으로 기능을 확장한 Clojure 및 Racket과 같은 언어에 영감을 주었습니다.
Scheme은 코드가 접두사 표기법으로 작성되는 완전한 괄호 구문을 사용합니다. 예를 들어, 덧셈 연산은 (+ 1 2)
로 작성됩니다.
Scheme의 함수는 일급 시민으로, 다른 함수에 인수로 전달되거나 반환될 수 있습니다. 예시:
(define (make-adder x)
(lambda (y) (+ x y)))
(define add5 (make-adder 5))
(add5 10) ; 15를 반환
Scheme은 꼬리 호출 최적화를 지원하여, 꼬리 위치에서 발생하는 재귀 호출에 대해 현재 스택 프레임을 재사용할 수 있게 하여 스택 오버플로우를 방지합니다.
Scheme은 계속을 사용할 수 있게 하여 프로그래머가 현재 계산 상태를 캡처하고 제어 흐름을 조작할 수 있게 합니다:
(call-with-current-continuation
(lambda (exit)
(exit 'done)))
Scheme은 프로그래머가 구문 확장을 만들 수 있는 강력한 매크로 시스템을 가지고 있습니다. 간단한 매크로는 다음과 같이 정의할 수 있습니다:
(define-syntax my-if
(syntax-rules ()
((_ test then else)
(if test then else))))
Scheme은 리스트, 쌍 및 고차 함수와 같은 구조를 통해 데이터 추상화를 지원하여 데이터의 효율적인 조작을 가능하게 합니다.
Scheme은 렉시컬 스코프를 사용하여 변수의 범위가 소스 코드에서의 물리적 위치에 의해 결정됩니다. 이는 변수 바인딩에 대한 예측 가능한 동작을 초래합니다.
Scheme은 동적 타이핑을 지원하여 변수는 명시적인 타입 선언 없이도 어떤 타입의 값을 가질 수 있습니다.
Lisp 방언으로서 Scheme은 리스트 처리를 최적화하여 리스트에 대한 작업을 쉽게 수행할 수 있습니다:
(define my-list (list 1 2 3 4))
(car my-list) ; 1을 반환
(cdr my-list) ; (2 3 4)를 반환
Scheme 함수는 메모리 사용과 성능을 최적화하기 위해 꼬리 위치에서 재귀적으로 정의될 수 있습니다. 예를 들어:
(define (factorial n)
(define (fact-helper n acc)
(if (zero? n)
acc
(fact-helper (- n 1) (* n acc))))
(fact-helper n 1))
Scheme 애플리케이션은 일반적으로 선택한 구현의 런타임 환경을 사용하여 빌드할 수 있습니다. 예를 들어, Racket에서는 명령줄 도구 racket
를 사용하여 .rkt
파일을 실행하거나 실행 파일로 컴파일할 수 있습니다.
Scheme을 위한 여러 컴파일러 및 인터프리터가 있습니다:
Scheme은 프로그래밍 원칙을 가르치고 컴퓨터 과학 연구 도구로서 학계에서 널리 사용됩니다. 인공지능, 언어 설계, 스크립팅 및 기호 계산이나 복잡한 데이터 조작이 필요한 다양한 분야에서 응용됩니다.
두 언어 모두 함수형 프로그래밍 스타일을 지원하지만, Python은 가독성과 단순성을 강조하는 반면, Scheme은 강력하고 간결한 표현에 중점을 둡니다. Scheme의 괄호가 많은 구문은 초보자에게 장벽으로 여겨질 수 있는 반면, Python의 들여쓰기 기반 구문은 일반적으로 더 접근하기 쉽습니다.
JavaScript도 함수형 프로그래밍을 지원하며 일급 함수를 가지고 있습니다. 그러나 JavaScript는 프로토타입 기반 객체 시스템을 가지고 있는 반면, Scheme은 함수형 패러다임에 의존합니다. Scheme의 매크로 시스템은 JavaScript에는 없는 기능을 제공합니다.
C는 시스템 프로그래밍을 위해 설계된 저수준의 정적 타이핑 언어인 반면, Scheme은 고수준의 동적 타이핑 언어입니다. C는 성능과 하드웨어 수준의 조작에 중점을 두는 반면, Scheme은 추상화와 계산의 이론적 측면을 강조합니다.
두 언어 모두 함수형 프로그래밍에 뿌리를 두고 있습니다. Haskell은 더 엄격한 타입 시스템을 사용하고 지연 평가를 지원하는 반면, Scheme은 동적 타이핑과 즉각 평가를 통해 성능의 일부를 희생하면서 더 유연한 프로그래밍을 가능하게 합니다.
Ruby는 함수형 프로그래밍 기능을 혼합한 객체 지향 프로그래밍 언어인 반면, Scheme은 순수 함수형입니다. Ruby의 구문은 더 장황한 반면, Scheme의 단순함은 미니멀리스트 디자인에서 비롯됩니다.
Scheme 코드를 다른 언어로 번역하는 것은 Scheme 구문과 대상 언어를 이해하는 도구를 통해 용이해질 수 있습니다. 유용한 소스-투-소스 코드 번역 도구는 다음과 같습니다:
Chicken Scheme은 Scheme 코드를 C로 변환할 수 있는 컴파일러를 제공하여 C 라이브러리를 활용하고 효율적인 실행 파일을 생성할 수 있게 합니다.
Scheme의 파생 언어인 Racket은 코드를 JavaScript로 변환하고 컴파일하는 내장 기능을 가지고 있어 웹 애플리케이션 배포를 용이하게 합니다.
Gambit Scheme은 Scheme 코드를 C 및 네이티브 실행 파일로 컴파일할 수 있어 성능이 중요한 애플리케이션에 대한 효율적인 번역 옵션을 제공합니다.