Cechy rakiety
Racket był aktywnie rozwijany jako narzędzie do badań nad językami programowania od połowy lat 90. XX wieku i przez lata zgromadził wiele funkcji. W tym artykule opisano i zademonstrowano niektóre z tych funkcji. Zauważ, że jednym z głównych celów projektowych Racket jest uwzględnienie tworzenia nowych języków, zarówno języków specyficznych dla domeny, jak i zupełnie nowych języków. Dlatego niektóre z poniższych przykładów są w różnych językach, ale wszystkie są zaimplementowane w Racket. Więcej informacji można znaleźć w głównym artykule .
Podstawowa implementacja Racket jest bardzo elastyczna. Nawet bez używania dialektów może działać jako w pełni funkcjonalny język skryptowy, zdolny do działania zarówno z GUI natywnym dla systemu Windows, jak i bez niego, oraz zdolny do wykonywania zadań od tworzenia serwera WWW po grafikę.
Wsparcie w czasie wykonywania
Zbieranie śmieci, wezwania ogona i bezpieczeństwo w kosmosie
Racket może używać trzech różnych śmieciarek :
- używany był konserwatywny moduł wyrzucania elementów bezużytecznych Boehm . Jednak konserwatywne gromadzenie jest niepraktyczne w przypadku długotrwałych procesów, takich jak serwer WWW — takie procesy mają tendencję do powolnego wycieku pamięci. Ponadto istnieją patologiczne przypadki, w których konserwatywny kolektor powoduje przeciek pamięci na tyle szybko, że uniemożliwia uruchomienie niektórych programów. Na przykład, podczas przechodzenia przez nieskończoną listę, pojedynczy konserwatywny błąd polegający na zachowaniu wskaźnika prowadzi do przechowywania całej listy w pamięci, szybko przepełniając dostępną pamięć. Ten kolekcjoner jest często określany jako „CGC” w społeczności Racket.
- SenoraGC to alternatywny konserwatywny moduł wyrzucania elementów bezużytecznych, który jest przeznaczony głównie do debugowania i śledzenia pamięci.
- Menedżer ruchomej pamięci (znany również jako „3m”) to precyzyjny moduł zbierania elementów bezużytecznych, który jest domyślnym modułem zbierającym Racket od 2007 roku. Ten moduł zbierający jest pokoleniowy i obsługuje rozliczanie pamięci za pośrednictwem opiekunów (patrz poniżej). Kolektor jest zaimplementowany jako transformator źródłowy C, który sam jest napisany w Racket. Dlatego proces kompilacji używa konserwatywnego kolektora do ładowania początkowego .
Podobnie jak wszystkie implementacje z rodziny Scheme , Racket implementuje pełną eliminację ogona . Racket idzie o krok dalej: dzięki analizie zmiennych na żywo język jest w pełni bezpieczny dla przestrzeni kosmicznej . Stanowi to uzupełnienie precyzyjnego wyrzucania elementów bezużytecznych iw niektórych przypadkach, jak w przypadku implementacji Lazy Racket, te dwie cechy są kluczowe dla prawidłowego wykonania. Jest to dodatek do dodatkowych optymalizacji kompilatora, takich jak podnoszenie lambda i kompilacja just-in-time .
Interfejs systemu i skrypty
Interfejs systemowy Racket obejmuje asynchroniczne, nieblokujące wejścia/wyjścia , zielone wątki , kanały synchronizacji, semafory, podprocesy i gniazda TCP .
Poniższy program uruchamia „serwer echa” na porcie 12345.
#lang rakieta ( zdefiniuj słuchacza ( tcp-listen 12345 )) ( niech echo-server () ;; utwórz serwer TCP ( zdefiniuj wartości ( in out ) ( tcp-accept listener )) ;; obsłuż połączenie przychodzące w ( zielony) wątek ( wątek ( λ () ( kopiowanie portu na zewnątrz ) ( zamykanie portu wyjścia na zewnątrz )))
;; i natychmiast zapętlić, aby zaakceptować dodatkowych klientów ( echo-server ))
Połączenie dynamicznej kompilacji i bogatego interfejsu systemowego sprawia, że Racket jest zdolnym językiem skryptowym, podobnym do Perla czy Pythona .
Poniższy przykład ilustruje chodzenie po drzewie katalogów, zaczynając od bieżącego katalogu. Używa in-directory
do skonstruowania sekwencji, która przechodzi przez drzewo. Formularz for
wiąże ścieżkę
z każdą ścieżką w sekwencji, a regexp-match?
testuje te ścieżki pod kątem podanego wzorca wyrażenia regularnego .
#lang rakieta ;; Znajduje źródła Racket we wszystkich podkatalogach ( for ([ path ( in-directory )]) ; iteruje po bieżącym drzewie ( when ( regexp-match? #rx"[.]rkt$" path ) ( printf "plik źródłowy: ~a \n " ścieżka )))
Następny przykład wykorzystuje tablicę mieszającą do rejestrowania wcześniej widzianych linii i drukowania tylko unikalnych.
#lang rakieta ;; Zgłoś każdą unikalną linię ze stdin ( let ([ saw ( make-hash )]) ( for ([ line ( in-lines )]) ( chyba ( hash-ref saw line #f ) ( displayln line )) ( hash-set linia piły #t ) ) )
Oba te programy można uruchomić w DrRacket lub w wierszu poleceń za pomocą pliku wykonywalnego rakiety
. Racket ignoruje początkową Shebang , umożliwiając przekształcenie takich programów w wykonywalne skrypty. Poniższy skrypt demonstruje to, oprócz użycia biblioteki Racket do analizowania argumentów wiersza poleceń :
#!/usr/bin/env rakieta #lang rakieta ( wiersz poleceń #:args ( katalog-bazowy ext re ) ( for ([ p ( w katalogu )] #: kiedy ( regexp-match? ( string-append " [.]" ext "$" ) p ) [( numer linii ) ( in-indexed ( plik-> linie p ))]) ( kiedy
( regexp-match? ( pregexp re ) wiersz ) ( printf "~a:~a: ~a~n" p ( + num 1 ) wiersz ))))
Skrypt jest narzędziem podobnym do grep, oczekującym trzech argumentów wiersza poleceń: katalogu podstawowego, rozszerzenia nazwy pliku i (zgodnego z Perlem) wyrażenia regularnego. Skanuje katalog podstawowy w poszukiwaniu plików z podanym sufiksem i drukuje wiersze pasujące do wzorca wyrażenia regularnego.
Zarządzanie zasobami i piaskownica
Racket zawiera koncepcję „opiekuna”: rodzaj wartości, która działa jako menedżer zasobów. Jest to często używane w serwerach sieciowych, gdzie każde połączenie jest obsługiwane przez nowego opiekuna, co ułatwia "wyczyszczenie" wszystkich zasobów, które mogły pozostać otwarte przez program obsługi (np. otwarte porty). Poniższy przykład rozszerza przykład „serwera echa” o takie użycie opiekuna:
#lang rakieta ( zdefiniuj słuchacza ( tcp-listen 12345 )) ;; dla per-connection handler ( definiuj ( handler in out ) ( kopiuj port in out ) ( close-output-port out )) ( niech echo-server () ( zdefiniuj wartości ( in out ) ( tcp-accept listener )) ( nitka
( λ () ( let ([ c ( make-custodian )]) ( parametrize ([ current-custodian c ]) ( handler in out ) ( opiekun-shutdown-all c ))))) ( echo-server ))
Custodians w połączeniu z funkcją rozliczania pamięci 3m Garbage Collector oraz szeregiem dodatkowych parametrów wykonawczych, które kontrolują dodatkowe aspekty środowiska wykonawczego, umożliwiają tworzenie całkowicie bezpiecznych kontekstów wykonawczych w piaskownicy. Rakieta /piaskownica
biblioteka zapewnia tego rodzaju funkcjonalność w prosty sposób. Poniższy przykład tworzy „serwer REPL” na określonym porcie; podłączenie do tego portu będzie wyglądać jak zwykły Racket REPL, z wyjątkiem tego, że ocena podlega różnym aspektom ochrony piaskownicy. Na przykład nie można uzyskać dostępu do systemu plików z tego REPL, utworzyć połączenia sieciowego, uruchomić podprocesów lub użyć zbyt dużo czasu lub pamięci. (W rzeczywistości ten REPL jest wystarczająco bezpieczny, aby można go było rozdawać publicznie).
#lang rakieta ( wymaga rakiety/piaskownicy ) ( zdefiniuj e ( make-evaluator ' rakieta/baza )) ( let-values ([( i o ) ( tcp-accept ( tcp-listen 9999 ))]) ( parametrize ([ current -port-wejściowy i ] [ port-bieżący-wyjściowy o ] [ port-błąd-bieżący o ] [
ocena-bieżąca e ] [ interakcja-bieżąca-odczyt ( λ ( x in ) ( wczytaj ) )]) ( pętla-ocena-wydruku ) ( fprintf o " \n Bye... \n " ) ( zamknij- port wyjściowy o )))
Programowanie WWW i sieci
Następny przykład implementuje serwer WWW przy użyciu języka web-server/insta
. Za każdym razem, gdy nawiązywane jest połączenie z serwerem, wywoływana jest funkcja start , aby pobrać
kod HTML do wysłania z powrotem do klienta.
#lang serwer WWW/insta ;; Mały serwer WWW „Hello World” ( definiuj ( żądanie startu ) ( response/xexpr ' ( html ( body „Hello World” ))))
Racket zawiera również funkcje potrzebne do pisania skrobaków i robotów. Jako przykład, poniższa funkcja wyświetli listę wyników Google dla ciągu wyszukiwania.
#lang rakieta ;; Prosty skrobak sieciowy ( wymagane net/url net/uri-codec ) ( zdefiniuj ( let-me-google-that-for-you str ) ( let* ([ g "http://www.google.com/search?q =" ] [ u ( string-append g ( uri-encode str ))] [ rx #rx"(?<=<h3 class=\"r\">).*?(?=</h3>)" ]) ( dopasowanie-regexp* rx ( get-pure-port ( string->url u )))))
Biblioteka zawiera również obsługę protokołów innych niż http:
#lang rakieta ;; Wysyłanie alertu e-mail o określonym czasie z rakiety ( wymagane net/sendmail ) ( spanie ( * ( - ( * 60 4 ) 15 ) 60 )) ; czekaj 3h 45m ( send-mail-message ( getenv "EMAIL" ) "Alert parkometru!" ( list ( getenv " EMAIL " )) null null ' ( „Czas wyjść i przestawić samochód” ) .
Grafika
Możliwości graficzne są dostępne w kilku różnych odmianach, które są przeznaczone dla różnych odbiorców. Biblioteka 2htdp/image
zapewnia wygodne funkcje do konstruowania obrazów. Ta biblioteka jest używana głównie przez studentów na na HTTP . W poniższym przykładzie Sierpińskiego
jest zdefiniowana i wywołana (w tym samym czasie) w celu wygenerowania trójkąta Sierpińskiego o głębokości 8.
#lang rakieta ;; Obraz ( wymaga 2htdp/image ) ( niech sierpinski ([ n 8 ]) ( if ( zero? n ) ( trójkąt 2 ' solid ' red ) ( niech ([ t ( sierpinski ( - n 1 ))]) ( freeze ( powyżej t ( obok t t ))))))
Edytory DrRacket mogą zawierać obrazy, a DrRacket wyświetla wartości obrazów tak samo, jak każdy inny typ wartości (taki jak liczby całkowite lub listy). Na przykład uruchomienie powyższego programu faktycznie wyświetla trójkąt Sierpińskiego, który można wyciąć i wkleić do innego programu.
Biblioteka działek
konstruuje wartości obrazu dla bardziej dojrzałych odbiorców i potrzeb. przykład sumę -wymiarowe) Gaussa, jako koncentryczne, częściowo przezroczyste powierzchnie:
#lang rakieta ;; Wizualizuj sumę dwóch gaussów 3D jako koncentryczne izopowierzchnie ;; Uwaga: ten przykład wymaga rakiety Racket 5.2 lub nowszej ( wymagany działka ) ;; Zwraca funkcję Gaussa R x R x R -> R o środku w punkcie (cx,cy,cz) ( zdefiniuj (( gaussowski cx cy cz ) x y z ) ( exp ( - ( + ( sqr ( - x cx )) ( sqr
( - y cy )) ( sqr ( - z cz )))))) ;; Podnosi + do działania na funkcjach trójargumentowych ( zdefiniuj (( f3+ g h ) x y z ) ( + ( g x y z ) ( h x y z ))) ;; Tworzy wartość obrazu reprezentującą sumę dwóch Gaussów ( plot3d ( 0 0 0 0
isosurfaces3d ( f3+ ( gaussowski ) ( gaussowski 1,5 -1,5 )) -1 2,5 -2,5 1 -1 1 #:label "g" )) ; etykietowanie dodaje legendę
W tym przypadku funkcja isosurfaces3d
wymaga funkcji trójargumentowej jako swojego pierwszego argumentu, którą dostarcza curried f3+
. Oprócz konstruowania wartości obrazu, plot
może również zapisywać pliki w formatach PNG , PDF , PostScript i SVG .
Programowanie GUI
Racket implementuje przenośną warstwę GUI , na której opierają się wspomniane wyżej biblioteki. Jest implementowany za pośrednictwem natywnego systemu Windows , za pośrednictwem Cocoa w systemie Mac OS X oraz za pośrednictwem GTK+ w systemie Linux i innych. Racket API to zestaw narzędzi oparty na klasach, nieco powiązany z wxWidgets , który był pierwotnie używany.
Poniższa prosta gra w zgadywanie demonstruje kodowanie za pomocą zestawu narzędzi GUI. Klasa frame %
implementuje okno najwyższego poziomu, a button%
implementuje przycisk. Zdefiniowana tutaj funkcja sprawdzania
tworzy funkcję, która jest używana do akcji wywołania zwrotnego przycisku.
#lang rakieta/gui ;; Gra w zgadywanie z GUI ( zdefiniuj sekret ( losowo 5 )) ( zdefiniuj f ( nowa ramka % [ etykieta " Gra w zgadywanie " ])) ; okno najwyższego poziomu ( zdefiniuj t ( nowa wiadomość% [ rodzic f ] [ etykieta "Czy zgadniesz liczbę, o której myślę?" ])) ( zdefiniuj p
( nowy poziomy panel% [ rodzic f ])) ; kontener poziomy ( zdefiniuj (( make-check i ) btn evt ) ( skrzynka-wiadomości "." ( cond [( < i tajne ) "Za małe" ] [( > i tajne ) "Za duże" ] [ else "Dokładnie! " ]))
( when ( = i secret ) ( send f show #f ))) ; sukces => zamknij okno ( for ([ i ( in-range 10 )]) ; utwórz wszystkie przyciski ( make-object button % ( format "~a" i ) p ( make-check i ))) ( send f show # t ) ; pokaż okno, aby uruchomić aplikację
GUI można w ten sposób zakodować ręcznie lub za pomocą programu do projektowania GUI dostępnego na PLaneT.
Pokaz slajdów
Prezentacje oparte na slajdach można również opracowywać w Racket przy użyciu języka pokazu slajdów
, podobnie jak Beamer , ale z programowymi funkcjami Racket. Elementami slajdów są obrazki, które można łączyć.
Na przykład poniższy program wyświetla na pełnym ekranie slajd tytułowy, a następnie slajd z kilkoma obrazami. Funkcje vc -append
i hc-append
łączą obrazy odpowiednio w pionie iw poziomie i są wyśrodkowane na drugiej osi.
#lang slideshow ( slide ( text "Slideshow" ' roman 56 ) ( text "Tworzenie prezentacji w Racket" ' roman 40 )) ( slide #:title "Some images" ( apply vc-append ( for/list ([ i 5 ] ) ( zdefiniuj ( skala+kolor p c ) (
colorize ( skala p ( / ( add1 i ) 5 )) c )) ( hc-append ( skala+kolor ( wypełniony prostokąt 100 50 ) "darkblue" ) ( skala+kolor ( dysk 100 ) "ciemnozielony" ) ( skala+ kolor ( strzałka 100 ( / pi 6 ))
"ciemny" ) ))))
Pakiety rozszerzeń istnieją również na PLaneT, na przykład w celu uwzględnienia elementów LaTeX .
Interfejs funkcji obcej
Racket posiada interfejs funkcji obcych oparty na libffi . Interfejs umożliwia pisanie niebezpiecznego kodu niskiego poziomu do C , który może przydzielać pamięć, wyłuskiwać wskaźniki, wywoływać funkcje w bibliotekach współdzielonych i wysyłać wywołania zwrotne do funkcji Racket (przy użyciu domknięć libffi). Podstawową implementacją jest cienka warstwa na szczycie libffi (napisana w C), a pełny interfejs jest następnie implementowany za pomocą kodu Racket. Interfejs w dużym stopniu wykorzystuje makra, co skutkuje wyrazistym językiem opisu interfejsu opartym na Racket . Ten język ma wiele przydatnych funkcji, takich jak jednolita reprezentacja funkcji wyższego rzędu (unikanie pułapek, gdy wywołania zwrotne i objaśnienia są różne), definicje struktur podobne do zwykłych struktur Racket oraz niestandardowe typy funkcji, które mogą reprezentować dane wejściowe i wyjściowe wskaźniki, argumenty niejawne (np. argument, który podaje liczbę elementów w wektorze przekazywanym jako inny argument). Korzystając z tego interfejsu, aby uzyskać dostęp do podstawowych zestawów narzędzi GUI, Racket całkowicie implementuje własną warstwę GUI w Racket.
OpenGL Racketa ), po szybkie wyciągnięcie pojedynczej obcej funkcji. Przykład drugiego podejścia:
0
#lang rakieta/baza ;; Proste użycie FFI ( wymagane ffi/unsafe ) ( zdefiniuj mci-send-string ( get-ffi-obj "mciSendStringA" "Winmm" ( _fun _string [ _pointer = #f ] [ _int = ] [ _pointer = #f ] - > [ ret : _int ]))) ( mci-send-string "odtwórz dźwięk.wav czekaj" )
Rozszerzenia językowe
Najbardziej godną uwagi cechą Racket jest jego zdolność do tworzenia nowych języków specyficznych dla domeny i ogólnego przeznaczenia . Jest to efekt połączenia kilku ważnych cech:
- elastyczny system modułowy służący do łączenia kodu i zarządzania przestrzenią nazw,
- rozbudowany system makr – działający jako kompilator-API – który może tworzyć nowe formy składniowe,
- bogaty system wykonawczy, zapewniający funkcje, z których mogą korzystać implementatorzy języka, takie jak (komponowalne, rozdzielane) kontynuacje, zarządzanie zasobami itp.,
- sposób na określenie (i zaimplementowanie) parserów dla składni nowego języka.
System modułów odgrywa ważną rolę w łączeniu tych funkcji i umożliwia pisanie kodu obejmującego wiele modułów, z których każdy może być napisany w innym języku.
Takie języki są szeroko stosowane w dystrybucji Racket oraz w bibliotekach użytkowników. W rzeczywistości tworzenie nowego języka jest tak proste, że istnieją języki, które mają mniej niż kilka zastosowań.
Racket ma wiele przydatnych języków, niektóre bardzo różnią się od domyślnego języka Racket.
Bazgrać
Scribble, system dokumentacji Racket, występuje w wielu językach używanych do pisania prozy. Służy do dokumentacji Racket, a także do pisania książek i artykułów. W rzeczywistości, zamiast pojedynczego języka „bazgrołów”, jest to rodzina (bardzo podobnych) dialektów, z których każdy służy do innego celu.
Aby uruchomić poniższy przykład, skopiuj go do DrRacket i kliknij jeden z dwóch przycisków renderowania bazgrołów, które się pojawią (renderowanie PDF wymaga pdfTeX ). Ewentualnie użyj scribble
w pliku.
#lang bazgroły/podstawa @; Wygeneruj dokument PDF lub HTML za pomocą `scribble' @(require (planet neil/numspell)) @title{99 Bottles of Beer} Na wypadek, gdybyś potrzebował trochę @emph{bla bla} w swoim życiu. b _ _ _ _ item{@string-titlecase [N] butelki piwa na ścianie, @N butelek piwa. Zdejmij jedną, podaj dalej, @N-- butelki piwa na ścianie.}))
Najbardziej uderzającą cechą języków Scribble jest użycie nowej składni, która została zaprojektowana specjalnie dla kodu bogatego w tekst. Składnia pozwala na dowolny tekst, interpolację ciągów znaków, dostosowywane cytaty i jest przydatna w innych aplikacjach, takich jak wstępne przetwarzanie tekstu , generowanie tekstu i systemy szablonów HTML. Należy zauważyć, że składnia rozszerza zwykłe S-wyrażenia i jest zaimplementowana jako alternatywne dane wejściowe dla takich wyrażeń.
#lang bazgroły/tekst Cześć, jestem plikiem tekstowym — uruchom mnie. @(definiuj (trzykrotnie . tekst) @list{@text, @text, @text}) @thrice{SPAM}! @thrice{HAM}!
Wpisana rakieta
Typowana rakieta to statycznie typowana odmiana rakiety. System typów , który implementuje, jest wyjątkowy, ponieważ motywacją do jego opracowania było uwzględnienie jak największej ilości idiomatycznego kodu Racketa — w rezultacie obejmuje on podtypy, związki i wiele więcej. Kolejnym celem Typed Racket jest umożliwienie migracji części programu do języka maszynowego, dzięki czemu umożliwia wywoływanie kodu wpisanego z kodu niewpisanego i odwrotnie, generując dynamiczne kontrakty aby wymusić niezmienniki typu. Jest to uważane za pożądaną cechę etapów życia aplikacji, ponieważ dojrzewa od „skryptu” do „aplikacji”, w której pisanie statyczne pomaga w utrzymaniu dużej części kodu.
#lang wpisany/racket ;; Używanie wpisywania wystąpień wyższego rzędu ( zdefiniuj typ Str-or-Num ( U String Number )) ( : tog (( Listof Str-or-Num ) -> String )) ( zdefiniuj ( tog l ) ( zastosuj string-append ( ciąg filtru ? l ))) ( tog ( lista 5 "witaj" 1/2 "świat" ( sqrt -1 )))
Leniwa rakieta
Leniwy język to język z leniwą semantyką oceny ,
podobny do Haskella . W poniższym przykładzie fibs
jest nieskończoną listą, której tysięczny element nie zostanie obliczony, dopóki jego wartość nie będzie potrzebna do wydruku.
#lang leniwy ;; Nieskończona lista: ( zdefiniuj fibs ( list* 1 1 ( map + fibs ( cdr fibs )))) ;; Wydrukuj tysięczną liczbę Fibonacciego: ( print ( list-ref fibs 1000 ))
Programowanie logiczne
Racket jest dostarczany z trzema językami programowania logiki : Racklog, język podobny do Prologu ; implementacja Datalog ; oraz port miniKanren . W przeciwieństwie do składni Scribble, pierwsze dwa z tych języków używają zupełnie nowej składni, a nie rozszerzenia S-wyrażeń. Jeśli użyjesz go w DrRacket, zobaczysz, że zapewnia on odpowiednie podświetlanie, zwykłą składnię sprawdzania narzędzi oraz REPL Prolog/Datalog.
#lang przodek dziennika danych ( A , B ) :- rodzic ( A , B ). przodek ( A , B ) :- rodzic ( A , C ), D = C , przodek ( D , B ). rodzic ( jan , douglas ). rodzic ( Bob ,
Jan ). przodek ( A , B ) ?
Narzędzia edukacyjne
Grupa PLT, która rozwija Racket, tradycyjnie zajmowała się edukacją na wszystkich poziomach. Jednym z najwcześniejszych pomysłów badawczych promowanych przez grupę było stosowanie poziomów językowych, które ograniczają nowych uczniów, jednocześnie dostarczając im pomocnych komunikatów o błędach, które pasują do poziomu wiedzy ucznia. To podejście jest często używane w How to Design Programs , podręczniku, którego autorami jest kilku programistów PLT, a także w projekcie ProgramByDesign . Poniższy program używa htdp/bsl
— „języka początkujących uczniów”. Używa 2htdp/image
biblioteka do tworzenia obrazków w nauczanych językach oraz biblioteka 2htdp/universe
do animacji interaktywnych.
#lang htdp/bsl ;; Dowolny klawisz nadmuchuje balon ( wymaga 2htdp/image ) ( wymaga 2htdp/universe ) ( definiuj ( balon b ) ( kółko b "solid" "red" )) ( definiuj ( powiększenie b k ) ( + b 5 )) ( zdefiniuj ( spuść powietrze b ) (
max ( - b 1 ) 1 )) ( big-bang 50 ( nadmuch na klawiszu ) ( opróżnianie na tik ) ( do rysowania balonu 200 200 ))
Algol
Rakieta jest dostarczana z pełną implementacją języka ALGOL 60 .
0
# lang algol60 rozpocząć procedurę całkowitą SIGMA ( x , i , n ) ; wartość n ; liczba całkowita x , ja , n ; początek suma całkowita ; suma := ; dla i := 1 krok 1 do n do sum := suma + x ; SIGMA
:= suma ; koniec ; liczba całkowita q ; printnln ( SIGMA ( q * 2 - 1 , q , 7 )) ; koniec
Typ Plai i Plai
#lang plai
#lang plai wpisany
Innym obsługiwanym językiem jest plai, który podobnie jak rakieta może być wpisany lub nie. „Moduły napisane w plai eksportują każdą definicję (w przeciwieństwie do schematu).” „Język Typed PLAI różni się od tradycyjnego Racket przede wszystkim tym, że jest typowany statycznie. Daje także kilka przydatnych nowych konstrukcji: zdefiniuj typ, typ-przypadek i test”.
Dodatkowe języki
Na koniec poniższy przykład jest implementacją nowego języka:
#lang rakieta ( dostarcz ( z wyjątkiem-out ( wszystko z-out- rakiety ) #%top #%app ) ( rename-out [ top #%top ] [ app #%app ])) ( definiuj regułę-składni ( top . x ) ' x ) ( zdefiniuj regułę składni ( app f . xs ) ( if ( haszysz? f ) ( hash-ref f . xs ) ( f . xs )))
Ten język:
- zapewnia wszystko z języka
rakietowego
, więc jest to nieco podobny wariant, - z wyjątkiem dwóch specjalnych „makr przechwytujących”, które implementują niezwiązane wyszukiwanie zmiennych i wywołania funkcji, zamiast nich dostępne są nowe formularze
- pośrednio cytuj wszystkie nieznane zmienne
- zezwalaj na używanie tablic skrótów jako funkcji, w których argumenty są używane do wyszukiwania w tabeli skrótów.
Jeśli ten kod jest przechowywany w pliku mylang.rkt
, możesz go użyć w następujący sposób:
#lang s-exp "mylang.rkt" ; składnia sexpr, używając semantyki mylang ( definiuj h ( make-hasheq )) ( hash-set! h A B ) ; A i B dokonują tutaj samooceny ( h A ) ; tablica skrótów jest używana jako funkcja
- Od tej edycji , w tym artykule wykorzystano treść z „Racket” , która jest licencjonowana w sposób umożliwiający ponowne wykorzystanie na mocy licencji Creative Commons Attribution-ShareAlike 3.0 Unported License , ale nie na mocy GFDL . Należy przestrzegać wszystkich odpowiednich warunków.