Schemat
Schemat | |
---|---|
Podstawowe dane | |
Paradygmaty : | Wieloparadygmat : funkcjonalny , proceduralny , meta |
Rok wydania: | 1975 |
Projektant: | Guy Lewis Steele junior , Gerald Jay Sussman |
Deweloper: | Guy L. Steele i Gerald Jay Sussman |
Aktualna wersja : | R 7 RS (norma ratyfikowana) (2013) |
Pisanie : | silny , dynamiczny |
Ważne realizacje : | wiele z. B. Schemat MIT/GNU |
Wpływem: | Lisp , ALGOL , MDL |
Dotknięty: | Wspólne Lisp , JavaScript , R , Rubin , Dylan , Lua , Rakieta , Pstryknięcie ! / BYOB |
www.scheme-reports.org |
Język programowania Scheme jest odmianą Lisp . Jest funkcjonalny , ale obsługuje również inne paradygmaty programowania (np. programowanie imperatywne ).
Schemat charakteryzuje się tym, że składnia określa tylko kilka koncepcji programistycznych . Istnieje zatem stosunkowo duża liczba sposobów, w jakie program można opisać w Schemacie.
Na przykład w standardzie Scheme nie ma narzędzi do programowania obiektowego, ale bardzo łatwo jest je zaprogramować w tym języku dzięki makrom i wyrażeniom λ : Scheme to programowalny język programowania, który można później rozszerzyć.
Schemat został opracowany przez Geralda Jaya Sussmana i Guya Lewisa Steele Jr. w Massachusetts Institute of Technology , gdzie dostępna jest również formalna specyfikacja , tzw. Revised Report . Aktualna specyfikacja to R 7 RS.
Składnia i semantyka
Składnia Schematu jest bardzo regularne i proste. Podstawą jest notacja przedrostkowa w pełnym nawiasie (patrz też notacja polska ). Program składa się z wyrażeń i definicji. Wyrażenia to literały lub wyrażenia złożone reprezentujące wywołanie funkcji:
(operator operand-1 operand-2 ... operand-n)
Każdy element wyrażenia złożonego jest z kolei wyrażeniem.
Znaczenie (lub semantykę) wyrażeń określa ich ocena . Znaczenie (semantyka) wyrażenia dosłownego jest stałą wartością wyrażenia. Na przykład ciąg ma 2
wartość liczby 2, a ciąg #t
ma wartość logiczną „prawda”. Podczas obliczania wyrażeń złożonych wyrażenie operator
(oparte na operatorach matematycznych ) musi dawać w wyniku funkcję. Na prawo od operatora znajduje się dowolna liczba operandów , które z kolei są formami prostymi lub złożonymi.
Dlatego nawiasy mają szczególne znaczenie i, w przeciwieństwie do większości innych języków programowania, nie można ich ustawiać dowolnie. Forma złożona
(foo 42)
na przykład jest wyrażeniem, które na poziomie semantycznym oznacza wywołanie foo
funkcji powiązanej ze zmienną z argumentem 42
. Ocena wyrażenia
(foo (42))
jednak prowadzi to do błędu w czasie wykonywania: (42)
jest to forma złożona, a semantyka zapewnia użycie operatora. Jednak ponieważ 42
jest to liczba, a nie funkcja, pojawia się błąd.
Jedną z zalet notacji przedrostkowej w pełnym nawiasie jest to, że notacja ta ma tylko jeden precedens dla wszystkich operatorów . Powszechna krytyka składni Scheme dotyczy dużej liczby nawiasów, które utrudniają tworzenie i edycję kodu źródłowego. Programiści schematów przeciwdziałają tej trudności, używając edytorów, które w specjalny sposób wspierają przetwarzanie tekstów źródłowych schematów (np. Emacs ). Pomoce te obejmują automatyczne wcinanie kodu i zaznaczanie par nawiasów, które należą do siebie podczas edycji.
Niektóre implementacje Scheme, takie jak Racket, pozwalają na użycie nawiasów kwadratowych oprócz standardu językowego. Ma to na celu zwiększenie przejrzystości. Przykład:
(let ([x 42]
[y 23])
(+ x y))
Forma specjalna lambda
Słowo kluczowe lambda wprowadza specjalną formę dla tak zwanych wyrażeń lambda. Wyrażenie lambda oblicza procedurę, która jest wartością pierwszej klasy w schemacie. Procedury mogą więc być używane w programie jak wartości innych typów, np. powiązane z nazwami, przekazywane jako argumenty w wywołaniu procedury lub zwracane przez procedurę.
Definicja specjalnej formy lambda:
(wyrażenie lambda (argument))
(lambda (x) (* x x)) ; Bildet das Quadrat von x
Wywołanie procedury wygenerowanej przez powyższe wyrażenie lambda:
((lambda(x) (* x x)) 5) ; Bildet das Quadrat von 5
; (Rückgabe = 25)
Nazwa tej specjalnej formy wywodzi się z rachunku lambda .
Definicje globalne
Definicja ze słowem kluczowym define
wiąże wartość z nazwą. Nazwa jest powiązana globalnie, więc może być używana w dowolnym miejscu programu po definicji. Ponieważ procedury w Scheme są również wartościami, define
można również zdefiniować procedury globalne. W poniższej sekcji kodu nazwa jest a-number
powiązana z liczbą 42, a następnie nazwa jest powiązana square
z funkcją podnoszącą liczbę do kwadratu:
(define a-number 42)
(define square
(lambda (x)
(* x x)))
Uproszczoną notację można również wykorzystać do zdefiniowania procedur globalnych, w których lambda
wyrażenie jest pomijane. Powyższą definicję square
można zapisać w formie skróconej w następujący sposób:
(define (square x)
(* x x))
Poniższe wyrażenie przedstawia przykład, w jaki sposób funkcja może zwrócić inną funkcję:
(define (sum-with x)
(lambda (y) (+ y x)))
Parametr x funkcji sum-z określa, jak zachowuje się zwracana funkcja: Zwracana funkcja dodaje argument y dokładnie przez współczynnik x określony w sum-z.
((sum-with 5) 1)
; (Rückgabe = 6)
Lokalne więzi
Deklaracja zmiennych i funkcji w schemacie jest nieco inna niż w tradycyjnych językach programowania. Po pierwsze zmienne i funkcje (procedury) nie muszą być powiązane z identyfikatorami , z drugiej strony deklaracja odbywa się za pomocą procedur, nie ma oddzielnych słów kluczowych.
Dla deklaracji dostępne są formularze define i let ; w razie potrzeby zamiast let można użyć wariacji let * i letrec .
pozwolić
let
wiąże kilka wartości z określonym identyfikatorem. Wiązania te są let
widoczne tylko od wewnątrz kadłuba . let
ma następującą składnię:
(let ((name-1 ''ausdruck-1'')
(name-2 ''ausdruck-2'')
...
(name-n ''ausdruck-n''))
...
; Rumpf des let-Ausdrucks
; name-1, ..., name-n sind nur innerhalb des Rumpfes von '''let''' gebunden
...
)
Wyrażenia ausdruck-1
do ausdruck-n
są oceniane w nieokreślonej kolejności, zanim wynikowe wartości zostaną powiązane z odpowiednimi nazwami. Następnie let
oceniana jest treść wyrażenia. Wiązania name-1
do zastosowania tylko w kadłubie name-n
. W szczególności nie jest let
możliwe użycie innej nazwy w wyrażeniu, które jest połączone w tym samym wyrażeniu (por . ).
ausdruck-i
let
let*
Wartość ostatniego wyrażenia w treści daje wartość całego let
wyrażenia. Ponieważ kolejność oceny wyrażeń nie jest stała i teoretycznie nawet wszystkie wyrażenia mogą być oceniane w tym samym czasie, mówi się o paraleli .
ausdruck-i
let
Przykłady:
(let ((a 3)
(b (+ 10 12))
(c (lambda (n) (* n 2))))
(c (+ a b)))
=> 50
(let ((a 1))
(let ((a 0)
(b a))
b))
=> 1
let
to uproszczona składnia tłumaczona na wywołanie funkcji. Przykład:
(let ((a (+ 1 1)) (b (+ 2 2)))
(+ a b))
rozszerza się do:
((lambda (a b) (+ a b)) (+ 1 1) (+ 2 2))
pozwolić *
let*
ma taką samą składnię let
i podobną semantykę. W przeciwieństwie do let
, let*
kolejność, w której wyrażenia są oceniane w parach nazwa-wyrażenie, jest stała: ocena jest przeprowadzana od lewej do prawej. Mówi się zatem o sekwencyjnymlet*
. W przeciwieństwie do let
, w wyrażeniach (po prawej stronie par nazwa-wyrażenie) można uzyskać dostęp do nazw par wiążących dalej w lewo.
Przykład:
(let ((a 1))
(let* ((a 0)
(b a))
b))
=> 0
How let
jest również let*
uproszczoną składnią i przekłada się na zagnieżdżone wywołania funkcji:
(let* ((a (+ 1 1))
(b (+ a 1)))
(* a b))
rozszerza się do:
((lambda (a)
((lambda (b) (* a b)) (+ a 1)))
(+ 1 1))
letrec i nazwany let
letrec
Wyrażenia mają taką samą składnię jak let
wyrażenia. Istnieją jednak pewne różnice w widoczności wiązanych nazwisk. Nazwy (czyli lewe strony par wiążących) mogą być używane w dowolnym wyrażeniu par wiążących. let*
Dobrze znane ograniczenia, że w nazwach wyrażenie może odnosić się tylko do poprzedniej (to znaczy bardziej w lewo), nazwy związku z tym nie może być stosowana. W szczególności może służyć letrec
do definiowania lokalnych funkcji rekurencyjnych. Przykład:
(letrec ((sum (lambda (lst s)
(if (null? lst)
s
(sum (cdr lst) (+ s (car lst)))))))
(sum (list 1 2 3) 0))
=> 6
Wzajemnie rekurencyjne funkcje można również zdefiniować:
(letrec ((even? (lambda (n)
(if (zero? n)
#t
(odd? (- n 1)))))
(odd? (lambda (n)
(if (zero? n)
#f
(even? (- n 1))))))
(even? 42))
=> #t
Wariantem letrec
jest tzw. namedlet
, który jest używany zwłaszcza do programowania pętli. Składnia to
(let ''name'' (''bindungen'') ''rumpf'')
, gdzie znajdują bindungen
się let
pary znane z nazwy i wyrażenia. Ciało namedlet
jest używane jako treść procedury o nazwie, name
która ma dokładnie tyle argumentów, ile jest określonych par wiążących. Nazwanylet
jest makro, które name
rozszerza się do wywołania tej procedury . Jako argumenty używane są prawe strony par wiążących. Przykład dla letrec
może być napisany z taką nazwąlet
:
(let sum ((lst (list 1 2 3))
(s 0))
(if (null? lst)
s
(sum (cdr lst) (+ s (car lst)))))
definiować
define
jest używany głównie do deklarowania funkcji i stałych na poziomie globalnym, ale może być również używany w ciele procedur. Widoczność tak połączonych zmiennych jest ograniczona do ciała, w którym znajduje się definicja. define
, które nie są na poziomie globalnym , otrzymują wewnętrzne definicje i są czasami letrec
używane zamiast jednej dla lepszej czytelności .
Składnia to:
(define bezeichner ausdruck)
Termin może również dotyczyć identyfikatora rekurencyjnego .
W tym przykładzie foo
i bar
są zdefiniowane wewnętrznie. Obie zmienne są widoczne tylko w treści let
wyrażenia.
(let ((x 5))
(define (foo y)
(bar x y))
(define (bar a b)
(+ (* a b) a))
(foo (+ x 3)))
Powyższy kod odpowiada tej wersji z letrec
:
(let ((x 5))
(letrec ((foo (lambda (y) (bar x y)))
(bar (lambda (a b) (+ (* a b) a))))
(foo (+ x 3))))
Typy danych
Procedury
Procedury są jednym z najważniejszych elementów językowych programu Scheme. Można je opisać wyrażeniem lambda ( lambda ). Ponieważ są one traktowane jak każdy inny typ danych w Scheme, możliwe jest powiązanie ich z identyfikatorem za pomocą let lub define .
Przykład: procedura z dwoma argumentami:
(define test
(lambda (arg1 arg2)
... ))
Istnieje uproszczona notacja, której można użyć do połączenia wyrażeń define i lambda :
(define (test arg1 arg2)
...)
Ta procedura nazywa się następująco:
(test wert1 wert2)
Wywołania procedur muszą być na ogół ujęte w dwóch nawiasach. Schemat podkreśla rolę wyrażeń, które mają wartość w porównaniu z poleceniami, które coś robią. Dlatego – w przeciwieństwie do wielu innych języków – nie jest konieczne zaznaczanie wyrażenia w treści opisu procedury jako wartości zwracanej. Wręcz przeciwnie: specjalne konstrukcje, takie jak begin są niezbędne do wykonania instrukcji bez zwracania ich wartości.
Oczywiście istnieje szereg predefiniowanych procedur takich jak cons , car , cdr , + , - , * , < . Te predefiniowane procedury można ponownie zdefiniować, jak pokazano w poniższym przykładzie:
(define (+ x y)
(- x y))
+ nie dodałby teraz, ale odejmij.
Ponieważ operatory matematyczne są również implementowane przez procedury, w obliczeniach istnieje notacja przedrostkowa . Schemat nie ma hierarchii operatorów, wszystkie formuły są unikalne.
Pary i listy
Listy są używane stosunkowo często w programach Scheme. Najważniejszym elementem składowym list w programie Scheme są pary . Para to struktura danych, która zawiera dowolne dwie wartości schematu. Wraz z cons
utworzeniem nowej pary. Przykład:
(cons 'sinn 42)
To wywołanie cons
tworzy nową parę, której pierwsze pole zawiera symbol, 'sinn
a drugie pole numer 42. Dostęp do pierwszego pola pary można uzyskać za pomocą funkcji wbudowanej car
(wymawiane: „carr”), drugie pole z cdr
(czyt.: "Kudder"). Nazwa car
( " C ontent o o DRES r egister"), a cdr
( " c ontent z d ecrement r egister") są zakorzenione w historii, ale otrzymuje się w ten sposób. Odnoszą się do operacji, które zostały użyte w pierwszej implementacji Lisp na IBM 704 . Wbudowane funkcje set-car!
i set-cdr!
ustawiają wartości odpowiednich pól pary na nową wartość. Predykat typu pair?
zwraca #t
(dla true) wtedy i tylko wtedy, gdy został zastosowany do pary, tj. cons
wartości, która została wygenerowana za pomocą .
Definicja list jest indukcyjna : lista pusta, napisana '()
, jest listą. Również para, która jest cdr
listą, jest listą. Definicja oznacza, że lista składa się z par: W car
polu pary znajduje się dowolna wartość, w cdr
polu para zawierająca kolejny element listy. Koniec listy zostaje osiągnięty, gdy w cdr
polu znajduje się pusta lista, co można null?
sprawdzić za pomocą wbudowanej funkcji . Przykłady list:
'()
(cons 1 '())
(cons 1 (cons 2 '()))
Istnieje również wygodna funkcja generowania list list
, która pobiera dowolną liczbę argumentów i zwraca je w postaci listy. Poniższe dwie listy są równoważne:
(list 1 2 3)
(cons 1 (cons 2 (cons 3 '())))
Funkcje przetwarzające listy są w większości funkcjami rekurencyjnymi. Funkcji tej można użyć np. do określenia długości listy:
(define (length lst)
(if (null? lst)
0
(+ 1 (length (cdr lst)))))
Programiści schematów prawie nigdy nie korzystają z możliwości zmiany pól pary za pomocą set-car!
lub set-cdr!
. Przetwarzanie list jest prawie zawsze czysto funkcjonalne , tj. H. nowe listy są generowane z list. Przykładem jest ta funkcja map
, która f
stosuje funkcję do wszystkich elementów listy:
(define (map f lst)
(if (null? lst)
'()
(cons (f (car lst)) (map f (cdr lst)))))
Inne typy danych
Inne typy danych obejmują:
- liczba całkowita (liczby całkowite, dowolna liczba cyfr)
- racjonalne (ułamki, dowolna precyzja)
- liczba rzeczywista ( liczby dziesiętne )
- Liczby zespolone
- Symbolika
- znak
- Smyczki
- Pary
- Wektory
- Port (reprezentacja urządzeń wejścia/wyjścia, plików itp.)
- Boole'a
prawda i fałsz są reprezentowane przez #t
i #f
, przy czym Scheme interpretuje tylko #f
(w przestarzałych implementacjach tylko synonim pustej listy '()
) jako logicznie fałsz; wszystkie inne wartości są uważane za prawdziwe.
Rozróżnienie przypadku
Gdyby
if
ocenia wyrażenie testowe i, w zależności od jego wartości logicznej, ocenia drugi argument ( consequent ) lub trzeci argument ( alternative ). Wartość całego wyrażenia If wynika z oceny następnika lub alternatywy. #f
Alternatywa jest oceniana tylko wtedy, gdy wyrażenie testowe ma wartość , w przeciwnym razie kolejne. TJ. każda wartość z wyjątkiem #f
jest uważana za logicznie prawdziwą.
Odpowiednie wyrażenie wygląda tak, na przykład:
(if (> x 0)
'positive
'not-positive)
To wyrażenie zwraca albo do symbolu 'positive
albo do symbolu 'not-positive
. Ponieważ If jest wyrażeniem, If można używać wewnątrz wyrażeń:
(* 2 (if (> x max) max x))
Warunek
Dzięki cond
temu możliwe jest rozróżnienie kilku przypadków. Przypadku składa się z testu i związany . Przypadki są przeglądane od lewej do prawej. Jeśli test nie #f
zwróci przypadku , obliczana jest odpowiednia konsekwencja: ta wartość daje następnie wartość całego cond
wyrażenia. Jeśli żaden z podanych przypadków nie ma zastosowania, oceniany jest inny case , jeśli istnieje . Jeśli nie ma innego przypadku, wartość cond
wyrażenia nie jest zdefiniowana. Przykład:
(cond ((= wert 65) 'a)
((= wert 66) 'b)
(else 'unbekannt))
wstążki
Scheme nie posiada żadnych konstrukcji języka programowania dla pętli (jednak automatycznie włączane „Biblioteki schematów standardowych” oferują możliwość tworzenia pętli na przykład z konstrukcją do). Pętle są zwykle implementowane przy użyciu rekurencyjnych wywołań funkcji . W najprostszym przypadku nieskończona pętla wygląda tak:
(define (loop)
(loop))
Przykładem często pokazywanym, aby to zademonstrować, jest obliczenie silni :
(define (fak n)
(if (= n 0) 1
(* n (fak (- n 1)))))
W celu praktycznej realizacji tej teoretycznie atrakcyjnej koncepcji, Scheme optymalizuje rekurencję trzpienia końcowego (lub bardziej ogólnie: wszystkie wywołania funkcji trzpienia końcowego). W przypadku nieterminalnej rekurencji funkcja nadal działa po samo wywołaniu . W przykładzie mnożenie:
(fak 4)
(* 4 (fak 3))
(* 4 (* 3 (fak 2)))
(* 4 (* 3 (* 2 (fak 1))))
(* 4 (* 3 (* 2 (* 1 (fak 0)))))
(* 4 (* 3 (* 2 (* 1 1))))
(* 4 (* 3 (* 2 1)))
(* 4 (* 3 2))
(* 4 6)
24
W trakcie procesu potrzeba coraz więcej miejsca (pamięci) do zapisania wyników pośrednich. Ogonowo-rekurencyjny wariant powyższego przykładu byłby następujący:
(define (fak-iter n a)
(if (= n 0) a
(fak-iter (- n 1) (* n a))))
(define (fak n)
(fak-iter n 1))
Proces wyglądałby wtedy tak:
(fak 4)
(fak-iter 4 1)
(fak-iter 3 4)
(fak-iter 2 12)
(fak-iter 1 24)
(fak-iter 0 24)
24
Scheme rozpoznaje, że wynik wywołania procedury jest zwracany tylko i dlatego może używać tej samej pamięci dla wszystkich wywołań procedury. Dodatkowa zmienna a w procedurze fak-iter akumuluje wyniki pośrednie.
Uwagi
Komentarze są poprzedzone średnikiem (;) i rozciągają się do końca linii.
Porównanie programu Scheme i LISP
Istnieją trzy główne cechy, które odróżniają Scheme od Lisp :
- W Scheme jest funkcja call-with-current-continuation . Pozwala na użycie bieżącej kontynuacji (tj. rodzaju stanu wykonania bieżącego programu ) jako zmiennej . Umożliwia to powrót do punktu tej kontynuacji w dalszej części przebiegu programu.
- Standard Scheme określa właściwą rekursję ogonową : wywołania procedur w końcowej pozycji rekurencyjnej nie mogą zajmować miejsca w pamięci na stosie wywołań programu. Oznacza to, że możliwa jest nieograniczona liczba końcowych rekurencyjnych wywołań procedury.
- W przeciwieństwie do LISP-a, makra w Scheme są „higieniczne”: identyfikatory wprowadzone w makrze nie ukrywają żadnych innych identyfikatorów w środowisku leksykalnym poza makro, tj. programem wywołującym. I odwrotnie, identyfikatory używane w makrze są zawsze rozwiązywane w środowisku leksykalnym makra, a nie na zewnątrz. Oznacza to, że identyfikator makra jest widoczny tylko dla samego makra i makro nie może uzyskać dostępu do identyfikatora programu wyższego poziomu, a program nie może uzyskać dostępu do wewnętrznego identyfikatora makra.
Wdrożenia i narzędzia programistyczne
Dostępna jest duża liczba implementacji języka programowania. Poniżej wymieniono tylko kilka popularnych implementacji:
- Bigloo tłumaczy kod Scheme na kilka innych języków: C , Java i .NET .
- Chicken to implementacja, która tłumaczy Scheme na C i dlatego działa na praktycznie wszystkich platformach. Zapewnia zarówno interpreter, jak i kompilator, a dzięki połączeniu z C posiada obszerną bibliotekę rozszerzeń. Implementacja jest w dużej mierze zgodna z R5RS.
- Oprócz interpretera Scheme , Gambit C posiada również jeden z najbardziej wydajnych kompilatorów Scheme-to-C .
- Gauche to implementacja zgodna z R5RS. Został zaprojektowany jako interpreter skryptów dla programistów i administratorów. Niektóre z celów rozwoju to krótki czas uruchamiania, wbudowany interfejs systemu, natywna obsługa wielu języków. Ponadto można zintegrować liczne rozszerzenia, m.in. B. dla OpenGL i GTK+ .
- GNU Guile to interpreter, który można zintegrować jako bibliotekę. Podstawowym celem jest możliwość łatwego dodawania funkcji skryptów do programów.
- LispMe jest implementacją dla PDA kompatybilnych z PalmOS.
- Racket (wcześniej PLT Scheme) to szeroko rozpowszechniona implementacja, która oprócz dużej liczby bibliotek zawiera własne środowisko programistyczne o nazwie DrRacket (wcześniej DrScheme). DrRacket jest specjalnie przystosowany do użycia w treningu programowania dla początkujących i jest łatwy w użyciu. Racket zawiera kilka kompilatorów, które konwertują kod Racket / Scheme na kod bajtowy lub C.
- Schemat 48 to implementacja Schematu napisana w całości w schemacie. Statycznie wpisane dialekt Program nazywa PreScheme jest używany do ładowania początkowego . Schemat 48 tłumaczy kod schematu na kod bajtowy, który można zapisać w obrazie pamięci. Schemat 48 jest szczególnie godny uwagi ze względu na jego zdolność do debugowania kodu schematu.
- SIOD. Mały, szybki interpreter schematów, który był używany w GIMP- ach ScriptFu do wersji 2.4.
literatura
- Hal Abelson , Gerald Jay Sussman: Struktura i interpretacja programów komputerowych . McGraw-Hill, ISBN 0-07-000422-6
- Abelson, Sussman: Struktura i interpretacja programów komputerowych . Springer-Verlag, ISBN 3-540-42342-7
- R. Kent Dybvig: Język programowania schematów . The MIT Press, ISBN 0-262-54148-3 ( 4 wydanie online )
- Iain Ferguson: Przewodnik intryganta . Schematy Inc., ISBN 0-9628745-2-3
- Daniel P. Friedman, Matthias Felleisen: Mały intrygant . Prasa MIT, ISBN 0-262-56099-2
- Friedman, Felleisen: Doświadczony intrygant . Prasa MIT, ISBN 0-262-56100-X
- Friedman, Felleisen: uzasadnionej Schemer . Prasa MIT, ISBN 0-262-56214-6
- Springer , Friedman: Schemat i sztuka programowania . Prasa MIT, ISBN 0-262-19288-8
- Herbert Klaeren, Michael Sperber: Siła abstrakcji: Wprowadzenie do programowania . Teubnera, ISBN 3-8351-0155-2
- Klaeren, Sperber: Od problemu do programu . Teubnera, ISBN 3-519-22242-6
- Jacques Chazarain: Programista ze schematem . Międzynarodowe wydawnictwo Thomson, Francja, ISBN 2-84180-131-4
linki internetowe
- schemers.org Zbiór materiałów na Scheme
- Guy Steele, Gerald Sussman: Oryginalne „Dokumenty Lambda”.
- SRFI (Scheme Requests for Implementation) zapewnia zbiór funkcjonalności, które praktycznie pojawiły się jako standardowa biblioteka dla implementacji Scheme.
Przedstawienia
- Jak projektować programy (HTDP) — podręcznik dla początkujących
- Struktura i interpretacja programów komputerowych (SICP) - Ta książka Schemat jest używana od lat na kursach programowania dla początkujących na MIT i innych uniwersytetach.
- Naucz się schematu w Dni Fixnum . - Kurs online dla początkujących.
Standardy językowe
- Definicja przestarzałego standardu językowego R 5 RS
- Definicja poprzedniego standardu językowego R 6 RS
- Definicja aktualnego standardu językowego R 7 RS (PDF; 679 kB)
Indywidualne dowody
- ↑ strona standardu R7RS
- ↑ Lista znanych wdrożeń
- ↑ Strona internetowa Bigloo
- ↑ Strona internetowa Gambit C
- ↑ Strona internetowa Gauche
- ↑ Strona internetowa LispMe
- ↑ Strona internetowa o rakietach
- ↑ Strona internetowa Schematu 48
- ↑ strona SIOD ( pamiątka z oryginałem z dnia 6 kwietnia 2007 w Internet Archive ) Info: archiwum Link został wstawiony automatycznie i nie została jeszcze sprawdzona. Sprawdź link do oryginału i archiwum zgodnie z instrukcjami, a następnie usuń to powiadomienie.