Raku (język programowania) - Raku (programming language)

Raku
Kamelia.svg
Kamelia, maskotka Raku
Paradygmat Wieloparadygmat
Rodzina Perl
Zaprojektowany przez Larry Wall
Deweloper Społeczność Raku
Po raz pierwszy pojawiły się 25 grudnia 2015 r .; 5 lat temu ( 25.12.2015 )
Wersja stabilna
6.d „Diwali” / 24 października 2020 r .; 11 miesięcy temu ( 24.10.2020 )
Dyscyplina pisania Dynamiczny , stopniowy
OS Wieloplatformowy
Licencja Powszechna Licencja Publiczna GNU lub Licencja Artystyczna 2
Rozszerzenia nazw plików .p6, .pm6, .pod6, .t6, .raku, .rakumod, .rakudoc, .rakutest
Strona internetowa raku .org
Główne wdrożenia
Rakudo
Wpływem
Perl , Ruby , Smalltalk , Haskell , JavaScript
Pod wpływem
Perl , Haskell , AntLang

Raku jest członkiem rodziny języków programowania Perl . Dawniej znany jako Perl 6 , został przemianowany w październiku 2019 roku. Raku wprowadza elementy wielu współczesnych i historycznych języków. Zgodność z Perlem nie była celem, chociaż tryb zgodności jest częścią specyfikacji. Proces projektowania dla Raku rozpoczął się w 2000 roku.

Historia

W Perlu 6 zdecydowaliśmy, że lepiej będzie naprawić język niż naprawić użytkownika.

—  Larry Wall

Proces projektowania Raku został po raz pierwszy ogłoszony 19 lipca 2000 r., czwartego dnia tegorocznej konferencji Perl , przez Larry'ego Walla w swoim wystąpieniu o stanie cebuli 2000 . W tym czasie głównym celem było usunięcie „historycznych brodawek” z języka; "łatwe rzeczy powinny pozostać łatwe, trudne rzeczy powinny stać się łatwiejsze, a niemożliwe rzeczy powinny stać się trudne"; ogólne uporządkowanie wewnętrznego projektu i interfejsów API . Proces rozpoczął się serią próśb o komentarze lub „RFC”. Ten proces był otwarty dla wszystkich współtwórców i nie pozostawiał żadnego aspektu języka zamkniętego na zmianę.

Po zakończeniu procesu RFC Wall sprawdził i sklasyfikował każde żądanie (otrzymano 361). Następnie rozpoczął proces pisania kilku „Apokalipsy”, używając pierwotnego znaczenia terminu „ujawnienie”. Podczas gdy pierwotnym celem było napisanie jednej apokalipsy dla każdego rozdziału programowania w Perlu , stało się oczywiste, że w miarę pisania każdej apokalipsy poprzednie apokalipsy były unieważniane przez późniejsze zmiany. Z tego powodu opublikowano zestaw Synops, z których każdy dotyczył treści Apokalipsy, ale z późniejszymi zmianami odzwierciedlonymi w aktualizacjach. Obecnie specyfikacja Raku jest zarządzana za pomocą pakietu testowego „pieczenia”, podczas gdy streszczenia są przechowywane jako odniesienie historyczne.

Istnieje również seria Egzegez napisanych przez Damiana Conwaya, które wyjaśniają treść każdej Apokalipsy pod kątem praktycznego zastosowania. Każda egzegeza składa się z przykładów kodu wraz z omówieniem użycia i implikacji przykładów.

Istnieją trzy podstawowe metody komunikacji używane w dzisiejszym rozwoju Raku. Pierwszym z nich jest kanał IRC raku na czacie Libera . Drugi to zestaw list dyskusyjnych na serwerach The Perl Foundation pod adresem perl.org . Trzecim jest repozytorium kodu źródłowego Git hostowane pod adresem https://github.com/raku .

Początkowe cele i implikacje

Głównym celem, jaki Wall zasugerował w swoim wstępnym przemówieniu, było usunięcie historycznych brodawek. Obejmowały one zamieszanie związane z użyciem sigilów w kontenerach, niejednoznaczność między selectfunkcjami oraz wpływ składniowy uchwytów plików gołych słów. Było wiele innych problemów, które programiści Perla omawiali przez lata, a które zostały wyraźnie omówione przez Walla w jego przemówieniu.

Implikacją tych celów było to, że Perl 6 nie miałby wstecznej kompatybilności z istniejącą bazą kodu Perla. Oznaczało to, że część kodu, który został poprawnie zinterpretowany przez kompilator Perla 5, nie zostanie zaakceptowany przez kompilator Perla 6. Ponieważ kompatybilność wsteczna jest powszechnym celem przy ulepszaniu oprogramowania, przełomowe zmiany w Perlu 6 musiały być wyraźnie określone. Różnica między Perl 5 i Perl 6 stała się tak duża, że ​​ostatecznie Perl 6 został przemianowany na Raku.

Przez lata Raku przeszedł kilka zmian w jego kierunku. Wprowadzenie koncepcji z Pythona i Ruby było wczesnymi wpływami. Ponadto, ponieważ Pugs — pierwszy interpreter zdolny do uruchamiania Raku — został napisany w języku programowania Haskell , zespół projektowy Raku wchłonął wiele wpływów programowania funkcjonalnego .

Maskotka

Larry Wall i Camelia

Maskotką języka jest „Camelia, pluskwa Raku”. Jej imię to ukłon w stronę wielbłądowej maskotki związanej z Perlem , a jej forma, zgodnie z tradycją społeczności Perla kochającej kalambury, jest grą na „ błędzie oprogramowania ”. Spiralne wzory osadzone w jej przypominających motyla skrzydłach przypominają postacie „P6”, ulubiony pseudonim Perla 6, a umieszczenie oczu poza środkiem jest celową grą słów na „Wall-eyed”.

Jednym z celów żywego i kolorowego projektu logo było zniechęcenie społeczności do mizoginii i umożliwienie osobom o „męskiej perswazji” pokazania swojej wrażliwej strony.

Realizacje

Od 2017 roku tylko wdrożenie Rakudo jest aktywnie rozwijane. Żadna implementacja nie zostanie oznaczona jako oficjalna implementacja Raku; raczej „Raku to wszystko, co przechodzi oficjalny zestaw testów”.

Rakudo Perl 6 jest przeznaczony dla wielu maszyn wirtualnych, takich jak MoarVM , Java Virtual Machine i JavaScript . MoarVM to maszyna wirtualna zbudowana specjalnie dla Rakudo i NQP Compiler Toolchain. Istnieje warstwa między Raku a maszynami wirtualnymi o nazwie Not Quite Perl 6 lub NQP, która implementuje reguły Raku do analizowania Raku, a także abstrakcyjne drzewo składni i generowanie kodu specyficznego dla backendu . Duże fragmenty Rakudo są napisane w samym Raku lub w jego podzbiorze NQP. Rakudo nie jest całkowicie samo-hostingową implementacją , ani nie ma w tym momencie konkretnych planów uczynienia Rakudo kompilatorem ładowania początkowego.

Realizacje historyczne

Mopsy były początkową implementacją Perla 6 napisaną w Haskell . Mopsy były kiedyś najbardziej zaawansowaną implementacją Perla 6, ale od połowy 2007 roku jest ona w większości uśpiona (z aktualizacjami tworzonymi tylko w celu śledzenia bieżącej wersji GHC ). Od listopada 2014 r. Mopsy nie były aktywnie utrzymywane.

W 2007 roku v6-MiniPerl6 ("mp6") i jego reimplementacja, v6-KindaPerl6 ("kp6") zostały napisane jako sposób na załadowanie wersji Perl-6.0.0 STD przy użyciu Perla 5. STD to pełna gramatyka dla Perla 6 i jest napisany w Perl 6. Teoretycznie wszystko, co jest w stanie parsować STD i generować kod wykonywalny, jest odpowiednim systemem ładowania początkowego dla Perl 6. kp6 jest obecnie kompilowany przez mp6 i może pracować z wieloma backendami. mp6 i kp6 nie są pełnymi implementacjami Perla 6 i zostały zaprojektowane tylko po to, aby zaimplementować minimalny zestaw funkcji wymagany do załadowania pełnego kompilatora Perl 6.

Yapsi był kompilatorem i środowiskiem uruchomieniowym Perla 6 napisanym w samym Perlu 6. W rezultacie do działania wymagał istniejącego interpretera Perl 6, takiego jak jedno z wydań Rakudo Star.

Niecza, kolejny duży wysiłek wdrożeniowy Perl 6, skupił się na optymalizacji i efektywnych badaniach wdrożeniowych. Jest ukierunkowany na wspólną infrastrukturę językową .

System modułowy

Specyfikacja Raku wymaga, aby moduły były identyfikowane według nazwy, wersji i uprawnień. Możliwe jest załadowanie tylko określonej wersji modułu lub nawet dwóch modułów o tej samej nazwie, różniących się wersją lub uprawnieniami. Dla wygody udostępniono alias do krótkiej nazwy.

CPAN , system dystrybucji modułów Perla, nie obsługuje jeszcze modułów Raku. Zamiast tego używany jest prototypowy system modułowy.

Główne zmiany z Perl

Perl i Raku różnią się zasadniczo, chociaż generalnie chodziło o "utrzymanie Raku Perla", tak aby Raku był wyraźnie "językiem programowania Perla". Większość zmian ma na celu normalizację języka, ułatwienie początkującym i doświadczonym programistom zrozumienia i uczynienie "łatwych rzeczy łatwiejszymi, a trudnych bardziej możliwymi".

Specyfikacja

Główna nietechniczna różnica między Perlem a Raku polega na tym, że Raku zaczął się jako specyfikacja. Oznacza to, że Raku można ponownie zaimplementować w razie potrzeby, a także oznacza, że ​​programiści nie muszą czytać kodu źródłowego, aby uzyskać najwyższy autorytet w danej funkcji. Oficjalna dokumentacja nie jest uważana za miarodajną i tylko nieformalnie opisuje zachowanie rzeczywistego interpretera Perla. Wszelkie rozbieżności znalezione między dokumentacją a implementacją mogą prowadzić do zmiany jednego z nich w celu odzwierciedlenia drugiego, co jest dynamiką, która napędza ciągły rozwój i udoskonalanie wydań Perla.

System typu

W Raku, dynamiczny system typów Perla został rozszerzony przez dodanie typów statycznych . Na przykład:

my Int $i = 0;
my Rat $r = 3.142;
my Str $s = "Hello, world";

Jednak pisanie statyczne pozostaje opcjonalne , więc programiści mogą robić większość rzeczy bez żadnego jawnego pisania:

my $i = "25" + 10; # $i is 35

Raku oferuje stopniowy system pisania , w którym programista może wybrać pisanie statyczne, dynamiczne pisanie lub mieszanie tych dwóch.

Formalne listy parametrów podprogramów

Perl definiuje podprogramy w ogóle bez formalnych list parametrów (chociaż proste liczenie parametrów i bardzo luźne sprawdzanie typów można wykonać za pomocą "prototypów" Perla). Przekazywane argumenty podprogramu są aliasowane do elementów tablicy @_ . Jeśli elementy @_ zostaną zmodyfikowane, zmiany zostaną odzwierciedlone w oryginalnych danych.

Raku wprowadza do języka prawdziwe parametry formalne. W Raku deklaracja podprogramu wygląda tak:

sub do_something(Str $thing, Int $other) {
    ...
}

Podobnie jak w Perlu, parametry formalne (tzn. zmienne na liście parametrów) są aliasami parametrów rzeczywistych (przekazanych wartości), ale domyślnie aliasy są stałe, więc nie można ich modyfikować. Mogą być zadeklarowane jawnie jako aliasy do odczytu i zapisu dla oryginalnej wartości lub jako kopie przy użyciu dyrektyw is rwlub is copyodpowiednio, jeśli programista wymaga ich lokalnej modyfikacji.

Tryby przekazywania parametrów

Raku udostępnia trzy podstawowe tryby przekazywania parametrów: parametry pozycyjne, parametry nazwane i parametry slurpy.

Parametry pozycyjne to typowa uporządkowana lista parametrów używana przez większość języków programowania. Wszystkie parametry można również przekazywać używając ich nazwy w sposób nieuporządkowany. Parametry tylko nazwane (wskazane przez a :przed nazwą parametru) mogą być przekazywane tylko przez określenie ich nazwy, tj. nigdy nie przechwytuje argumentu pozycyjnego. Parametry Slurpy (oznaczone *przed nazwą parametru) są narzędziem Raku do tworzenia funkcji wariadycznych . Slurpy hash przechwyci pozostałe parametry przekazywane przez nazwę, podczas gdy tablica slurpy przechwyci pozostałe parametry przekazywane przez pozycję.

Oto przykład użycia wszystkich trzech trybów przekazywania parametrów:

sub somefunction($a, $b, :$c, :$d, *@e) {
    ...
}

somefunction(1, 2, :d(3), 4, 5, 6); # $a=1, $b=2, $d=3, @e=(4,5,6)

Parametry pozycyjne, takie jak te użyte powyżej, są zawsze wymagane, chyba że następuje po nich ?wskazanie, że są opcjonalne. Nazwane parametry są domyślnie opcjonalne, ale można je oznaczyć jako wymagane przez dodanie !po nazwie zmiennej. Parametry Slurpy są zawsze opcjonalne.

Bloki i zamknięcia

Parametry można również przekazywać do dowolnych bloków, które działają jak domknięcia . W ten sposób, na przykład, fori whileiteratory pętli są nazwane. W poniższym przykładzie lista jest przeszukiwana po 3 elementy na raz i przekazywana do bloku pętli jako zmienne $a, $b, $c.

for @list -> $a, $b, $c {
    ...
}

Jest to ogólnie określane jako „pointy sub” lub „pointy block”, a strzałka zachowuje się prawie dokładnie jak subsłowo kluczowe, wprowadzając anonimowe zamknięcie (lub anonimową procedurę w terminologii Perla).

Niezmienność pieczęci

W Perlu sigile – znaki interpunkcyjne poprzedzające nazwę zmiennej – zmieniają się w zależności od sposobu użycia zmiennej:

# Perl code
my @array = ('a', 'b', 'c');
my $element = $array[1];    # $element equals 'b',
my @extract = @array[1, 2]; # @extract equals ('b', 'c')
my $element = @array[1];    # 'b' comes with a warning (5.10 option)

W Raku sigile są niezmienne, co oznacza, że ​​nie zmieniają się w zależności od tego, czy jest to tablica, czy element tablicy, który jest potrzebny:

# Raku code
my @array = 'a', 'b', 'c';
my $element = @array[1];    # $element equals 'b'
my @extract = @array[1];    # @extract equals ('b')
my @extract = @array[1, 2]; # @extract equals ('b', 'c')

Wariancja w Perlu jest inspirowana zgodnością liczb w języku angielskim i wielu innych językach naturalnych:

"This apple."                    # $a        CORRECT
"These apples."                  # @a        CORRECT
"This third apple."              # $a[3]     CORRECT
"These third apple."             # @a[3]     WRONG

Jednak to mapowanie pojęciowe załamuje się, gdy w grę wchodzą odwołania, ponieważ mogą odnosić się do struktur danych, nawet jeśli są skalarami. Zatem zajmowanie się zagnieżdżonymi strukturami danych może wymagać wyrażenia w jednym terminie zarówno liczby pojedynczej, jak i mnogiej:

# Perl code: retrieve a list from the leaf of a hash containing hashes that contain arrays
my @trans_verbs = @{ $dictionary{ 'verb' }{ 'transitive' } };

Ta złożoność nie ma odpowiednika ani w powszechnym użyciu języka naturalnego, ani w innych językach programowania i powoduje duże obciążenie poznawcze podczas pisania kodu w celu manipulowania złożonymi strukturami danych. To jest ten sam kod w Raku:

# Raku code: retrieve a list from the leaf of a hash containing hashes that contain arrays
my @trans_verbs = %dictionary<verb><transitive><>;

Programowanie obiektowe

Perl obsługuje programowanie obiektowe za pośrednictwem mechanizmu znanego jako błogosławieństwo . Każde odniesienie może zostać pobłogosławione, aby stać się obiektem określonej klasy. Pobłogosławiony obiekt może mieć wywoływane metody przy użyciu „składni strzałek”, co spowoduje, że Perl zlokalizuje lub „wyśle” odpowiedni podprogram według nazwy i wywoła go z pobłogosławioną zmienną jako pierwszym argumentem.

Choć niezwykle potężny, sprawia, że ​​najczęstszy przypadek orientacji obiektowej, obiektu podobnego do struktury z pewnym powiązanym kodem, jest niepotrzebnie trudny. Ponadto, ponieważ Perl nie może przyjmować żadnych założeń dotyczących używanego modelu obiektów , wywoływanie metod nie może być bardzo dobrze zoptymalizowane.

W duchu uczynienia "łatwych rzeczy łatwymi i trudnymi możliwymi", Raku zachowuje model błogosławieństwa i dostarcza bardziej solidny model obiektowy dla typowych przypadków. Na przykład klasa do hermetyzacji punktu kartezjańskiego może być zdefiniowana i użyta w ten sposób:

class Point is rw {
    has $.x;
    has $.y;
    
    method distance( Point $p ) {
        sqrt(($!x - $p.x) ** 2 + ($!y - $p.y) ** 2)
    }
    
    method distance-to-center {
        self.distance: Point.new(x => 0, y => 0)
    }
}

my $point = Point.new( x => 1.2, y => -3.7 );
say "Point's location: (", $point.x, ', ', $point.y, ')';
# OUTPUT: Point's location: (1.2, -3.7)

# Changing x and y (note methods "x" and "y" used as lvalues):
$point.x = 3;
$point.y = 4;
say "Point's location: (", $point.x, ', ', $point.y, ')';
# OUTPUT: Point's location: (3, 4)

my $other-point = Point.new(x => -5, y => 10);
$point.distance($other-point); #=> 10
$point.distance-to-center;     #=> 5

Kropka zastępuje strzałkę w ukłonie w stronę wielu innych języków (np. C++ , Java , Python , itp.), które połączyły się wokół kropki jako składni wywoływania metod.

W terminologii Raku $.xnazywana jest „atrybutem”. Niektóre języki nazywają te pola lub członkami . Metoda używana do uzyskania dostępu do atrybutu nazywana jest „akcesorem”. Metoda autoakcesora to metoda tworzona automatycznie i nazwana na podstawie nazwy atrybutu, tak jak xw powyższym przykładzie. Te funkcje akcesorów zwracają wartość atrybutu. Kiedy klasa lub indywidualny atrybut jest zadeklarowany z is rwmodyfikatorem (skrót od "odczyt/zapis"), autoakcesory mogą otrzymać nową wartość, aby ustawić atrybut, lub mogą być bezpośrednio przypisane jako l- wartość (jak w przykład). Autoakcesory można zastąpić metodami zdefiniowanymi przez użytkownika, jeśli programista życzy sobie bogatszego interfejsu do atrybutu. Dostęp do atrybutów można uzyskać tylko bezpośrednio z definicji klasy za pośrednictwem $!składni, niezależnie od sposobu zadeklarowania atrybutów. Wszystkie inne metody dostępu muszą przejść przez metody akcesora.

System obiektowy Raku zainspirował framework Moose , który wprowadza wiele funkcji OOP Raku do Perla.

Dziedziczenie, role i klasy

Dziedziczenie to technika, dzięki której obiekt lub typ może ponownie użyć kodu lub definicji z istniejących obiektów lub typów. Na przykład programista może chcieć mieć typ standardowy, ale z dodatkowym atrybutem. Dziedziczenie w innych językach, takich jak Java, jest zapewniane przez umożliwienie klasom bycia podklasami istniejących klas.

Raku zapewnia dziedziczenie za pośrednictwem klas, które są podobne do klas w innych językach i ról.

Role w Raku przejmują funkcję interfejsów w Javie , domieszki w Ruby oraz cechy w PHP i w wariancie Smalltalk Squeak . Są one podobne do klas, ale zapewniają bezpieczniejszy mechanizm kompozycji. Są one używane do wykonywania kompozycji, gdy są używane z klasami, a nie dodawane do ich łańcucha dziedziczenia . Role definiują typy nominalne; dostarczają semantycznych nazw dla kolekcji zachowań i stanu. Podstawowa różnica między rolą a klasą polega na tym, że klasy mogą być tworzone; role nie są.

Chociaż role różnią się od klas, możliwe jest napisanie kodu Raku, który bezpośrednio tworzy instancję roli lub używa roli jako obiektu typu, Raku automatycznie utworzy klasę o tej samej nazwie co rola, umożliwiając przezroczyste użycie roli jakby to była klasa.

Zasadniczo rola to zestaw (prawdopodobnie abstrakcyjnych) metod i atrybutów, które można dodać do klasy bez korzystania z dziedziczenia. Rolę można nawet dodać do pojedynczego obiektu; w takim przypadku Raku utworzy anonimową podklasę, doda rolę do podklasy i zmieni klasę obiektu na anonimową podklasę.

Na przykład pies jest ssakiem, ponieważ psy dziedziczą pewne cechy od ssaków, takie jak gruczoły sutkowe i (poprzez rodzica ssaka , Kręgowiec ) kręgosłup . Z drugiej strony psy mogą również wykazywać jeden z kilku różnych typów zachowań, które z czasem mogą się zmieniać. Na przykład Pies może być Zwierzakiem , Bezdomnym (porzucony zwierzak nabędzie zachowań niezwiązanych ze zwierzęciem) lub Przewodnikiem dla niewidomych (psy przewodniki są szkolone, więc nie zaczynają życia jako psy przewodniki) . Są to jednak zestawy dodatkowych zachowań, które można dodać do psa. Możliwe jest również opisanie tych zachowań w taki sposób, aby można je było zastosować do innych zwierząt, na przykład Kot może być w równym stopniu Zwierzakiem jak i Bezdomnym. W związku z tym pies i kot różnią się od siebie, pozostając jednocześnie w bardziej ogólnej kategorii ssaków. Tak więc Mammal to klasa, a Dog i Cat to klasy, które dziedziczą po Mammal. Ale zachowania związane z Zwierzakiem, Bezdomnym i Przewodnikiem są rolami, które można dodać do klas, lub obiektami utworzonymi z klas.

class Mammal is Vertebrate {
    ...
}
class Dog is Mammal {
    ...
}
role Pet {
    ...
}
role Stray {
    ...
}
role Guide {
    ...
}

Role są dodawane do klasy lub obiektu za pomocą doessłowa kluczowego. Aby pokazać dziedziczenie z klasy, istnieje inne słowo kluczowe is. Słowa kluczowe odzwierciedlają różne znaczenia tych dwóch cech: skład ról daje klasie zachowanie roli, ale nie wskazuje, że jest to naprawdę to samo, co rola.

class GuideDog is Dog does Guide {
    ...
}   # Subclass composes role

my $dog = new Dog;
$dog does Guide;       # Individual object composes role

Chociaż role różnią się od klas, oba są typami, więc rola może pojawić się w deklaracji zmiennej, w której normalnie umieściłoby się klasę. Na przykład rola Ślepiec dla Człowieka może zawierać atrybut typu Przewodnik; ten atrybut może zawierać Psa Przewodnika, Konia Przewodnika, Człowieka Przewodnika, a nawet Maszynę Przewodnika.

class Human {
    has Dog $dog;      # Can contain any kind of Dog, whether it does the
    ...                # Guide role or not
}
role Blind {
    has Guide $guide;  # Can contain any object that does the Guide role,
    ...                # whether it is a Dog or something else
}

Wyrażenia regularne

Obsługa wyrażeń regularnych i przetwarzania ciągów Perla zawsze była jedną z jego cech definiujących. Ponieważ konstrukcje dopasowujące do wzorców Perla od pewnego czasu przekraczają możliwości wyrażeń w języku regularnym , dokumentacja Raku będzie odnosić się do nich wyłącznie jako do regexes , dystansując ten termin od formalnej definicji.

Raku zapewnia rozszerzeniem Perl dysponuje w odniesieniu do regexes, składając je w szerszym kontekście zwanej „ zasady ”, które zapewniają możliwości kontekstowych analizowania formalizmach (takich jak składniowych orzeczników z parsowania gramatyk ekspresji i ANTLR ), a także działając jako zamknięcie w odniesieniu do ich zakresu leksykalnego . Reguły wprowadza się za pomocą rulesłowa kluczowego, które ma zastosowanie podobne do definicji podprogramu. Reguły anonimowe można również wprowadzić za pomocą słowa kluczowego regex(lub rx) lub można ich po prostu użyć w tekście, tak jak wyrażenia regularne w Perlu, za pomocą operatorów m(dopasowanie) lub s(podstawienie).

W Apocalypse 5 Larry Wall wymienił 20 problemów z „obecną kulturą wyrażeń regularnych”. Wśród nich były takie, że wyrażenia regularne Perla były „zbyt zwarte i „słodkie”, miały „zbyt małą zależność od zbyt małej liczby metaznaków”, „małą obsługę nazwanych przechwytywań”, „małą obsługę gramatyki” i „słabą integrację z „prawdziwym” język".

Uproszczenie składni

Niektóre konstrukcje Perla zostały zmienione w Raku, zoptymalizowane pod kątem różnych wskazówek składniowych dla najczęstszych przypadków. Na przykład nawiasy (okrągłe nawiasy ) wymagane w konstrukcjach przepływu sterowania w Perlu są teraz opcjonalne:

if is-true() {
    for @array {
        ...
    }
}

Ponadto ,operator (przecinek) jest teraz konstruktorem list, więc umieszczanie nawiasów wokół list nie jest już wymagane. Kod

@array = 1, 2, 3, 4;

teraz tworzy @arraytablicę z dokładnie elementami „1”, „2”, „3” i „4”.

Porównania łańcuchowe

Raku pozwala na porównania do „łańcucha”. Oznacza to, że dozwolona jest sekwencja porównań, taka jak poniżej:

if 20 <= $temperature <= 25 {
    say "Room temperature is between 20 and 25!"
}

Jest to traktowane tak, jakby każde porównanie od lewej do prawej było wykonywane osobno, a wynik jest logicznie łączony za pomocą andoperacji.

Leniwa ocena

Raku wykorzystuje technikę leniwego oceniania list, która była cechą niektórych funkcjonalnych języków programowania , takich jak Haskell :

@integers = 0..Inf; # integers from 0 to infinity

Powyższy kod nie ulegnie awarii przy próbie przypisania tablicy o nieskończonym rozmiarze do tablicy @integers, ani nie będzie zawieszać się w nieskończoność przy próbie rozszerzenia listy, jeśli zostanie przeszukana ograniczona liczba boksów.

Upraszcza to wiele typowych zadań w Raku, w tym operacje wejścia/wyjścia, przekształcenia list i przekazywanie parametrów.

Zbierać

Z leniwą oceną wiąże się konstruowanie leniwych list przy użyciu gatheri take, które zachowują się trochę jak generatory w językach takich jak Icon czy Python .

my $squares = lazy gather for 0..Inf {
    take $_ * $_;
};

$squaresbędzie nieskończoną listą liczb kwadratowych, ale leniwe obliczanie gatherzapewnia, że ​​elementy są obliczane tylko wtedy, gdy są dostępne.

Połączenia

Raku wprowadza pojęcie połączeń : wartości, które są złożeniem innych wartości. W swojej najprostszej postaci węzły tworzy się przez połączenie zbioru wartości z operatorami junctive :

# Example for | ("any") Junction:
my $color = 'white';
unless $color eq 'white' | 'black' | 'gray' | 'grey' {
    die "Color printing not supported\n";
}

# Example for & ("all") Junction:
my $password = 'secret!123';
if $password ~~ /<:alpha>/ & /<:digit>/ & /<:punct>/ {
    say "Your password is reasonably secure";
}

|wskazuje wartość, która jest równa albo jego argumentom po lewej, albo po prawej stronie. &wskazuje wartość, która jest równa zarówno jego argumentom po lewej, jak i po prawej stronie. Te wartości mogą być używane w dowolnym kodzie, który używa normalnej wartości. Operacje wykonywane na skrzyżowaniu działają jednakowo na wszystkie elementy skrzyżowania i łączą się zgodnie z operatorem połączenia. Więc ("apple"|"banana") ~ "s"ustąpi "apples"|"bananas". W porównaniach, węzły zwracają jeden prawdziwy lub fałszywy wynik porównania. anyWęzły „ ” zwracają prawdę, jeśli porównanie jest prawdziwe dla dowolnego elementu skrzyżowania. allWęzły „ ” zwracają prawdę, jeśli porównanie jest prawdziwe dla wszystkich elementów skrzyżowania.

Połączenia mogą być również używane do bogatszego rozszerzania systemu typów poprzez wprowadzenie stylu programowania generycznego, który jest ograniczony do połączeń typów:

subset Color of Any where RGB_Color | CMYK_Color;
sub get_tint(Color $color, Num $opacity) {
    ...
}

Makra

W językach niskiego poziomu koncepcja makr stała się synonimem tekstowego zastępowania kodu źródłowego ze względu na powszechne użycie preprocesora C . Jednak języki wysokiego poziomu, takie jak Lisp, były starsze niż C w użyciu makr, które były znacznie potężniejsze. Raku skorzysta z tej konceptu makro przypominającego Lisp. Siła tego rodzaju makr wynika z faktu, że działa na programie jako wysokopoziomowa struktura danych , a nie jako prosty tekst i ma do dyspozycji pełne możliwości języka programowania.

Definicja makra Raku będzie wyglądać jak definicja podprogramu lub metody i może działać na nieprzeanalizowanych ciągach, AST reprezentującym wstępnie przeanalizowany kod lub kombinację tych dwóch. Definicja makra wyglądałaby tak:

macro hello($what) {
    quasi { say "Hello { {{{$what}}} }" };
}

W tym konkretnym przykładzie makro nie jest bardziej złożone niż podstawienie tekstowe w stylu C, ale ponieważ parsowanie parametru makra następuje przed wykonaniem przez makro operacji na kodzie wywołującym, komunikaty diagnostyczne byłyby znacznie bardziej pouczające. Jednak ponieważ treść makra jest wykonywana w czasie kompilacji za każdym razem, gdy jest używana, można zastosować wiele technik optymalizacji . Możliwe jest nawet wyeliminowanie złożonych obliczeń z programów wynikowych, wykonując pracę w czasie kompilacji.

Identyfikatory

W Perlu nazwy identyfikatorów mogą używać znaków alfanumerycznych ASCII i podkreśleń dostępnych również w innych językach. W Raku znaki alfanumeryczne mogą zawierać większość znaków Unicode. Ponadto można używać myślników i apostrofów (z pewnymi ograniczeniami, takimi jak nie następuje po nich cyfra). Używanie myślników zamiast podkreśleń do oddzielania słów w nazwie prowadzi do stylu nazewnictwa zwanego „ sprawą kebaba ”.

Przykłady

Witaj świecie

Program hello world jest popularnym programem służącym do wprowadzania języka. W Raku hello world to:

say 'Hello, world';

— choć jest na to więcej niż jeden sposób .

Factorial

Funkcja silnia w Raku, definiowana na kilka różnych sposobów:

# Using recursion (with `if\else` construct)
sub fact( UInt $n --> UInt ) {
    if $n == 0 { 1 }
    else       { $n * fact($n-1) }
}

# Using recursion (with `if` as statement modifier)
sub fact( UInt $n --> UInt ) {
    return 1 if $n == 0;
    return $n * fact($n-1);
}

# Using recursion (with `when` construct)
sub fact( UInt $n --> UInt ) {
    when $n == 0 { 1 }
    default      { $n * fact($n-1) }
}

# Using the ternary operator
sub fact( UInt $n --> UInt ) {
    $n == 0 ?? 1 !! $n * fact($n-1)
}

# Using multiple dispatch
multi fact(0) { 1 }
multi fact( UInt $n --> UInt ) {
    $n * fact($n - 1)
}

# Using the reduction metaoperator
sub fact( UInt $n --> UInt ) {
    [*] 1..$n
}

# Creating a factorial operator and using the reduction metaoperator
sub postfix:<!>( UInt $n --> UInt ) { [*] 1..$n }

# Using `state` declarator to create a memoized factorial
sub fact( UInt $n --> UInt ) {
    state %known = 0 => 1;
    return %known{$n} if %known{$n}:exists;
    %known{$n} = $n * fact($n-1);
    return %known{$n};
}

Szybkie sortowanie

Quicksort to dobrze znany algorytm sortowania. Działającą implementację wykorzystującą paradygmat programowania funkcyjnego można zwięźle napisać w Raku:

# Empty list sorts to the empty list
multi quicksort([]) { () }

# Otherwise, extract first item as pivot...
multi quicksort([$pivot, *@rest]) {
    # Partition.
    my @before = @rest.grep(* before $pivot);
    my @after  = @rest.grep(* after $pivot);

    # Sort the partitions.
    flat (quicksort(@before), $pivot, quicksort(@after))
}

Wieża Hanoi

Wieża Hanoi jest często używana do wprowadzenia programowania rekurencyjnego w informatyce. Ta implementacja wykorzystuje mechanizm wielu wysyłek Raku i ograniczenia parametryczne:

multi sub hanoi(0, $, $, $) { }                         # No disk, so do not do anything
multi sub hanoi($n, $a = 'A', $b = 'B', $c = 'C') {     # Start with $n disks and three pegs A, B, C
    hanoi $n - 1, $a, $c, $b;                           # firstly move top $n - 1 disks from A to B
    say "Move disk $n from peg $a to peg $c";           # then move last disk from A to C
    hanoi $n - 1, $b, $a, $c;                           # lastly move $n - 1 disks from B to C
}

Książki

W historii Raku były dwie fale pisania książek. Pierwsza fala nastąpiła po pierwszym ogłoszeniu Perla 6 w 2000 roku. Książki te odzwierciedlają stan projektu języka tamtych czasów i zawierają głównie przestarzały materiał. Druga fala, która nastąpiła po ogłoszeniu wersji 1.0 w 2015 roku, obejmuje kilka książek, które zostały już opublikowane i kilka innych, które są w trakcie pisania.

Książki opublikowane przed Perl 6 w wersji 1.0 (znanej jako wersja 6.c)

  • A. Randal, D. Sugalski, L. Totsch. Perl 6 i Parrot Essentials , wydanie 1, 2003, ISBN  978-0596004996
  • A. Randal, D. Sugalski, L. Totsch. Perl 6 i Parrot Essentials , wydanie drugie 2004. ISBN  978-0596007379
  • S. Waltersa. Perl 6 teraz: podstawowe idee zilustrowane w Perl 5. 2004. ISBN  978-1590593950

Ponadto w 2009 roku ukazała się książka poświęcona jednej z pierwszych maszyn wirtualnych Perla 6, Parrot.

Książki opublikowane po Perl 6 w wersji 1.0 (znanej jako wersja 6.c)

Książki opublikowane pod nową nazwą Raku

Książki do opublikowania

Istnieje kilka raportów różnych autorów na temat nowych książek, które zostaną wkrótce opublikowane, wszystkie oparte na aktualnej wersji 1.0 (znanej jako wersja 6.c) Perla 6.

Bibliografia

Zewnętrzne linki