Systém
| systém | ||
|---|---|---|
|
| ||
| ? | ||
| Obecná informace | ||
| Běžná rozšíření | scm a ss | |
| Paradigma | multi-paradigma | |
| Objevil se v | 1975 | |
| Navrhl | Guy L. Steele a Gerald Jay Sussman | |
| typový systém | silný, dynamický | |
| implementací | Schéma, Schéma 48, Kuře, Gambit, FLUENT, Guile , Bigloo, Chez Schéma, STk, STklos, Krádež, SCM | |
| dialekty | T | |
| ovlivněný | lisp | |
Scheme je funkcionální programovací jazyk (i když nečistý , protože jeho datové struktury nejsou neměnné)a dialekt Lisp . Byl vyvinut Guyem L. Steelem a Geraldem Jayem Sussmanem v 70. letech a představen akademickému světu prostřednictvím série dokumentů známých jakoSussman a Steele Lambda Papers .
Filozofie Scheme je minimalistická . Jeho cílem není nashromáždit velké množství funkcionalit, ale vyhnout se slabinám a omezením, kvůli kterým je nutné je přidávat. Scheme tedy poskytuje minimální možný počet primitivních pojmů a vše ostatní buduje z redukovaného počtu abstrakcí. Například hlavním mechanismem pro řízení toku jsou rekurzivní volání .
Scheme byl první dialekt Lisp, který používal výhradně statické scoping , také známé jako lexikální scoping , (místo dynamického ). Byl to také jeden z prvních programovacích jazyků s explicitními pokračováními , mechanismem pro ukládání a používání celého stavu programu v daném čase. Scheme také nabízí automatickou správu paměti ( garbage collection ).
Seznamy jsou základní datovou strukturou jazyka, který mezi svými předdefinovanými typy nabízí i pole . Vzhledem ke své minimalistické specifikaci neexistuje žádná explicitní syntaxe pro vytváření registrů nebo struktur nebo pro objektově orientované programování , ale mnoho implementací takovou funkcionalitu nabízí.
Scheme se původně jmenovalo „Schemer“, v návaznosti na tradici jazyků Planner a Conniver . Jeho současný název je dán tím, že jeho autoři použili operační systém ITS , který omezil délku názvů souborů na 6 znaků.
Výhody schématu
Schéma, stejně jako všechny dialekty jazyka Lisp , má ve srovnání s mnoha jinými jazyky velmi omezenou syntaxi. Nepotřebuje pravidla přednosti ve své gramatice, protože používá předponu pro všechna volání funkcí. Ve světě Lisp jsou takové výrazy známé jako S-výrazy .
Charakteristická síla Lisp spočívá v jednoduchosti jeho homoikonické syntaxe tvořené vnořenými seznamy, která odráží strukturu abstraktního stromu syntaxe programu a zpřístupňuje ji programátorovi. To usnadňuje metaprogramování pomocí maker. Makra Scheme umožňují snadné přizpůsobení novým doménám, například přidáním podpory pro objektově orientované programování . Existuje například rozšíření, které implementuje objektový systém napsaný na méně než tisíci řádcích kódu Scheme včetně komentářů. [ 1 ] Schéma poskytuje hygienický makro systém , který, i když není tak výkonný jako Common Lisp , je mnohem bezpečnější a často jednodušší na použití. Výhodou takového systému maker (který se vyskytuje i v jiných jazycích, např. Dylan ) je, že se automaticky vyhýbá kolizím mezi názvy použitými v definici makra a kontextem, ve kterém je makro expandováno. Na druhou stranu hygienická makra nemohou zavádět nové symboly.
Schéma usnadňuje funkční programování . Ačkoli je Scheme nečisté, protože umožňuje destruktivní přiřazování, jeho použití ve stylu čistého funkcionálního programování se vyhýbá globálním proměnným a vedlejším efektům , díky čemuž je bezpečnější v přítomnosti souběžných procesů ( bezpečné pro vlákna ), navíc značně usnadňuje ověřování programu . nejméně ve srovnání s imperativním stylem .
Ve schématu jsou procedury nebo funkce prvotřídními objekty . To umožňuje definici funkcí vyššího řádu ; funkce, které přijímají nebo vracejí jiné funkce, které umožňují vyšší stupeň abstrakce v programech. Je také možné vytvořit anonymní (doslovné) procedury pomocí (lambda (arg1 ...) (...)).
Standard Scheme je také minimalistický. To s sebou nese výhody i nevýhody. Například napsat kompilátor schématu nebo interpret , který odpovídá standardu, je snazší než implementovat Common Lisp; vložení Lisp na zařízení s nízkou pamětí bude také schůdnější, pokud místo Common Lisp použijeme Scheme. Fanoušci schémat velmi pobaveně poukazují na to, že jejich standard, pouhých 50 stran, je kratší než obsah v knize Guy Steele Common Lisp: The Language .
Nevýhody schématu
Standard Scheme je skutečně minimalistický a specifický sám o sobě. To znamená, že existuje mnoho různých implementací, z nichž každá představuje svá vlastní rozšíření a knihovny, které je činí vzájemně nekompatibilními. Tento problém se snaží vyřešit žádost o implementaci schématu ( SRFI ).
Někteří vidí skutečnost, že procedury a proměnné sdílejí stejný jmenný prostor, jako nevýhodu, protože některé funkce mají názvy, které se běžně používají pro proměnné. Jedná se například listo název procedury, takže je velmi běžné vidět lstnebo xsjako názvy proměnných namísto „ list“.
Jak jsme již řekli, jmenný prostor je jedinečný (Schéma je LISP-1), a proto obsahuje také makra. To znemožňuje odlišit použití makra od použití funkce, takže pokud nebudeme konzultovat definici každého z použitých objektů, nebude obecně možné určit pořadí hodnocení v programech, se kterými jsme neznámý.
standardy
Programovací jazyk Scheme definují dva standardy: oficiální standard IEEE a de facto standard známý jako Revised n-th Report on the Algorithmic Language Scheme , často zkrácený jako R n RS, kde n je číslo revize. . Nejnovější R n RS je R6RS a je k dispozici online .
Jazykové prvky
Komentáře
Chcete-li přidat komentář do schématu, začněte středníkem ( ;) a pokračujte až do konce řádku.
Proměnné
Proměnné jsou dynamicky typovány. K jejich přiřazení ke konkrétní hodnotě můžeme použít definevýraz let, výraz nebo jednu z jeho variant. Proměnné přiřazené na první úrovni pomocí definejsou v globálním rozsahu (to znamená, že jsou viditelné pro zbytek programu).
( definujte hodnotu var1 )
Proměnné přiřazené přes letvidí jejich rozsah redukovaný na tělo uvedeného let:
( let (( hodnota var1 ) ) ... rozsah var1 ... )
Postupy
Funkce nebo procedury jsou ve Scheme objekty první třídy. Lze je přiřadit k proměnným. Například funkce se dvěma argumenty arg1 a arg2 může být definována jako:
( definujte zábavu
( lambda ( arg1 arg2 )
... ))
nebo v ekvivalentní krátké formě:
( definovat ( fun arg1 arg2 )
... )
Volání funkcí mají následující syntaxi:
( zábavná hodnota1 hodnota2 )
Jak vidíme, volaná funkce je nalezena jako první, poté následují argumenty volání tvořící seznam. Můžeme také použít proceduru apply, která má dva argumenty: první je procedura, kterou chceme vyvolat, zatímco druhý je seznam argumentů. Výše uvedené volání funkce lze tedy zapsat ekvivalentně jako:
( použít zábavu ( hodnota seznamu1 hodnota2 ) )
Ve Scheme spadají funkce v zásadě do dvou kategorií: uživatelsky definované procedury a primitiva. Primitiva jsou v jazyce předdefinovaná a zahrnují +, -, *, /, set!, car, cdra další základní procedury. Mnoho implementací umožňuje uživateli přepsat některá primitiva. Například následující kód:
( definovat +
( lambda ( x y )
( - x y )))
převede primitivum +na uživatelem definovanou proceduru, která odečte jeho dva argumenty místo toho, aby je přidala.
Seznamy
Schéma používá propojené seznamy obdobně jako jiné dialekty jazyka Lisp .
Všimněte si, že použití seznamů je mnohem jednodušší než v jiných programovacích jazycích, jako je C, C++ a Pascal.
Typy dat
Další datové typy ve schématu jsou celá čísla , racionální hodnoty , reálná čísla , komplexy , symboly , řetězce a porty , asociativní seznamy , hashovací tabulky , vektory , pole a struktury .
Většina implementací poskytuje to, co je známé jako kompletní numerická věž , stejně jako přesnou a nepřesnou aritmetiku .
Booleovské hodnoty jsou reprezentovány symboly #ta #f. Ve skutečnosti je jakákoli hodnota jiná než #f(včetně prázdného seznamu) interpretována jako „pravda“ ve správném kontextu, zatímco v jiných dialektech Lisp je prázdný seznam interpretován jako logická hodnota nepravda.
Symboly lze definovat různými způsoby, bytí
'symbol
( řetězec->symbol "symbol" )
nejčastější.
Rovnost
Schéma má tři různé typy rovnosti:
eq?- Vrátí
#t, zda jsou tyto dva objekty přesně stejným objektem, a dokonce zkontroluje, kde jsou fyzicky uloženy. eqv?- Obvykle stejné jako
eq?, ale s některými objekty (například znaky a čísly) zachází zvláštním způsobem, takže čísla, která jsou stejná, jsoueqv?, i když nejsoueq?. equal?- Porovnává obsah datových struktur, jako jsou seznamy, vektory a řetězce, aby zjistil, zda jsou stejné.
Ve schématu existují také typově závislé operátory ekvivalence:
string=?- Porovnejte dva řetězce
char=?- Porovnejte dva znaky
=- porovnat čísla
Řídící struktury
Podmíněné hodnocení
( cond ( test1 expr1 )
( test2 expr2 )
...
( else expr ))
Bude vyhodnocen první výraz, pro který je test pravdivý (cokoli kromě #fpravdivého). Jsou - li všechny testy #fsplněny , je klauzule vyhodnocena else.
Varianta klauzule condje:
( podmínka ...
( test => expr )
... )
V tomto případě by to exprmělo vést k funkci, která přebírá jeden argument. Pokud testse ukáže, že je to pravda, výše uvedená funkce se zavolá s hodnotou vrácenou test.
Schéma má také:
( pokud test then-expr else-expr )
ale používá se mnohem méně, protože condje obecnější a je obvykle čitelnější.
Smyčky
Smyčky ve schématu mají obvykle podobu ocasní rekurze . Tento typ rekurze je preferován, protože se obejde bez hromadění rámců na zásobníku volání a jejich následného přetečení. Standard vyžaduje implementace pro optimalizaci volání v pozici konečné rekurze pro generování kódu ekvivalentního smyčce v imperativních jazycích. Klasickým příkladem je faktoriální funkce, kterou lze definovat bez konečné rekurze jako:
( definovat ( faktoriál n )
( podmínka (( = n 0 ) 1 )
( jinak ( * n ( faktoriál ( - n 1 ))))))
( faktoriál 5 )
;; => 120
Nebo s konečnou rekurzí pomocí zvláštního postupu:
( definovat ( faktoriál n )
( fakt-iter 1 n ))
( definovat ( fact-iter product n )
( if ( < n 2 )
product
( fact-iter ( * product n )
( - n 1 ))))
( faktoriál 5 )
;; => 120
Další typickou formou smyčky je funkce vyššího řádu, jako mapje , která aplikuje funkci na každý prvek seznamu, lze ji také definovat bez konečné rekurze takto:
( definovat ( map f lst )
( cond ( ( null? lst ) lst )
( else ( cons ( f ( car lst ))
( map f ( cdr lst ))))))
( mapa ( lambda ( x ) ( * x x )) ' ( 1 2 3 4 ))
;; => (1 4 9 16)
Obojí můžeme definovat pomocí finální rekurze následovně. let Pojmenovaný výraz a příkaz dojsou syntaktický cukr , který zjednodušuje definice pomocí koncové rekurze.
( definovat ( faktoriál n )
( nechat smyčku (( fakt 1 )
( n n ))
( cond ( ( = n 0 ) fakt )
( jinak ( smyčka ( * n fakt ) ( - n 1 )))))))
( faktoriál 5 )
;; => 120
( definovat ( map f lst )
( do ( ( lst lst ( cdr lst ))
( res ' () ( cons ( f ( car lst )) res )))
( ( null? lst ) ( reverse res ))))
( mapa ( lambda ( x ) ( * x x )) ' ( 1 2 3 4 ))
;; => (1 4 9 16)
Všimněte si, že v obou případech je preferována verze s konečnou rekurzí kvůli menšímu využití prostoru.
Vstup/výstup
Schéma má koncept portů pro čtení nebo zápis. Schéma definuje tři výchozí porty přístupné pomocí current-input-port, current-output-porta current-error-port.
Viz také
- lisp
- obyčejný lisp
- herecký model
- Guy L. Steele, Jr.
- Gerald Jay Sussman