맨위로가기

스킴 (프로그래밍 언어)

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

1. 개요

스킴은 1970년대 초 칼 휴이트의 액터 모델을 이해하려는 시도로 시작된 함수형 프로그래밍 언어이다. Lisp 언어 계열에 속하며, S-표현식을 기반으로 하는 단순한 구문과 람다 계산법을 활용하는 특징을 가진다. 스킴은 렉시컬 스코프, 블록 구조, 적절한 꼬리 재귀, 일급 객체로서의 컨티뉴에이션, 프로시저와 변수를 위한 공유 네임스페이스 등을 지원하며, 언어 기능을 최소한으로 유지하려는 미니멀리즘을 추구한다. IEEE에 의해 공식적으로 정의되며, R5RS와 R6RS, R7RS 등의 표준이 존재한다. 스킴은 SRFI(Scheme Requests for Implementation)를 통해 확장을 표준화하며, 다양한 구현체(Bigloo, Chicken, Racket 등)가 존재한다. 교육용으로 널리 사용되며, GIMP, GNU Guile, Android의 App Inventor 등 다양한 분야에서 활용된다.

더 읽어볼만한 페이지

  • 1975년 개발된 프로그래밍 언어 - CLU (프로그래밍 언어)
    ALGOL을 기반으로 MIT에서 개발된 CLU는 '클러스터' 개념을 통해 데이터 추상화와 정보 은닉을 지원하며 타입 안전성을 위한 설계, 반복자, 예외 처리, 다중 할당 등의 기능을 제공하고 객체 지향 프로그래밍 발전에 기여한 프로그래밍 언어로서 에이다, C++, 자바, 파이썬 등 여러 언어에 영향을 주었다.
  • 리스프 프로그래밍 언어 계열 - 클로저 (프로그래밍 언어)
    클로저는 리치 히키가 개발한 JVM 기반의 함수형 프로그래밍 언어로, 자바와의 호환성을 특징으로 하며 불변 데이터 구조와 STM을 활용한 동시성 관리, 그리고 REPL 환경, 매크로 시스템 등의 기능을 제공한다.
  • 리스프 프로그래밍 언어 계열 - 커먼 리스프
    커먼 리스프는 1980년대 초 여러 리스프 방언 통합 시도에서 시작된 언어로, S-표현식 문법, 다양한 자료형, 일급 함수, 매크로, CLOS를 특징으로 하며, ANSI 표준으로 정의되어 다양한 분야에서 활용된다.
  • 다중 패러다임 프로그래밍 언어 - Tcl
    Tcl은 존 오스터하우트가 개발한 명령어 기반의 프로그래밍 언어로, Tk 툴킷과 결합하여 GUI 스크립팅 환경으로 발전했으며, 다양한 운영체제에서 사용 가능하고 C, C++, Java 등 다른 언어와의 인터페이스를 지원한다.
  • 다중 패러다임 프로그래밍 언어 -
    펄은 래리 월이 개발한 텍스트 조작에 강점을 가진 다목적 프로그래밍 언어이며, 1987년 펄 1.0이 처음 공개된 이후 여러 버전 업데이트를 거쳐 객체 지향 프로그래밍과 유니코드 지원 기능을 추가했고, 현재 펄 5가 널리 사용되며 CPAN을 통해 방대한 모듈 생태계를 제공한다.
스킴 (프로그래밍 언어) - [IT 관련 정보]에 관한 문서
기본 정보
람다 소문자
람다 소문자
패러다임다중 패러다임: 함수형, 명령형, 메타
계열리스프
설계자가이 L. 스틸, 제럴드 제이 서스먼
발표 연도1975년
최신 버전R7RS
최신 버전 발표일2013년
자료형동적, 레이턴트, 강한
유효 범위어휘적
파일 확장자.scm, .ss
웹사이트Scheme 공식 웹사이트
영향
영향을 받은 언어알골, 리스프, MDL
영향을 준 언어클로저, 커먼 리스프, 딜런, EuLisp, 하스켈, Hop, 자바스크립트, 줄리아, 루아, MultiLisp, 파이썬, R, 래킷, 루비, 러스트, S, 스칼라, T
구현체
구현체 목록여러 구현체 ([:Category:Scheme (programming language) implementations|Scheme 구현체] 참조)

2. 역사

MIT 인공지능 연구소에서는 LISP에서 파생된 여러 언어가 만들어졌다.

년도언어제작자
1960년LISP|LISP영어매카시 외
1964년Meteor|Meteor영어보브로우
1969년Convert|Convert영어가즈만
1969년Planner|Planner영어휴이트
1970년Muddle|Muddle영어서스먼, 휴이트 외
1971년Micro-Planner|Micro-Planner영어서스먼 외
1972년Conniver|Conniver영어서스먼 외
1973년Plasma|Plasma영어휴이트 외
1975년Schemer|Schemer영어서스먼, 스틸



칼 휴이트가 설계한 규칙 기반 언어 Planner는 너무 복잡해서 모든 기능을 구현하기 어려웠다.[66] 서스먼 등은 Planner의 기능을 축소한 Micro-Planner|Micro-Planner영어를 만들었고, 더 나아가 Planner와 비슷한 Conniver|Conniver영어를 개발했다.

칼 휴이트의 액터 언어 Plasma|Plasma영어 (Planner|Planner영어-73) 역시 복잡하여 MacLisp|MacLisp영어로 구현되었지만 이해하기 어려웠다. 서스먼과 가이 스틸 주니어는 Plasma|Plasma영어를 이해하고자 불필요한 기능을 제거하고 LISP|LISP영어 구문을 사용하는 더 작은 Plasma|Plasma영어를 설계했다.

이 과정은 Planner|Planner영어에서 Micro-Planner|Micro-Planner영어와 Conniver|Conniver영어를 만드는 과정과 비슷했기 때문에, 새 언어는 처음에는 Schemer|Schemer영어 (음모자)로 불렸다. 그러나 당시 운영 체제의 파일 이름 제한으로 인해 Scheme|Scheme영어이라는 이름이 사용되었다.

2. 1. 기원

1970년대에 스킴은 칼 휴이트의 액터 모델을 이해하려는 시도로 시작되었다. 이를 위해 스틸과 서스만은 Maclisp를 사용하여 "작은 리스프 인터프리터"를 작성한 다음 "액터를 만들고 메시지를 보낼 수 있는 메커니즘"을 추가했다.[7] 스킴은 원래 Planner나 ''Conniver''와 같은 다른 리스프 파생 언어의 전통에 따라 "Schemer"라고 불렸다. 현재 이름은 저자들이 ITS 운영 체제를 사용한 결과로, 이 운영 체제는 파일 이름을 최대 6자리의 두 부분으로 제한했기 때문이다. 현재 "Schemer"는 일반적으로 스킴 프로그래머를 지칭하는 데 사용된다.

스킴은 MIT AI 연구소에서 제럴드 제이 서스먼과 가이 스틸 주니어에 의해 1975년경 기본적인 설계가 이루어졌다. 동기는 칼 휴이트가 제안한 병행 계산 모델인 액터와 그 언어의 PLASMA(Planner-73)를 이해하기 위해서였다.

정적 스코프는 상태를 가진 데이터인 액터(클로저[59])의 실현 외에도 lambda 구문을 사용한 '''람다 대수'''[60]와 '''꼬리 재귀'''[61]의 최적화에 필수적인 기구였다.

또한, 프로그램의 제어 이론에서 당시 등장한 '''지속'''[62] 및 액터 이론에서의 액터에 대한 '''메시지 전달'''[63]의 개념에서 영감을 얻은 '''지속 전달 형식'''[64][65]이라고 불리는 프로그래밍 기법은 이후 지속 연구에 큰 영향을 미쳤다.

MIT 인공지능 연구소에서 LISP에서 시작된 여러 언어가 만들어졌다.

년도언어제작자
1960년LISP|LISP영어매카시 외
1964년Meteor|Meteor영어보브로우
1969년Convert|Convert영어가즈만
1969년Planner|Planner영어휴이트
1970년Muddle|Muddle영어서스먼, 휴이트 외
1971년Micro-Planner|Micro-Planner영어서스먼 외
1972년Conniver|Conniver영어서스먼 외
1973년Plasma|Plasma영어휴이트 외
1975년Schemer|Schemer영어서스먼, 스틸



칼 휴이트가 설계한 규칙 기반 언어 Planner는 복잡한 구조를 가지고 있었기 때문에, 처음 설계된 모든 기능을 구현하는 것은 어려웠다.[66] 서스먼 등은 이를 서브셋 언어인 Micro-Planner|Micro-Planner영어로 실현했으며, 더 나아가 Planner의 흐름을 따른 독자적인 언어로서 Conniver|Conniver영어를 만들었다.

칼 휴이트가 설계한 액터 언어 Plasma|Plasma영어 (Planner|Planner영어-73) 역시 복잡한 구조를 가지고 있어서, MacLisp|MacLisp영어에 의한 구현이 존재했지만, 그 작동 방식을 이해하기는 어려웠다. 서스먼과 가이 스틸 주니어는 Plasma|Plasma영어를 이해하기 위해 불필요한 기능을 제거한 LISP|LISP영어 구문을 가진 작은 Plasma|Plasma영어를 설계했다.

Plasma|Plasma영어에서 그 작은 Plasma|Plasma영어의 설계에 이르는 과정은 Planner|Planner영어에서 Micro-Planner|Micro-Planner영어 및 Conniver|Conniver영어에 이르는 과정을 연상시켰기 때문에, 그 언어는 Planner|Planner영어 (계획하는 자) 및 Conniver|Conniver영어 (계략을 꾸미는 자)의 다음이라는 의미로 처음에는 Schemer|Schemer영어 (음모를 꾸미는 자)라고 이름 붙여졌다. 하지만, 당시 운영 체제의 파일 시스템의 제한으로 파일 이름이 6자로 잘렸기 때문에 Scheme|Scheme영어이라는 이름이 사용되었다.

2. 2. R6RS

2003년 스킴 워크숍에서 새로운 언어 표준화 과정이 시작되었으며, 2006년에 R6RS 표준을 제정하는 것을 목표로 했다. 이 과정은 이전의 R''n''RS의 만장일치 방식에서 벗어났다.

R6RS는 표준 모듈 시스템을 특징으로 하며, 핵심 언어와 라이브러리 간의 분리를 허용한다. 2007년 8월 28일에 새로운 표준이 비준되었다.[6]

R6RS의 특징은 레코드 타입 기술자(RTD)이다. RTD는 레코드 타입 표현이 메모리 레이아웃을 보여줄 수 있게 한다. 또한 객체 필드 비트 마스크 및 변경 가능한 스킴 객체 필드 비트 마스크를 계산하며, 가비지 수집기가 RTD에 저장된 전체 필드 목록을 순회하지 않고 필드에 대해 수행할 작업을 알 수 있도록 돕는다.[10]

R6RS는 언어에 많은 중요한 변경 사항을 도입했다.[11] 소스 코드는 이제 유니코드로 지정되었으며, 유니코드 문자의 큰 하위 집합이 이제 스킴 심볼 및 식별자에 나타날 수 있다. 문자 데이터도 이제 유니코드로 지정된다. 많은 표준 프로시저가 새로운 표준 라이브러리로 이동되었으며, 이전에는 표준의 일부가 아니었던 프로시저 및 구문 형식을 포함하고 있다. 새로운 모듈 시스템이 도입되었으며, 예외 처리를 위한 시스템이 이제 표준화되었다. 구문 규칙은 매크로 확장 시 모든 스킴을 사용할 수 있도록 하는 더 표현력이 풍부한 구문 추상화 기능(syntax-case)으로 대체되었다. 준수 구현은 이제 스킴의 전체 숫자 체계를 지원하도록 ''요구''되며, 숫자의 의미는 주로 부동 소수점 숫자 표현에 대한 IEEE 754 표준 지원 방향으로 확장되었다.

R6RS는 Unicode영어 지원 등 실용적인 언어로서 필요한 요소가 포함된 점이 특징이다. 그러나 많은 기능이 포함되었음에도 불구하고 세부적인 면에서의 완성도가 부족하다는 비판도 있었다.[73]

2. 3. R7RS

R6RS 표준은 일부에서 최소주의 철학에서 벗어났다고 보아 논란을 일으켰다.[12][13] 2009년 8월, 표준화 과정을 감독하는 Scheme 운영 위원회는 프로그래머를 위한 크고 현대적인 프로그래밍 언어와 교육자 및 일반 구현자들이 칭찬하는 최소주의를 유지하는 작은 버전, 즉 큰 버전의 하위 집합, 이렇게 두 개의 언어로 Scheme을 분리할 것을 권고할 의사를 발표했다.[14] 이 두 개의 새로운 버전의 Scheme 작업을 위해 두 개의 작업 그룹이 만들어졌다. Scheme Reports Process 사이트에는 작업 그룹의 헌장, 공개 토론 및 문제 추적 시스템에 대한 링크가 있다.

R7RS의 아홉 번째 초안(작은 언어)은 2013년 4월 15일에 공개되었다.[15] 이 초안을 비준하는 투표는 2013년 5월 20일에 마감되었으며,[16] 최종 보고서는 2013년 8월 6일부터 제공되었으며, "해당 노력의 '작은' 언어를 설명하므로 R6RS의 후속 제품으로 단독으로 간주할 수 없다".[5]

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

style="font-size:112%" | 리스프 방언 타임라인
19581960196519701975198019851990199520002005201020152020
LISP 1, 1.5, LISP 2colspan="10" |
colspan="2" |Maclispcolspan="6" |
colspan="3" |Interlispcolspan="5" |
colspan="3" |MDLcolspan="5" |
colspan="4" |Lisp 머신 Lispcolspan="4" |
colspan="4" |SchemeR5RSR6RSR7RS small
colspan="4" |NIL
colspan="5" |ZIL
colspan="5" |Franz Lisp
colspan="5" |Common LispANSI 표준
colspan="5" |Le Lisp
colspan="5" |MIT Scheme
colspan="5" |XLISP
colspan="6" |Tcolspan="4" |
colspan="6" |Chez Scheme
colspan="6" |Emacs Lisp
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. 특징

스킴은 주로 함수형 프로그래밍 언어이며, 리스프 계열 언어의 특징들을 공유한다.

스킴 구문은 S식(S-expression)만을 사용한다. S식은 아톰(atom)이나 리스트(list) 중 하나이며, 리스트는 공백으로 분리된 여러 S식을 괄호로 묶은 것이다. 빈 리스트는 `()`로 나타낸다. 함수 호출도 S식으로 표현하는데, 예를 들어 `(f a1 a2 ... an)`는 C 언어의 `f(a1, a2, ..., an)`에 해당한다.

S식 `(f a1 a2 ... an)`는 함수 호출의 결과를 계산한 값을 의미한다. 이 함수 호출을 계산하는 방법은 먼저 함수 부분 `f`와 각 인수 `a1`부터 `an`까지의 값을 구한 후, 함수 `f`를 인수에 적용하는 것이다. 이러한 계산 모델을 ‘계산 후 적용 모델’(eval-apply model)이라고 부르기도 한다.

스킴에는 `quote`, `cond`, `let`, `define`, `lambda`와 같은 특수 구문이 존재한다. 이들은 S식 형태를 가지지만 특수한 방식으로 수행된다. `quote`는 인수로 주어진 식의 값을 계산하지 않고, `cond`는 주어진 조건에 따라 다른 값을 계산한다. `let`은 지역 변수를 생성하고, `define`은 변수의 값을 정의한다. `lambda`는 함수 값을 정의하는 구문으로, 예를 들어 인수의 두 배를 반환하는 함수는 `(lambda (n) (+ n n))`로 나타낼 수 있다.

스킴은 S-표현식을 기반으로 하는 단순한 구문을 가지며, 접두 연산자 뒤에 인수가 오는 형태이다. 스킴 프로그램은 중첩된 목록의 시퀀스로 구성되며, 목록은 스킴의 주요 데이터 구조이므로 소스 코드와 데이터 형식 간에 밀접한 동등성(동형성)이 있다. 스킴 프로그램은 스킴 코드 조각을 동적으로 쉽게 생성하고 평가할 수 있다.

스킴은 리스트 처리에 필요한 `cons`, `car와 cdr` 등의 기본 요소를 상속받았다. 또한, 동적 타입 변수를 사용하고 일급 프로시저를 지원하여, 프로시저를 변수에 값으로 할당하거나 다른 프로시저에 인수로 전달할 수 있다.

스킴은 MIT AI 연구소에서 제럴드 제이 서스먼과 가이 스틸 주니어에 의해 1975년경에 설계되었다. 칼 휴이트의 액터와 PLASMA(Planner-73)를 이해하기 위한 목적이었다.

정적 스코프 (ALGOL에서 유래[58])는 상태를 가진 데이터인 액터(클로저[59])의 실현 외에도, `lambda` 구문을 사용한 람다 대수[60]꼬리 재귀[61] 최적화에 필수적이었다.

또한, 프로그램 제어 이론에서 등장한 지속[62] 및 액터 이론에서의 메시지 전달[63] 개념에서 영감을 얻은 지속 전달 형식[64][65]은 지속 연구에 큰 영향을 미쳤다.

3. 1. 미니멀리즘

스킴은 매우 단순한 언어이며, 비슷한 표현력을 가진 다른 많은 언어보다 구현하기가 훨씬 쉽다.[17] 이러한 용이성은 언어의 구문 대부분을 더 기본적인 형태로 파생하기 위해 람다 계산법을 사용한 데 기인한다. 예를 들어, R5RS 스킴 표준에 정의된 23개의 s-표현식 기반 구문 구조 중 14개는 파생 양식 또는 라이브러리 양식으로 분류되며, 이는 주로 람다를 포함하는 매크로로 작성할 수 있다. R5RS (§3.1)에서 "변수 바인딩 구조 중 가장 기본적인 것은 람다 표현식이다. 왜냐하면 다른 모든 변수 바인딩 구조는 람다 표현식으로 설명할 수 있기 때문이다."라고 명시하고 있다.[4]

기본 형식과 파생 형식은 다음과 같다.

기본 형식파생 형식



다음은 변수 바인딩을 수행하기 위해 `lambda`를 사용하여 `let`을 표현식으로 구현하는 매크로 예시이다.



(define-syntax let

(syntax-rules ()

((let ((var expr) ...) body ...)

((lambda (var ...) body ...) expr ...))))



따라서 위에서 정의한 `let`을 사용하면 스킴 구현은 "`(let ((a 1)(b 2)) (+ b a))`"를 " `((lambda (a b) (+ b a)) 1 2)`"로 다시 작성하며, 이는 구현의 작업을 프로시저 인스턴스화 코딩으로 줄여준다.

1998년 서스먼(Sussman)과 스틸(Steele)은 스킴의 미니멀리즘이 의도적인 설계 목표가 아니라 설계 과정의 의도치 않은 결과라고 언급했다. "우리는 실제로 복잡한 것을 만들려고 노력했고, 우연히, 모든 목표를 충족하지만 의도했던 것보다 훨씬 단순한 것을 설계했다는 것을 발견했다... 우리는 람다 계산법—작고 단순한 형식론—이 강력하고 표현력 있는 프로그래밍 언어의 핵심 역할을 할 수 있다는 것을 깨달았다."[7]

3. 2. 렉시컬 스코프 (정적 스코프)

초기 Maclisp와 같은 리스프와 달리, 스킴은 대부분의 현대적인 프로그래밍 언어처럼 정적 유효 범위를 사용한다. 즉, 프로그램 단위 내의 모든 가능한 변수 바인딩은 해당 프로그램 단위가 호출될 컨텍스트를 고려하지 않고 프로그램 텍스트를 읽음으로써 분석할 수 있다.[7] 이는 초기 리스프 방언의 특징이었던 동적 유효 범위와 대조된다.

1970년대 초반, 서스먼은 ALGOL 연구를 통해 정적 유효 범위 모델을 리스프의 새로운 버전에 통합하려는 동기를 얻었다. 그는 ALGOL과 유사한 정적 유효 범위 메커니즘이 리스프에서 휴이트의 액터 모델을 구현하려는 초기 목표를 실현하는 데 도움이 될 것이라고 제안했다.[7]

서스먼과 스틸은 1975년 람다 논문 "Scheme: 확장된 람다 계산기 인터프리터"[18]에서 리스프 방언에 정적 유효 범위를 도입하는 방법에 대한 핵심 통찰력을 대중화했으며, 정적 클로저의 개념을 채택했다(21페이지).[19]

en로서 리스프 초창기부터 이미 인식되어 논의되었던 것이기는 하지만, 반드시 1975년의 스킴부터 시작되었다고는 할 수 없다. 그럼에도 불구하고 스킴 이후의 리스프 방언에 정적 스코프가 널리 퍼진 것은 스킴의 영향이라고 할 수 있으며, 특히 Common Lisp가 특기할 만하다.

3. 3. 람다 계산법

앨론조 처치의 람다 대수는 스킴에서 프로시저 도입에 "lambda" 키워드를 사용하고, 고차 함수를 활용하는 함수형 프로그래밍 기법 발전에 영향을 주었다.[7] 초기 리스프는 자유 변수 처리 방식 때문에 람다 대수를 적절하게 표현하지 못했다.[7]

형식적인 람다 시스템은 공리와 완전한 계산 규칙을 가져 수학적 논리와 도구를 사용한 분석에 유용하다. 이 시스템에서 계산은 방향성 있는 추론으로 볼 수 있다. 람다 대수의 구문은 x, y, z, ..., 괄호, 공백, 점(.) 및 기호 λ로부터 재귀적인 표현을 따른다.[20] 람다 계산은 강력한 수학적 논리의 출발점, 기계 평가 모방, 상당한 메타 이론 창출 등의 기능을 한다.[21]

렉시컬 스코프 도입은 람다 표기법과 프로그래밍 언어 표현 사이의 등가성을 확립하여 이 문제를 해결했다. 수스만과 스틸은 람다 표현식을 "제어 구조와 환경 수정자"로 사용하여, 다른 프로그래밍 언어의 의미론과 다른 리스프의 동적 스코프를 도출할 수 있음을 보였다.[22] 그들은 람다 페이퍼(Lambda Papers)에서 연속 전달 방식을 도입하고, 람다 대수의 실용적인 사용의 강력함을 보였다.

3. 4. 블록 구조

스킴은 ALGOL로부터 블록 구조를 상속받았다. 스킴에서 블록은 `let`, `let*`, `letrec`의 세 가지 ''바인딩 구성자''로 구현된다. 예를 들어, 다음 구성자는 `var`라는 심볼이 숫자 10에 바인딩되는 블록을 생성한다.

```scheme

(define var "goose")

;; 여기에 var에 대한 모든 참조는 "goose"에 바인딩됩니다.

(let ((var 10))

;; statement가 여기에 옵니다. 여기에 var에 대한 모든 참조는 10에 바인딩됩니다.

)

;; 여기에 var에 대한 모든 참조는 "goose"에 바인딩됩니다.

```

프로그래머의 필요에 따라 블록을 중첩하여 임의로 복잡한 블록 구조를 만들 수 있다. 블록 구조를 사용하여 지역 바인딩을 생성하면 그렇지 않으면 발생할 수 있는 네임스페이스 충돌의 위험을 완화할 수 있다.

`let`의 한 변형인 `let*`는 바인딩이 동일한 구성에서 이전에 정의된 변수를 참조하도록 허용한다.

```scheme

(let* ((var1 10)

(var2 (+ var1 12)))

;; 그러나 var1의 정의는 var2를 참조할 수 없습니다.

)

```

다른 변형인 `letrec`은 상호 재귀 프로시저가 서로 바인딩될 수 있도록 설계되었다.

```scheme

;; Hofstadter의 남성 및 여성 시퀀스를 쌍 목록으로 계산

(define (hofstadter-male-female n)

(letrec ((female (lambda (n)

(if (= n 0)

1

(- n (male (female (- n 1)))))))

(male (lambda (n)

(if (= n 0)

0

(- n (female (male (- n 1))))))))

(let loop ((i 0))

(if (> i n)

'()

(cons (cons (female i)

(male i))

(loop (+ i 1)))))))

(hofstadter-male-female 8)

===> ((1 . 0) (1 . 0) (2 . 1) (2 . 2) (3 . 2) (3 . 3) (4 . 4) (5 . 4) (5 . 5))

```

(이 예제에 사용된 정의는 호프스태터의 남성 및 여성 수열을 참조한다.)

단일 `letrec`에 바인딩된 모든 프로시저는 서로의 이름으로, 그리고 동일한 `letrec`에서 이전에 정의된 변수의 값으로 참조할 수 있지만, 동일한 `letrec`에서 나중에 정의된 ''값''은 참조할 수 없다.

`let`의 한 변형인 "named let" 형식은 `let` 키워드 뒤에 식별자가 있다. 이는 let 변수를 주어진 식별자를 이름으로 하고 본문이 let 형식의 본문인 프로시저의 인수에 바인딩한다. 본문은 프로시저를 호출하여 원하는 대로 반복할 수 있다. "named let"은 반복을 구현하는 데 널리 사용된다.

예: 간단한 카운터

```scheme

(let loop ((n 1))

(if (> n 10)

'()

(cons n

(loop (+ n 1)))))

===> (1 2 3 4 5 6 7 8 9 10)

```

스킴의 모든 프로시저와 마찬가지로 "named let"에서 생성된 프로시저는 일급 객체이다.

3. 5. 적절한 꼬리 재귀

스킴은 반복 구문인 `do`를 가지고 있지만, 관용적인 스킴에서는 꼬리 재귀를 사용하여 반복을 표현하는 것이 더 일반적이다. 표준을 준수하는 스킴 구현은 무한한 수의 활성 꼬리 호출을 지원하도록 꼬리 호출을 최적화해야 하며(R5RS sec. 3.5)[4] — 스킴 보고서에서 '적절한 꼬리 재귀'라고 설명하는 속성 — 스킴 프로그래머가 때로는 더 직관적인 재귀 구조를 사용하여 반복 알고리즘을 작성하는 것을 안전하게 해준다. 꼬리 재귀 프로시저와 'named `let`' 형식은 꼬리 재귀를 사용한 반복을 지원한다.

다음은 0에서 9까지의 제곱수 목록을 만드는 예제이다.

```scheme

;; 0에서 9까지의 제곱수 목록 만들기:

;; 참고: loop는 레이블로 사용되는 임의의 기호입니다. 어떤 기호든 상관없습니다.

(define (list-of-squares n)

(let loop ((i n) (res '()))

(if (< i 0)

res

(loop (- i 1) (cons (* i i) res)))))

(list-of-squares 9)

===> (0 1 4 9 16 25 36 49 64 81)

3. 6. 일급 객체로서의 연속(continuation)

스킴은 `call-with-current-continuation` ( `call/cc`로도 알려짐) 프로시저를 제공하여 현재 연속을 캡처하고 일급 객체로 처리한다.[4] 일급 연속은 프로그래머가 반복자, 코루틴, 백트래킹과 같은 비지역 제어 흐름 제어 구조를 만들 수 있게 해준다.

3. 7. 프로시저와 변수를 위한 공유 네임스페이스

공통 리스프와 달리 스킴에서는 모든 데이터와 프로시저가 공통 네임스페이스를 공유한다. 반면 공통 리스프에서는 함수와 데이터가 별도의 네임스페이스를 가지고 있어 함수와 변수가 동일한 이름을 가질 수 있으며, 함수를 값으로 참조하기 위한 특수한 표기법이 필요하다. 이는 때때로 스킴의 통합 네임스페이스와 공통 리스프의 별도 네임스페이스를 나타내는 "Lisp-1 vs. Lisp-2" 구별로 알려져 있다.[23]

스킴에서는 데이터를 조작하고 바인딩하는 데 사용되는 동일한 기본 요소로 프로시저를 바인딩할 수 있다. 공통 리스프의 `defun` 및 `#'` 기본 요소와 같은 것은 없다.

다음은 코드 예시이다.

설명코드결과
숫자에 바인딩된 변수===> 10
변이 (바인딩된 값 변경)===> 26
동일한 변수에 프로시저 할당===> 18
동일한 변수에 표현식의 결과 할당===> 13
함수형 프로그래밍


4. 구현 표준

스킴의 언어 사양은 IEEE에 의해 공식적으로 정해졌으며[72], 그 사양은 "Revisedn Report on the Algorithmic Language Scheme (R''n''RS)영어"라고 불린다. 2016년 현재 널리 구현되고 있는 것은 R5RS(1998년)이다.

2007년 9월에는 "The Revised6 Report on the Algorithmic Language Scheme (R6RS)영어"[73]가 성립되었다. R6RS는 4부 구성으로 R5RS에 비해 약 3배 분량이며, Unicode영어 지원 등 실용적인 언어로서 필요한 요소가 포함되었다. 그러나 방대한 기능에도 불구하고 세부적인 완성도가 부족하다는 비판이 있었고, 비공식적으로 R5RS를 확장하는 ERR5RS (Extended R5RS Scheme영어) 규격을 검토하는 움직임도 있었다.

2009년 8월, Scheme영어 언어 운영 위원회는 Scheme영어을 대규모 버전과, 대규모 버전의 서브셋이 되는 작은 언어 사양의 두 가지 언어로 분할하는 것을 권장하는 의향을 발표했다[74].

2013년 7월, "The Revised7 Report on the Algorithmic Language Scheme (R7RS)영어"[75] (small language영어)가 성립되었다.

4. 1. 수치 타워

스킴은 복소수유리수 형식을 포함한 비교적 완전한 수치 데이터 유형 집합을 지정하며, 이는 스킴에서 수치 타워로 알려져 있다.[4] 표준은 이를 추상화로 취급하며, 구현자가 특정 내부 표현을 사용하도록 강제하지 않는다.

숫자는 정확성을 가질 수 있다. 정확한 숫자는 다른 정확한 숫자를 포함하는 정확한 연산 시퀀스에 의해서만 생성될 수 있으며, 부정확성은 전염성이 있다. 표준은 모든 정확한 숫자를 생성하는 연산에 대해 모든 두 구현이 동일한 결과를 생성해야 한다고 명시한다.

R5RS 표준은 숫자의 정확성을 변경하는 데 사용할 수 있는 프로시저 `exact->inexact` 및 `inexact->exact`를 지정한다. `inexact->exact`는 "인수에 수치적으로 가장 가까운 정확한 숫자"를 생성한다. `exact->inexact`는 "인수에 수치적으로 가장 가까운 부정확한 숫자"를 생성한다. R6RS 표준은 이러한 프로시저를 주요 보고서에서 생략하지만, 표준 라이브러리(rnrs r5rs (6))에서 R5RS 호환성 프로시저로 지정한다.

R5RS 표준에서, 스킴 구현은 전체 수치 타워를 구현할 필요는 없지만, "구현의 목적과 스킴 언어의 정신에 부합하는 일관된 하위 집합"을 구현해야 한다(R5RS sec. 6.2.3).[4] 새로운 R6RS 표준은 전체 타워 구현을 요구하며, "실질적으로 무제한 크기 및 정밀도의 정확한 정수 객체와 정확한 유리수 객체를 구현하고, 특정 프로시저를 구현하여...정확한 인수가 주어지면 항상 정확한 결과를 반환하도록 해야 한다"(R6RS sec. 3.4, sec. 11.7.1).[6]

예시 1: 정확한 유리수 복소수를 지원하는 구현의 정확한 산술.

```scheme

;; 세 개의 유리수 실수와 두 개의 유리수 복소수의 합

(define x (+ 1/3 1/4 -1/5 -1/3i 405/50+2/3i))

x

===> 509/60+1/3i

;; 정확성 확인.

(exact? x)

===> #t

```

예시 2: 정확한 유리수 또는 복소수를 지원하지 않지만 유리수 표기법의 실수를 허용하는 구현에서 동일한 산술.

```scheme

;; 네 개의 유리수 실수의 합

(define xr (+ 1/3 1/4 -1/5 405/50))

;; 두 개의 유리수 실수의 합

(define xi (+ -1/3 2/3))

xr

===> 8.48333333333333

xi

===> 0.333333333333333

;; 정확성 확인.

(exact? xr)

===> #f

(exact? xi)

===> #f

```

두 구현 모두 R5RS 표준을 준수하지만, 두 번째 구현은 전체 수치 타워를 구현하지 않기 때문에 R6RS를 준수하지 않는다.

4. 2. 지연 평가

스킴은 `delay` 형식과 `force` 프로시저를 통해 지연 평가를 지원한다.

```scheme

(define a 10)

(define eval-aplus2 (delay (+ a 2)))

(set! a 20)

(force eval-aplus2)

===> 22

(define eval-aplus50 (delay (+ a 50)))

(let ((a 8))

(force eval-aplus50))

===> 70

(set! a 100)

(force eval-aplus2)

===> 22

```

프로미스의 원래 정의에 대한 어휘적 컨텍스트가 유지되며, `force`를 처음 사용한 후에도 해당 값은 유지된다. 프로미스는 단 한 번만 평가된다.[24]

이러한 기본 요소는 프로미스를 생성하거나 처리하며, 스트림과 같은 고급 지연 평가 구성을 구현하는 데 사용될 수 있다.[24]

R6RS 표준에서는 더 이상 기본 요소가 아니지만, 대신 R5RS 호환 라이브러리(rnrs r5rs (6))의 일부로 제공된다.

R5RS에서는 `delay`와 `force`의 제안된 구현이 제공되며, 프로미스를 인수가 없는 프로시저(thunk)로 구현하고, `force`가 호출되는 횟수와 관계없이 단 한 번만 평가되도록 메모이제이션을 사용한다(R5RS sec. 6.4).[4]

SRFI 41은 유한 및 무한 시퀀스를 매우 경제적으로 표현할 수 있게 해준다. 예를 들어, 다음은 SRFI 41에 정의된 함수를 사용하여 피보나치 수열을 정의한 것이다.[24]

```scheme

;; Define the Fibonacci sequence:

(define fibs

(stream-cons 0

(stream-cons 1

(stream-map +

fibs

(stream-cdr fibs)))))

;; Compute the hundredth number in the sequence:

(stream-ref fibs 99)

===> 218922995834555169026

4. 3. 프로시저 인수의 평가 순서

대부분의 리스프(Lisp)는 프로시저 인수의 평가 순서를 지정하지만, 스킴은 그렇지 않다. 평가 순서(연산자 위치의 표현식을 평가하는 순서를 포함)는 호출별로 구현에 의해 선택될 수 있으며, 유일한 제약 조건은 "연산자와 피연산자 표현식의 동시 평가 효과가 어떤 순차적 평가 순서와 일치하도록 제한된다"는 것이다.[4]

```scheme

(let ((ev (lambda(n) (display "Evaluating ")

(display (if (procedure? n) "procedure" n))

(newline) n)))

((ev +) (ev 1) (ev 2)))

===> 3

```

```

Evaluating 1

Evaluating 2

Evaluating procedure

```

`ev`는 전달된 인수를 설명한 다음 인수의 값을 반환하는 프로시저이다. 다른 리스프와 달리, 스킴 표현식의 연산자 위치(첫 번째 항목)에 표현식이 나타나는 것은 해당 표현식의 결과가 프로시저이기만 하면 매우 합법적이다.

프로시저 "+"를 호출하여 1과 2를 더할 때, 표현식 `(ev +)`, `(ev 1)` 및 `(ev 2)`는 효과가 병렬로 평가된 것과 같지 않기만 하면 어떤 순서로든 평가될 수 있다. 따라서 위의 예제 코드가 실행될 때 표준 스킴에 의해 다음 세 줄이 어떤 순서로든 표시될 수 있지만, 하나의 줄 텍스트가 다른 줄과 교차될 수는 없다. 이는 순차적 평가 제약을 위반하기 때문이다.

4. 4. 위생 매크로

`syntax-rules`라고도 불리는 위생 매크로는 언어의 나머지 부분에 대한 어휘 범위를 존중하여 일반적인 프로그래밍 오류를 방지한다. 이는 매크로 확장에 대한 특수한 명명 및 범위 규칙에 의해 보장된다.[4] R6RS는 더 정교한 변환 시스템인 `syntax-case`를 지정하며, 이는 오랫동안 R5RS 스킴에 대한 언어 확장으로 사용되어 왔다.

다음은 여러 표현식을 가진 "if"의 변형을 구현하는 매크로를 정의하는 예시이다.

```scheme

;; 여러 표현식을 가진 "if"의 변형을 구현하는 매크로 정의

;; 참 분기 및 거짓 분기가 없음.

(define-syntax when

(syntax-rules ()

((when pred exp exps ...)

(if pred (begin exp exps ...)))))

```

대부분의 스킴 구현은 위생 매크로 외에도 구문적 클로저, 명시적 이름 변경 매크로, `define-macro`와 같은 추가적인 매크로 시스템을 제공한다. 하지만 매크로가 위생적인지 여부를 지정할 수 없는 것은 단점 중 하나이며, 범위 집합과 같은 확장을 위한 대안 모델은 잠재적인 해결책을 제공한다.[26]

4. 5. 환경(Environments)과 eval

R5RS 이전의 스킴에는 다른 Lisp에서 흔히 사용되는 `eval` 프로시저에 해당하는 표준이 없었다. 하지만 첫 번째 람다 논문에서는 `evaluate`를 "LISP 함수 EVAL과 유사"라고 설명했고[18], 1978년의 첫 번째 개정 보고서에서는 이를 `enclose`로 대체했는데, `enclose`는 두 개의 인수를 받았다. 두 번째, 세 번째, 네 번째 개정 보고서에서는 `eval`에 해당하는 것을 생략했다.

이러한 혼란의 이유는 스킴의 렉시컬 스코핑에서 표현식의 평가 결과가 평가되는 위치에 따라 달라지기 때문이다. 예를 들어, 다음 표현식의 평가 결과가 5인지 6인지 명확하지 않다.[27]

```scheme

(let ((name '+))

(let ((+ *))

(evaluate (list name 2 3))))

```

`name`이 정의된 외부 환경에서 평가되면 결과는 피연산자의 합이다. 심볼 "+"가 프로시저 "*"의 값에 바인딩된 내부 환경에서 평가되면 결과는 두 피연산자의 곱이다.

R5RS는 환경을 반환하는 세 가지 프로시저를 지정하고, s-표현식과 환경을 받아 제공된 환경에서 표현식을 평가하는 `eval` 프로시저를 제공하여 이러한 혼란을 해결한다.(R5RS sec. 6.5)[4] R6RS는 프로그래머가 평가 환경으로 가져올 객체를 정확하게 지정할 수 있는 `environment`라는 프로시저를 제공함으로써 이를 확장한다.

최신 스킴(일반적으로 R5RS와 호환)에서는 이 표현식을 평가하기 위해 다음과 같은 `evaluate` 함수를 정의해야 한다.

```scheme

(define (evaluate expr)

(eval expr (interaction-environment)))

```

`interaction-environment`는 인터프리터의 전역 환경이다.

4. 6. 부울 표현식에서 비-부울 값 처리

대부분의 리스프 방언(Common Lisp 포함)에서는 관례에 따라 `NIL` 값을 부울 표현식에서 거짓 값으로 평가한다. 그러나 스킴에서는 1991년 IEEE 표준 이후[3] `#f`를 제외한 모든 값, 즉 스킴에서 `'()`로 표현되는 `NIL`과 동일한 값도 부울 표현식에서 참 값으로 평가된다.[4]

대부분의 리스프에서 참을 나타내는 부울 값의 상수가 `T`인 반면, 스킴에서는 `#t`이다.

4. 7. 기본 데이터 타입의 분리성(Disjointness)

스킴에서 기본 데이터 타입은 서로 배타적이다. `boolean?`, `pair?`, `symbol?`, `number?`, `char?`, `string?`, `vector?`, `port?`, `procedure?` 중 오직 하나의 술어만 임의의 스킴 객체에 대해 참이 될 수 있다.[4]

반면에 수치 데이터 타입 내에서는 수치 값들이 겹친다. 예를 들어, 정수 값은 동시에 `integer?`, `rational?`, `real?`, `complex?`, `number?` 술어를 모두 만족한다.[4]

4. 8. 동등성 술어 (Equivalence predicates)

스킴은 임의의 객체 간의 세 가지 다른 유형의 동등성을 가지며, `eq?`, `eqv?`, `equal?`의 세 가지 ''동등성 술어''(관계 연산자)로 표시된다.[4]

  • `eq?`: 매개변수가 메모리에서 동일한 데이터 객체를 나타내지 않는 한 `#f`로 평가된다.
  • `eqv?`: 일반적으로 `eq?`와 같지만, 원시 객체(예: 문자 및 숫자)를 특별하게 처리하여 동일한 값을 나타내는 숫자가 동일한 객체를 참조하지 않더라도 `eqv?`가 되도록 한다.
  • `equal?`: 리스트, 벡터문자열과 같은 데이터 구조를 비교하여 구조가 일치하는지 확인하고, 내용이 `eqv?`인지 확인한다.(R5RS sec. 6.1)[4]


스킴에는 유형에 따라 달라지는 동등성 연산자도 있다. `string=?`와 `string-ci=?`는 두 문자열을 비교하고 (후자는 대소문자를 구분하지 않는 비교를 수행한다), `char=?`와 `char-ci=?`는 문자를 비교하며, `=`는 숫자를 비교한다.[4]

4. 9. 주석

R5RS 표준까지 스킴의 표준 주석은 세미콜론(;)이었다. 세미콜론을 사용하면 해당 줄의 나머지 부분을 스킴에서 인식하지 못한다.[28] R6RS 표준에서는 두 가지 새로운 주석 규칙을 허용한다. `#;`를 앞에 붙여 전체 S-표현식을 주석 처리할 수 있으며, `#|` 와 `|#`로 텍스트를 묶어 여러 줄 주석 또는 "블록 주석"을 만들 수 있다.[28]

4. 10. 입출력

스킴의 입출력은 ''포트'' 데이터 유형을 기반으로 한다. (R5RS 6.6절)[4] R5RS는 `current-input-port`와 `current-output-port` 프로시저를 통해 접근할 수 있는 두 개의 기본 포트를 정의하며, 이는 유닉스의 표준 입력과 표준 출력 개념에 해당한다. 대부분의 구현은 `current-error-port`도 제공한다. 표준에서는 `with-input-from-file` 및 `with-output-to-file`과 같은 표준 프로시저를 통해 입력 및 표준 출력의 리다이렉션을 지원한다. 대부분의 구현은 SRFI 6에 설명된 프로시저를 사용하여 파일 대신 문자열 버퍼에서 많은 일반적인 입출력 연산을 수행할 수 있도록 하는 유사한 리다이렉션 기능을 갖춘 문자열 포트를 제공한다.[29]

다음은 엄격한 R5RS 스킴으로 작성된 예제들이다.
예제 1: 출력 기본값이 (current-output-port)인 경우:

```scheme

(let ((hello0 (lambda() (display "Hello world") (newline))))

(hello0))

```
예제 2: 1과 같지만, 선택적 포트 인수를 사용하여 출력 프로시저를 사용한다.

```scheme

(let ((hello1 (lambda (p) (display "Hello world" p) (newline p))))

(hello1 (current-output-port)))

```
예제 3: 1과 같지만, 출력이 새로 생성된 파일로 리다이렉션된다.

```scheme

;; NB: with-output-to-file은 R5RS의 선택적 프로시저이다.

(let ((hello0 (lambda () (display "Hello world") (newline))))

(with-output-to-file "helloworldoutputfile" hello0))

```
예제 4: 2와 같지만, 명시적인 파일 열기 및 포트 닫기를 사용하여 파일로 출력을 보낸다.

```scheme

(let ((hello1 (lambda (p) (display "Hello world" p) (newline p)))

(output-port (open-output-file "helloworldoutputfile")))

(hello1 output-port)

(close-output-port output-port))

```
예제 5: 2와 같지만, call-with-output-file을 사용하여 파일로 출력을 보낸다.

```scheme

(let ((hello1 (lambda (p) (display "Hello world" p) (newline p))))

(call-with-output-file "helloworldoutputfile" hello1))

```

입력에도 유사한 프로시저가 제공된다. R5RS 스킴은 `input-port?` 및 `output-port?` 술어를 제공한다. 문자 입출력을 위해 `write-char`, `read-char`, `peek-char` 및 `char-ready?`가 제공된다. 스킴 표현식의 쓰기 및 읽기를 위해 스킴은 `read` 및 `write`를 제공한다. 읽기 연산에서 입력 포트가 파일의 끝에 도달하면 반환되는 결과는 파일 끝 객체이며, 이는 `eof-object?` 술어를 사용하여 테스트할 수 있다.

표준과 함께 SRFI 28은 이름의 유래가 된 Common Lisp의 `format` 함수와 유사한 기본 형식 지정 프로시저를 정의한다.[30]

4. 11. 표준 프로시저의 재정의

R5RS 언어 표준에서는 프로그램이 내장 프로시저의 변수 바인딩을 변경하여 사실상 재정의할 수 있도록 허용했다.[4] 예를 들어, 아래 코드와 같이 `+`를 재정의하여 문자열과 숫자를 모두 처리하도록 확장할 수 있다.



(set! +

(let ((original+ +))

(lambda args

(apply (if (or (null? args) (string? (car args)))

string-append

original+)

args))))

(+ 1 2 3)

===> 6

(+ "1" "2" "3")

===> "123"



하지만 R6RS에서는 표준을 포함한 모든 바인딩이 특정 라이브러리에 속하며, 내보낸 모든 바인딩은 변경할 수 없게 되었다.[6] 따라서 변형을 통한 표준 프로시저의 재정의는 금지된다. 대신, 표준 프로시저의 이름으로 다른 프로시저를 가져오는 것이 가능하며, 이는 재정의와 유사한 효과를 낼 수 있다.

4. 12. 명명 규칙(Nomenclature) 및 명명 관례(Naming conventions)

표준 스킴에서 자료형을 변환하는 프로시저는 이름에 "->" 문자열을 포함하고, 술어는 "?"로 끝나며, 이미 할당된 데이터의 값을 변경하는 프로시저는 "!"로 끝나는 명명 규칙을 따른다. 스킴 프로그래머들은 이러한 명명 관례를 자주 따른다.

공식적인 맥락에서 람다 표현식이나 기본 프로시저를 지칭할 때 "함수(function)" 대신 "프로시저(procedure)"라는 용어를 사용한다. 그러나 일반적인 사용에서는 "프로시저"와 "함수"라는 단어를 서로 바꿔서 사용한다. 프로시저 적용은 공식적으로 ''결합''이라고도 한다.

다른 리스프와 마찬가지로, 스킴에서는 인수가 없는 프로시저를 지칭하기 위해 "thunk"라는 용어를 사용한다. "정미 꼬리 재귀(proper tail recursion)"라는 용어는 모든 스킴 구현이 꼬리 호출 최적화를 수행하여 무한히 많은 활성 꼬리 호출을 지원하는 속성을 지칭한다.[31][32]

5. 표준 형식(Standard forms) 및 프로시저(Standard procedures)

Scheme영어은 R5RS(1998년)[4]와 R6RS(2007년)[6] 표준에 의해 공식적으로 정의된다. 이들은 언어의 제어 구조를 제공하는 키워드와 함께 제공되는 구문인 표준 "형식"과 일반적인 작업을 수행하는 표준 프로시저를 설명한다.

다음 표는 Scheme영어의 표준 형식을 설명한다. 일부 형식은 언어의 단일 기능으로 쉽게 분류할 수 없기 때문에 여러 행에 나타난다.

R5RS 스킴 언어의 표준 형식
목적형식
정의
바인딩 구성, (L), (L), (L), (L)
조건부 평가, (L), (L), (L), (L)
순차적 평가(*)
반복, (L), (L)
구문 확장, , , (R5RS), (R6RS)
인용('''), (,), (`), (,@)
할당
지연된 평가(L)


  • `begin`은 R5RS에서 라이브러리 구문으로 정의되어 있지만, 스플라이싱 기능을 달성하기 위해 확장기가 이를 알아야 한다. R6RS에서는 더 이상 라이브러리 구문이 아니다.
  • "L"로 표시된 형식은 표준에서 파생된 "라이브러리" 형식으로 분류되며, 실제로 더 기본적인 형식을 사용하여 매크로로 구현되는 경우가 많아 다른 언어보다 구현 작업이 훨씬 쉽다.


다음 두 표는 R5RS Scheme영어의 표준 프로시저를 설명한다. R6RS는 훨씬 더 광범위하며 이러한 유형의 요약을 실용적이지 않다.

일부 프로시저는 언어의 단일 함수로 쉽게 분류할 수 없기 때문에 여러 행에 나타난다.

언어 R5RS Scheme의 표준 프로시저
목적프로시저
구성, , ,
동등성 술어, , , , , ,
타입 변환, , , , , , , , ,
숫자별도 표 참조
문자열, , , , , , , , , , , , , , , , , , , , ,
문자, , , , , , , , , , , , , , , , , , ,
벡터, , , , , , , ,
심볼, ,
쌍 및 리스트, , , , , , , , , , , , , , , , , , , , , , ,
정체성 술어, , , , , , , ,
연속(), , ,
환경, , , (optional)
입출력, , , , , , , , , , , , , , , , , , , (optional), (optional)
시스템 인터페이스(optional), (optional), (optional)
지연된 평가
함수형 프로그래밍, , ,
부울,



이름에 "-ci"가 포함된 문자열 및 문자 프로시저는 인자 간의 대소문자를 구분하지 않는 비교를 수행한다. 동일한 문자의 대문자 및 소문자 버전은 동일한 것으로 간주된다.

언어 R5RS Scheme의 표준 숫자 프로시저
목적프로시저
기본 산술 연산자, , , , , , , , , , ,
유리수, , ,
근사, , ,
정확성, , ,
부등식, , , ,
기타 술어, , , ,
최댓값 및 최솟값,
삼각법, , , , ,
지수,
복소수, , , , , ,
입출력,
타입 술어, , , ,



두 개 이상의 인수를 사용하는 `-` 및 `/`의 구현은 정의되어 있지만 R5RS에서 선택 사항으로 남겨둡니다.

6. 구현을 위한 스킴 요청 (Scheme Requests for Implementation, SRFI)

스킴은 핵심 언어를 작게 유지하면서 확장을 표준화하기 위해 "구현을 위한 스킴 요청"(Scheme Requests for Implementation, SRFI) 프로세스를 사용한다. 이 프로세스를 통해 확장 라이브러리가 확장 제안에 대한 논의를 거쳐 정의되므로 코드 이식성이 높아진다.[33]

다음은 다양한 구현에서 비교적 널리 지원되는 SRFI 목록이다.[33]

번호제목설명
0기능 기반 조건부 확장 구성
1리스트 라이브러리
4동종 숫자 벡터 데이터 유형
6기본 문자열 포트
8다중 값에 바인딩되는 수신
9레코드 유형 정의
13문자열 라이브러리
14문자 집합 라이브러리
16변수 인자의 프로시저에 대한 구문
17일반화된 set!
18멀티스레딩 지원
19시간 데이터 유형 및 프로시저
25다차원 배열 기본 요소
26커링 없이 매개변수 특수화를 위한 표기법
27난수 비트 소스
28기본 형식 문자열
29지역화
30중첩된 여러 줄 주석
31재귀 평가를 위한 특수 형식
37args-fold: 프로그램 인수 프로세서
39매개변수 객체
41스트림
42즉시 컴프리헨션
43벡터 라이브러리
45반복적인 게으른 알고리즘을 표현하기 위한 기본 요소
60비트로서의 정수
61보다 일반적인 cond 절
66옥텟 벡터
67비교 프로시저



스킴은 언어 기능을 최소화하는 것을 목표로 하기 때문에 명세가 간소하다. 이로 인해 실용적인 측면에서 다양한 라이브러리가 사용되어 이식성 문제가 발생한다. 이러한 문제를 해결하기 위해 구현 간 통일을 위한 커뮤니티 논의를 "Scheme Requests for Implementation (SRFI)영어" (SRFI)를 통해 진행한다. SRFI는 라이브러리 및 언어 확장 사양 등을 정리하며, SRFI를 준수하는 구현은 "◯◯에 준거"와 같이 표시하여 사용자 편의를 제공한다.

스킴은 언어 기능과 라이브러리 기능을 분리해서 생각하므로 SRFI와 스킴 언어 사양 커뮤니티는 원칙적으로 분리되어 있다.

7. 구현체(Implementations)

스킴은 우아하고 미니멀한 디자인 덕분에 언어 설계자, 취미 활동가, 교육자들에게 인기 있는 프로그래밍 언어가 되었다.[34] 전형적인 인터프리터의 작은 크기는 임베디드 시스템스크립팅에 널리 사용되도록 한다. 그러나 수많은 구현체가 등장하면서, 구현체 간 프로그램 이식성이 매우 어려워졌다.[14] 표준 언어의 작은 크기 때문에 표준적이고 이식 가능한 스킴으로 복잡하고 유용한 프로그램을 작성하는 것은 거의 불가능하다.[14] R6RS 표준은 이러한 문제를 해결하고 프로그래머에게 더 넓은 매력을 제공하기 위해 더 광범위한 언어를 지정한다.

대부분의 구현체는 개발 및 디버깅을 위해 전통적인 Lisp 스타일의 REPL을 제공하며, 많은 구현체가 스킴 프로그램을 실행 가능한 바이너리로 컴파일한다. 스킴은 상대적으로 구현이 단순하여 C와 같은 다른 언어로 개발된 시스템에 스크립팅 기능을 추가하는 데 널리 사용된다. 따라서 다른 언어로 작성된 프로그램에 스킴 코드를 포함하는 기능도 일반적이다. 갬빗, 치킨, 빅루와 같은 스킴 인터프리터는 스킴을 C로 컴파일하여 임베딩을 쉽게 만든다. 빅루 컴파일러는 자바 가상 머신 (JVM)용 바이트코드를 생성하도록 구성할 수 있으며, .NET용 실험적인 바이트코드 생성기도 있다.

일부 구현체는 추가 기능을 지원한다. 예를 들어, 카와 및 JScheme은 자바 클래스와의 통합을 제공하며, 스킴-C 컴파일러는 C로 작성된 외부 라이브러리를 쉽게 사용할 수 있도록 한다. Pvts는 스킴 학습을 지원하는 시각적 도구를 제공한다.

다음은 몇 가지 스킴 구현체 목록이다.


  • '''Bigloo''': 고속 실행 파일을 만드는 컴파일러이다.
  • '''BiwaScheme''': JavaScript로 구현되어 브라우저에서 동작한다.
  • '''Chez Scheme''': 원래 상용이었지만 현재는 오픈 소스인 고속 구현체이다.
  • '''Chicken''': 이식성이 높은 실용적인 컴파일러이다.
  • '''Gauche''': 인터프리터이며, 다국어 지원과 STklos영어를 발전시킨 (메타)객체 시스템을 갖는다.
  • '''Gambit''' (영문판): Scheme 인터프리터 및 Scheme→C 컴파일러이다.
  • '''GNU Guile''': GNU의 공식 확장 언어이며, 스킴을 기반으로 한다.
  • '''HScheme'''
  • '''IronScheme'''
  • '''Jscheme'''
  • '''JAKLD''': Java영어 애플리케이션 내장용 LISP영어 드라이버이다.
  • '''Kawa''': GNU 프로젝트의 하나로, 스킴 프로그램을 Java영어 가상 머신용으로 컴파일할 수 있다.
  • '''Larceny''': IA-32, SPARC영어의 기계어를 출력하며, IEEE/ANSI, R5RS, ERR5RS, R6RS를 준수한다.
  • '''LispMe''': Palm OS영어용 구현이며, 무료이다.
  • '''MIT Scheme''': x86 아키텍처용 스킴 구현이며, 무료이다.
  • '''Mosh Mosh''': R6RS 준수의 고속 인터프리터이며, FFI, 소켓 등의 확장 기능을 제공한다.
  • '''Ocs'''
  • '''PocketScheme''': Windows CE영어용 구현이다.
  • '''Racket''': 구칭 PLT Scheme영어이며, 교육용의 화려한 개발 환경과 유연한 시스템으로 널리 사용된다.
  • '''QScheme'''
  • '''rhizome/pi'''
  • '''Scheme48'''
  • '''SECDR-Scheme''': Lispkit Lisp영어 확장에 의한 (병렬) 스킴이다.
  • '''SigScheme''': 애플리케이션 내장을 목적으로 하는 R5RS 준수 구현이며, uim에서 사용되고 있다.
  • '''SISC''': Second Interpreter of Scheme Code영어의 약자로, Java영어 가상 머신에서 동작하는 R5RS 준수 구현이다. Java영어 객체를 스킴 상에서 이용할 수 있다.
  • '''TinyScheme''': 매우 작은 구현으로, Zaurus영어 등에서도 실행된다. 정규 표현식과 소켓 통신도 지원한다.
  • '''Vx-scheme''': VxWorks영어 용 구현이다.
  • '''Ypsilon''': R6RS를 준수하는 실시간 애플리케이션용 구현이다.

8. 활용(Usage)

스킴은 여러 학교에서 널리 사용된다. 특히, 몇몇 초급 컴퓨터 과학 수업에서는 교재 ''프로그래밍의 구조와 해석(SICP)''과 함께 스킴을 사용한다.[36] PLT는 ProgramByDesign(구 TeachScheme!) 프로젝트를 운영해 왔으며, 이 프로젝트는 600명에 가까운 고등학교 교사와 수천 명의 고등학생들에게 기본적인 스킴 프로그래밍을 접하게 했다. MIT의 이전 초급 프로그래밍 수업 6.001은 스킴으로 진행되었다.[37] 6.001은 더 현대적인 코스로 대체되었지만, SICP는 MIT에서 계속 가르치고 있다.[38] UC 버클리의 초급 수업 CS 61A는 2011년까지 완전히 스킴으로 가르쳐졌다. 오늘날 버클리는 MIT와 마찬가지로 커리큘럼을 주로 파이썬 3으로 가르치는 더 현대적인 버전으로 대체했지만, 현재 커리큘럼은 여전히 과거 커리큘럼을 기반으로 하며, 수업의 일부는 여전히 스킴으로 가르쳐진다.[39]

매티아스 펠라이젠(Matthias Felleisen)의 교재 ''프로그램 설계 방법''은 현재 노스이스턴 대학교에서 초급 컴퓨터 과학 수업에 사용된다. 노스이스턴 대학교와 우스터 폴리테크닉 연구소는 각각 초급 과정인 컴퓨터 과학의 기초(CS2500)와 프로그램 설계 입문(CS1101)에 스킴을 독점적으로 사용한다.[40][41] 로즈-헐먼 공과대학은 좀 더 진보된 프로그래밍 언어 개념 과정에서 스킴을 사용한다.[42] 브랜다이스 대학교의 핵심 과정인 컴퓨터 프로그램의 구조와 해석(COSI121b)도 이론 컴퓨터 과학자 해리 메이슨이 스킴으로만 가르친다.[43] 인디애나 대학교의 초급 수업인 C211은 완전히 스킴으로 가르쳐진다. CS 61AS는 이 수업의 자율 학습 버전이며, 스킴을 계속 사용한다.[44] 예일 대학교그리넬 칼리지의 초급 컴퓨터 과학 수업도 스킴으로 가르쳐진다.[45] 노스이스턴 대학교의 컴퓨터 과학 대학원생을 위한 필수 과목인 프로그래밍 설계 패러다임[46]도 스킴을 광범위하게 사용한다.

미네소타 대학교-트윈 시티의 이전 초급 컴퓨터 과학 과정인 CSCI 1901도 스킴을 주 언어로 사용했으며, 그 다음 과정에서는 학생들에게 자바 언어를 소개했다.[47] 그러나 MIT의 사례를 따라, 해당 학과는 1901을 파이썬 기반의 CSCI 1133으로 대체했고,[48] 기능적 프로그래밍은 3학기 과정인 CSCI 2041에서 자세히 다루어진다.[49]

스킴은 또한 다음과 같은 용도로 사용되었거나 사용되고 있다.


  • 문서 스타일 시맨틱스 및 명세 언어(DSSSL)는 SGML 스타일 시트를 지정하는 방법을 제공하며, 스킴의 서브셋을 사용한다.[50]
  • 오픈 소스 래스터 그래픽 편집기 GIMP는 TinyScheme를 스크립팅 언어로 사용한다.[51]
  • Guile는 GNU 프로젝트에 의해 공식적인 스크립팅 언어로 채택되었으며, 스킴의 이러한 구현은 GNU LilyPond 및 GnuCash와 같은 응용 프로그램에 확장 기능용 스크립팅 언어로 내장되어 있다. 마찬가지로, Guile는 데스크톱 환경 GNOME의 스크립팅 언어로 사용되었으며,[52] GNOME은 여전히 라이브러리 스택에 대한 Guile 바인딩을 제공하는 프로젝트를 가지고 있다.[53]
  • Elk Scheme는 시놉시스에서 기술 CAD(TCAD) 도구용 스크립팅 언어로 사용된다.[54]
  • 영화 ''파이널 판타지: 더 스피릿츠 위딘''의 수석 프로그래머인 카와이 시로(Shiro Kawai)는 실시간 렌더링 엔진을 관리하기 위한 스크립팅 언어로 스킴을 사용했다.[55]
  • 안드로이드용 구글 앱 인벤터는 스킴을 사용하며, 여기서 Kawa는 안드로이드 기기에서 실행되는 자바 가상 머신에 대한 바이트코드로 스킴 코드를 컴파일하는 데 사용된다.[56]

참조

[1] 웹사이트 Influences - The Rust Reference https://doc.rust-lan[...] 2023-04-18
[2] 서적 Common LISP: The Language, 2nd Ed. Digital Press 1981
[3] 간행물 1178-1990 (Reaff 2008) IEEE Standard for the Scheme Programming Language https://web.archive.[...] IEEE 2008-03-26
[4] 논문 Revised5 Report on the Algorithmic Language Scheme http://www.schemers.[...] 2012-08-09
[5] 웹사이트 R7RS final available http://trac.sacrideo[...] 2013-07-06
[6] 웹사이트 Revised6 Report on the Algorithmic Language Scheme (R6RS) http://www.r6rs.org Scheme Steering Committee 2011-09-13
[7] 논문 The First Report on Scheme Revisited 1998-12-01
[8] 웹사이트 R6RS Implementations http://www.r6rs.org/[...] r6rs.org 2017-11-24
[9] 웹사이트 R6RS Libraries and syntax-case system (psyntax) https://www.cs.india[...] Ikarus Scheme 2009-10-20
[10] 논문 A run-time representation of scheme record types 2014-11
[11] 웹사이트 Revised^6 Report on the Algorithmic Language Scheme, Appendix E: language changes http://www.r6rs.org/[...] Scheme Steering Committee 2009-10-20
[12] 웹사이트 R6RS Electorate http://www.r6rs.org/[...] Scheme Steering Committee 2012-08-09
[13] 웹사이트 Implementors' intentions concerning R6RS http://lists.r6rs.or[...] Scheme Steering Committee, r6rs-discuss mailing list 2012-08-09
[14] 웹사이트 Position Statement ''(draft)'' http://scheme-report[...] Scheme Steering Committee 2012-08-09
[15] 웹사이트 R7RS 9th draft available http://trac.sacrideo[...] 2013-04-15
[16] 웹사이트 extension of voting period http://lists.scheme-[...] Scheme Language Steering Committee, scheme-reports mailing list 2013-07-07
[17] 웹사이트 The Incomplete Scheme 48 Reference Manual for release 1.8 http://s48.org/1.8/m[...] Jonathan Rees, s48.org 2012-08-09
[18] 논문 Scheme: An Interpreter for Extended Lambda Calculus https://dspace.mit.e[...] MIT AI Lab 2021-12-23
[19] 간행물 The Function of FUNCTION in LISP, or Why the FUNARG Problem Should Be Called the Environment Problem 1970-06
[20] 논문 A Lambda Calculus for Quantum Computation 2004-01-01
[21] 논문 A concurrent lambda calculus with futures https://hal.inria.fr[...] 2006-11
[22] 논문 Lambda: The Ultimate Imperative http://library.reads[...] MIT AI Lab 2012-08-09
[23] 뉴스 Technical Issues of Separation in Function Cells and Value Cells http://www.nhplace.c[...] 2012-08-09
[24] 웹사이트 SRFI 41: Streams http://srfi.schemers[...] The SRFI Editors, schemers.org 2012-08-09
[25] 논문 Revised4 Report on the Algorithmic Language Scheme http://www.cs.indian[...] 2012-08-09
[26] 서적 Proceedings of the 43rd Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages
[27] 문서 The Scheme of Things The June 1992 Meeting http://mumble.net/~j[...] 2011-07-16
[28] 웹사이트 SRFI 62: S-expression comments http://srfi.schemers[...] The SRFI Editors, schemers.org 2012-08-09
[29] 웹사이트 SRFI 6: Basic String Ports http://srfi.schemers[...] The SRFI Editors, schemers.org 2012-08-09
[30] 웹사이트 SRFI 28: Basic Format Strings http://srfi.schemers[...] The SRFI Editors, schemers.org 2012-08-09
[31] 논문 Revised Report on the Algorithmic Language Algol 60 http://www.masswerk.[...] 2012-08-09
[32] 논문 Revised(3) Report on the Algorithmic Language Scheme (Dedicated to the Memory of ALGOL 60) http://groups.csail.[...] 2012-08-09
[33] 웹사이트 Scheme Systems Supporting SRFIs http://srfi.schemers[...] The SRFI Editors, schemers.org 2012-08-09
[34] 웹사이트 scheme-faq-standards http://community.sch[...] Community Scheme Wiki 2009-10-20
[35] 웹사이트 List of Scheme-using schools http://www.schemers.[...] Schemers Inc. 2009-10-20
[36] 웹사이트 List of SICP-using schools http://mitpress.mit.[...] MIT Press 2009-10-20
[37] 웹사이트 6.001 Structure and Interpretation of Computer Programs http://ocw.mit.edu/O[...] MIT Open Courseware 2009-10-20
[38] 웹사이트 6.184 - Zombies drink caffeinated 6.001 http://web.mit.edu/a[...] MIT CSAIL 2009-10-20
[39] 웹사이트 Computer Science 61A, Berkeley https://cs61a.org/ar[...] Department of Electrical Engineering and Computer Sciences, Berkeley 2019-12-17
[40] 뉴스 CS 2500: Fundamentals of Computer Science I http://www.ccs.neu.e[...] Northeastern University
[41] 뉴스 CS 1101: Introduction to Program Design (A05): course software http://web.cs.wpi.ed[...] Worcester Polytechnic Institute
[42] 웹사이트 CSSE 304: Programming Language Concepts https://www.rose-hul[...] Rose-Hulman Institute of Technology
[43] 웹사이트 Spring 2021 CS121b Syllabus https://moodle2.bran[...] Brandeis University
[44] 웹사이트 Home https://berkeley-cs6[...]
[45] 웹사이트 Introduction to Computer Science (CPSC 201) http://zoo.cs.yale.e[...] The Zoo, Yale University Computer Science Department 2009-10-20
[46] 웹사이트 Programming Design Paradigms CSG107 Course Readings http://www.ccs.neu.e[...] Northeastern University College of Computer and Information Science 2012-08-09
[47] 뉴스 Structure of Computer Programming I http://www-users.itl[...]
[48] 뉴스 CSci Required Class Course Descriptions and Other Information https://www.cs.umn.e[...]
[49] 뉴스 CSCI 2041—New Course https://www.csdy.umn[...] CSE Curriculum Committee, University of Minnesota
[50] 웹사이트 DSSSL - Document Style Semantics and Specification Language. ISO/IEC 10179:1996 http://xml.coverpage[...] Cover Pages 2012-08-09
[51] 웹사이트 The GIMP Basic Scheme Tutorial http://www.gimp.org/[...] The GIMP Team 2012-08-09
[52] 웹사이트 GNOME FAQ from Internet Archive http://www.gnome.org[...] The Gnome Team, gnome.org 2012-08-09
[53] 웹사이트 guile-gnome https://www.gnu.org/[...] Free Software Foundation 2012-08-09
[54] 웹사이트 Synopsys MAP-inSM Program Update: EDA Interoperability Developers' Forum http://www.synopsys.[...] Synopsis Inc 2012-08-09
[55] 간행물 Gluing Things Together - Scheme in the Real-time CG Content Production http://practical-sch[...] 2012-08-09
[56] 웹사이트 Under the Hood of App Inventor for Android http://googleresearc[...] Google Inc, Official Google Research blog 2012-08-09
[57] 웹사이트 Influences - The Rust Reference https://doc.rust-lan[...] 2023-04-18
[58] 문서 元々のALGOLには関数引数等が無いためFUNARG問題なども無く、静的スコープの歴史としてALGOLをあまり強調する意味は無い。
[59] 문서 closure
[60] 문서 lambda calculus
[61] 문서 tail-recursion
[62] 문서 continuation
[63] 문서 message passing
[64] 문서 continuation passing style、CPS
[65] 문서 継続渡し形式は一連のλ論文において導入された。ただし、体系として確立されてはいないものの、同様の手法は「John C. Reynolds, 1972, Denitional Interpreters for Higher-Order Programming Languages(http://cs.au.dk/~hosc/local/HOSC-11-4-pp363-397.pdf)」にもみられる。
[66] 문서 後の完全な Planner の実装として、エジンバラ大学の Julian Davies が POP-2 で実装した Popler がある。
[67] 웹사이트 From LISP 1 to LISP 1.5 https://www-formal.s[...] 2024-04-08
[68] 문서 「Scheme 過去◇現在◇未来 前編」『bit』(共立出版)Vol. 28, No.4(1996年4月号) pp. 4~9
[69] 간행물 Shallow binding in Lisp 1.5 https://doi.org/10.1[...] Association for Computing Machinery 1978-07
[70] 문서 当初は CATCH という名称であった。
[71] 문서 escape operator
[72] 간행물 "1178-1990 (Reaff 2008) IEEE Standard for the Scheme Programming Language. IEEE part number STDPD14209, unanimously reaffirmed at a meeting of the IEEE-SA Standards Board Standards Review Committee (RevCom), March 26, 2008 (item 6.3 on minutes), reaffirmation minutes accessed October 2009. NOTE: this document is only available for purchase from IEEE and is not available online at the time of writing (2009)." http://standards.iee[...]
[73] 웹사이트 The Revised6 Report on the Algorithmic Language Scheme http://www.r6rs.org/ 2009-02-02
[74] 웹사이트 Position statement http://scheme-report[...] 2013-12-16
[75] 웹사이트 Scheme Working Groups http://trac.sacrideo[...] 2013-12-16
[76] 웹사이트 Gluing Things Together - Scheme in the Real-time CG Content Production http://practical-sch[...] 2002-10
[77] 웹사이트 YPSILON http://www.littlewin[...] 2014-06-20
[78] 문서 Online version of the Lambda Papers http://library.reads[...]
[79] 보고서 Scheme: An Interpreter for Extended Lambda Calculus http://hdl.handle.ne[...]
[80] 학술지 Scheme: A interpreter for extended lambda calculus https://www.research[...] Springer



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

문의하기 : help@durumis.com