Raku (tidigare Perl 6) | |
---|---|
Språkklass | Multi-paradigm |
Framträdde i | Utvecklingen har pågått sedan 2000. Den första releasen ägde rum den 25 december 2015 |
Författare | Larry Wall |
Utvecklaren | Larry Wall och Audrey Tan |
Filtillägg _ | .raku, .rakumod, .rakudoc, .rakutesteller.t |
Släpp | 6.d (24 februari 2020 ) |
Typ system | dynamisk, statisk |
Blivit påverkad |
haskel , JavaScript , Perl , Ruby , Smalltalk , J |
påverkas | Perl , Haskell , AntLang |
Licens | GNU General Public License , Artistic License |
Hemsida | raku.org |
OS | plattformsoberoende |
Raku (av japanska 楽土, pron. rakudo - Paradise , [1] [2] och från 楽, pron. raku - happiness, ease, sukha [3] [4] ) är ett programmeringsspråk från familjen Perl -liknande språk . En stor översyn av både designen och implementeringen av Perl-språket, vilket bröt bakåtkompatibiliteten med det, även om kompatibilitetsläget fortfarande var tänkt att existera fram till 2010. [5]
Precis som Perl-språket lämnar Raku mycket frihet för programmerare . Det låter dig fortfarande uttrycka dig kortfattat, inklusive att skriva enkla texter, men det förenklar också att skriva stora program, tack vare statisk skrivning och förbättrat OOP- stöd .
Rakus tidigare namn var Perl 6. [6] Under många år har det förekommit skämt i Perl-communityt om releasedatumet. På frågan "när Perl 6 kommer att släppas" var det vanliga svaret "vid jul", men utan ett år. [7] [8] 2015, det vill säga efter femton års väntan, tillkännagavs äntligen den så kallade "Jul"-versionen. [9] [10] [11]
I Perl 6 bestämde vi oss för att det var bättre att fixa språket än att fixa användaren.Larry Wall [12]
Utvecklingen av Perl 6 tillkännagavs först av Larry Wall den 19 juli 2000, den fjärde dagen av det årets Perl-konferens, [13] i hans State of the Onion -talk . [14] På den tiden var prioriteringarna: att ta bort de "historiska vårtorna" från språket; "enkla saker måste förbli enkla, komplexa saker måste bli enklare och omöjliga saker måste bli komplexa"; allmän rengöring av intern design och API . Processen började med en serie RFC:er . Denna process var öppen för alla deltagare, och ingen aspekt av språket lämnades stängd för förändring. [femton]
361 förfrågningar kom in, som alla granskades av Wall. Han började sedan processen att skriva flera "Apokalypser", en kristen term som betyder "avslöja goda nyheter för goda människor." [16] Även om det ursprungliga målet var att skriva en Apocalypse för varje kapitel i en:Programming Perl- boken , blev det uppenbart att när varje Apocalypse skrevs, åsidosattes tidigare Apocalypses av senare ändringar. Av denna anledning publicerades en uppsättning synopser, var och en hänvisade till en enda Apocalypse men inklusive korrigeringar från nya Apocalypses. Idag drivs Raku-specifikationen av "roast"-testsviten, [17] medan synopses hålls som historisk referens. [arton]
Det finns också en serie Exegesis skriven av Damian Conway som förklarar innehållet i varje Apocalypse i termer av praktisk användning. Varje Exegesis består av kodexempel med en diskussion om deras användning och betydelse. [19]
Huvudmålet som Wall föreslog i sitt ursprungliga tal var att ta bort "historiska vårtor". Dessa inkluderade förvirring i sigils av arrayer och hash, tvetydighet i funktioner select, problem med användningen av blotta [20] (utan skiljetecken [21] ) fildeskriptorer. Wall nämnde också många andra problem i sitt tal som Perl-programmerare har diskuterat i flera år.
Konsekvensen av dessa mål var förlusten av bakåtkompatibilitet. Eftersom bakåtkompatibilitet vanligtvis antyds när programvaran förbättras, borde ändringarna i Perl 6 som bryter den ha angetts uttryckligen. Gradvis blev skillnaden mellan Perl 5 och Perl 6 så stor att Perl 6 döptes om till Raku den 12 oktober 2019 . [6]
Under åren har utvecklingsvektorn för Raku förändrats flera gånger. Införandet av koncept från Python och Ruby var ett tidigt inflytande. [22] [23] [24] Dessutom är Pugs, den första Raku-tolken, skriven på det funktionella språket Haskell , och många delar av funktionell programmering har absorberats av Raku-utvecklingsteamet. [25] [26]
Tungans maskot är insekten Camellia. [27] Dess namn är en hänvisning till Perl-språkemblemet, kamelen ("Kamelen"), och dess form, i traditionen av den ordleksälskande Perl-gemenskapen, ekar ordet " kryp ". Spiralmönstren inskrivna i dess fjärilsliknande vingar påminner om "P6"-karaktärerna, och den divergerande kisningen är en avsiktlig ordlek på "Wall-eyed". [28]
Ett av målen med den livliga och färgglada logotypdesignen var att motverka kvinnohat i samhället och tillåta människor med "maskulina övertygelser" att visa sin känsliga sida. [29]
Rakudo är den mest utvecklade implementeringen, [30] vilket inte gör det till den officiella versionen av språket, som språket definieras inte av implementeringen, utan av testsviten. [31]
Rakudo låter dig exekvera [32] kod i virtuella MoarVM-, JVM- och Node.js - maskiner . [33] MoarVM är en virtuell maskin byggd specifikt för Rakudo och NQP-kompilatorn. [34] [35] NQP -kompilatorn (Not Quite Perl 6 ) implementerar en delmängd av språket som inkluderar Raku-regler för källkodsanalys, abstrakt syntaxträdmanipulation och backend-specifik kodgenerering . Mycket av Rakudo är skrivet i Raku och NQP. Rakudo är inte en fristående kompilator, och det finns inga planer på att marknadsföra kompilatorn för närvarande.
Efter version "2015.02" tappade Rakudo stödet för den virtuella maskinen Parrot [36] (föregångaren till MoarVM), byggt på det felaktiga antagandet att Perl 6 skulle likna Perl 5. [37] [38]
Den första implementeringen av Raku var Pugs [39] , en tolk och kompilator skriven i Haskell . Var den mest avancerade implementeringen, men endast minimala korrigeringar har gjorts sedan 2007 för att hålla jämna steg med nya versioner av GHC , och från och med november 2014 stöds inte Pugs. [40] I augusti 2006 delade Yichun Zhang upp Pugs-testfilerna i fragment och bifogade lämpliga Synapsis-stycken till dem, [41] [42] och i januari 2008 integrerades dessa tester i de officiella språktesten ("roast") ”). [43] [44] I februari 2015 förklarade gemenskapen att språktest var en specifikation. [45]
Raku och Perl är fundamentalt olika, även om avsikten var att behålla Raku som Perl. De flesta ändringarna syftar till att normalisera språket så att det är lättare att förstå för både nybörjare och erfarna programmerare, och att göra "enkla saker enklare och komplexa saker mer möjliga."
Den huvudsakliga icke-tekniska skillnaden är att Raku började som en specifikation. [31] Detta innebär att Raku kan implementeras om vid behov, och även att programmerare inte behöver läsa källkoden för att få full kontroll över någon av dess funktioner. När det gäller Perl-språket beskriver den officiella dokumentationen endast beteendet hos den aktuella tolken. Eventuella avvikelser som hittas mellan dokumentationen och implementeringen kan resultera i att antingen det ena eller det andra ändras, vilket är drivkraften bakom den pågående utvecklingen och förbättringen av Perl-utgåvor.
I Raku har det dynamiska typsystemet kompletterats med statiska typer . [46] Till exempel:
min Int $i = 0 ; min råtta $r = 3.142 ; min Str $s = "Hej världen" ;Statiska typer förblir dock valfria, så programmerare kan göra det mesta utan att uttryckligen ange typer.
min $i = "25" + 10 ; # $i är 35I Perl har subrutiner inga formella parametrar , även om enkel kontroll av antalet och typerna av parametrar är möjlig med hjälp av subrutinprototyper. [47] Istället är de faktiska parametrarna som skickas med referens gömda bakom arrayelementen @_i subrutinkroppen.
Verkliga formella parametrar visas i Raku. [48] Till exempel:
sub do_something ( Str $thing , Int $other ) { ... }Precis som i Perl skickas i Raku parametrar genom referens, men som standard i Raku är de konstanta , dvs. deras värden kan inte ändras. De kan uttryckligen deklareras för att tillåta att det ursprungliga värdet ändras ( is rw) eller som kopior ( is copy), vilket motsvarar att passera efter värde.
Sätt att skicka parametrarDet finns tre sätt att skicka parametrar i Raku: positional, named och slurpy .
Positionsparametrar är bara en ordnad lista, som i de flesta programmeringsspråk. Även de kan passeras i en godtycklig ordning, så länge som deras namn anges. Parametrar som endast kan skickas med namn betecknas med en symbol :före sigilen för den formella parametern. Squishing parametrar är ett sätt att skapa variabla funktioner i Raku. De indikeras med en symbol *före sigilen för den formella parametern. Den slurpy-hash kommer att fånga de namngivna parametrarna som inte nämns i subrutindeklarationen, och slurpy-arrayen kommer att fånga de efterföljande positionella faktiska parametrarna.
I följande exempel är alla tre metoderna närvarande, inklusive en slurpy array.
sub somefunction ( $a , $b , : $c , : $d , * @e ) { ... } någon funktion ( 1 , 2 , : d ( 3 ), 4 , 5 , 6 ); # $a=1, $b=2, $d=3, @e=(4,5,6)Positionsparametrar krävs som standard om inte parameternamnet följs av ett frågetecken. Namngivna standardparametrar, å andra sidan, är valfria om inte namnet följs av ett utropstecken. Squishy parametrar är alltid valfria.
Block och stängningarParametrar kan också skickas till alla kodblock som beter sig som stängningar . forI synnerhet är till exempel kretsloppen whilestängningar. I följande exempel tar loopen tre element från listan åt gången och skickar dem till blocket som variablerna $a, $boch $c. [49]
för @list -> $a , $b , $c { ... }Detta kallas "pointy sub" eller "pointy block", och pilen i det beter sig lite som ett nyckelord sub, vilket introducerar en anonym stängning (eller en anonym subrutin i Perl-terminologi). [48]
I Perl ändras sigils (skiljetecken som visas före variabelnamn) beroende på hur variabeln används .
# Perl-kod min @ array = ('a', 'b', 'c'); mitt $element = $ array[1]; # returnerar 'b', mitt @extract = @array [ 1, 2]; # returnerar ('b', 'c') mitt $element = @array [1]; # returnerar 'b' med varning (sedan 5.10)I Raku är sigiler invarianta: både en array och ett arrayelement kommer att ha samma sigil. [46]
# Raku-kod min @ array = 'a', 'b', 'c'; mitt $element = @array [1]; # $element är skrivet 'b' mitt @extract = @array [ 1]; # @extract skrivs ('b') mitt @extract = @array [ 1, 2]; # @extract skrivs ('b', 'c')Variabiliteten av sigils i Perl är inspirerad av talkonventionen på engelska och många andra naturliga språk .
" Det är ett äpple." # $a är sant " Dessa äpplen." # @en sann " Detta är det tredje äpplet." # $a[3] är sant " Detta är det tredje äpplet." # @a[3] är inte korrektDetta koncept bryts dock när referenser kommer till spel, eftersom de kan referera till datastrukturer samtidigt som de är skalärer. Att arbeta med kapslade datastrukturer kan därför kräva att både singular och plural uttrycks i samma term:
# Perl-kod: hämta en array från ett hash-element. # Denna hash lagrar hash som innehåller arrayer. mitt @trans_verbs = @ { $dictionary { 'verb' }{ 'transitive' } };Sådana konstruktioner har inga analoger i vanliga naturliga språk, vilket orsakar en hög kognitiv belastning när man skriver kod. Samma Raku-kod:
# Raku-kod: hämta en array från ett hash-element. # Denna hash lagrar hash som innehåller arrayer. mina @trans_verbs = %ordbok<verb><transitive><> ;I Perl-språket stöds objektorienterad programmering genom en funktion som gör vilken variabel som helst till ett objekt av en viss klass, varifrån metoderna som deklareras i klassen blessblir tillgängliga att anropa . [femtio]
Även om den är extremt kraftfull, gör denna mekanism det samtidigt svårt att beskriva även de mest grundläggande OOP - enkla strukturliknande objekt med tillhörande procedurer. Dessutom, eftersom Perl inte gör några antaganden om objektmodellen, kan metodanrop inte optimeras av kompilatorn.
Raku behåller lågnivåmetoden bless, men tillhandahåller också en mer restriktiv objektmodell för vanliga användningsfall. [51] [52] Till exempel kan en klass som kapslar in en punkt i ett kartesiskt koordinatsystem definieras enligt följande:
klass Punkten är rw { har $.x ; har $.y ; metodavstånd ( Point $p ) { sqrt ( ( $!x - $p . x ) ** 2 + ( $!y - $p . y ) ** 2 ) } metod avstånd till centrum { själv . avstånd: Punkt . ny ( x => 0 , y => 0 ) } } min $point = Point . ny ( x => 1,2 , y => -3,7 ); säg "Punktposition: (" , $punkt . x , ', ' , $punkt . y , ')' ; # Punktposition: (1,2, -3,7) # Ändra x och y (med "x" och "y" metoderna): $point . x = 3 ; $point . y = 4 ; säg "Punktposition: (" , $punkt . x , ', ' , $punkt . y , ')' ; # Punktposition: (3, 4) min $other-point = Point . ny ( x => -5 , y => 10 ); $point . avstånd ( $other-point ); #=> 10 $point . avstånd till centrum ; #=> 5I Perl anropas metoder med en pil: $object->method(). Raku använder en prick istället för en pil som många andra språk (som Java och Python).
I Raku-terminologi $.xkallas det ett attribut. Metoden som används för att komma åt ett attribut kallas en accessor [53] (från engelska access - access). Det skapas automatiskt (när ett attribut deklareras med en punkt [54] ) och heter samma namn som attributet. Det fungerar som en getter och när en klass eller attribut is rwtar på sig egenskaperna hos en setter och kan användas på vänster sida av en uppgift. Istället för automatiska accessorer kan programmeraren definiera sina egna anpassade metoder. Dessutom, i klasskroppen, kan alla attribut, oavsett hur de deklareras, nås direkt med hjälp av $!.
Arv, roller och klasserArv är en teknik där objekt eller typer återanvänder logik eller definitioner från andra objekt eller typer. Till exempel kan en programmerare göra en standardtyp med ett valfritt attribut. I språk som Java tillhandahålls arv av klasser, som kan vara underklasser till andra befintliga klasser.
Raku ger också arv genom klasser, liknande klasser i andra programmeringsspråk, såväl som genom roller.
Roller i Raku tar på sig funktionen av gränssnitt i Java, mixins i Ruby, egenskaper [55] i PHP och Squeak (en dialekt av Smalltalk-språket ). De liknar klasser, men ger en säkrare sammansättningsmekanism än arv som förhindrar attribut- och metodnamnskonflikter. [56] [57] Roller är inte inbyggda i en arvskedja. Roller avser det nominella typsystemet (se sv:Nominellt typsystem ), inte det strukturella typsystemet, som används till exempel i Go . De ger semantiska namn för uppsättningar av beteenden och tillstånd. Den grundläggande skillnaden mellan roller och klasser är att roller inte instansierar objekt. [58]
Även om roller skiljer sig från klasser är det möjligt att skriva kod som skapar ett objekt från en roll. Ett försök att använda en roll för att skapa ett objekt kommer att resultera i skapandet av en klass med samma namn. Raku-dokumentationen kallar denna mekanism för automatisk rollspelning. den genererade klassen är en ordlek. [59]
I huvudsak är roller buntar av attribut och potentiellt abstrakta metoder som kan läggas till en klass utan att använda arv. En roll kan till och med läggas till ett enda objekt. I det senare fallet kommer Raku att skapa en anonym underklass, lägga till en roll till den och ersätta objektets klass med den anonyma underklassen.
Till exempel är en hund ett däggdjur , eftersom hundar ärver vissa egenskaper från däggdjur, såsom bröstkörtlar och, genom sina ryggradsdjurs förfäder , ryggraden . Å andra sidan kan hundar ha olika typer av beteenden som kan förändras över tid. Till exempel kan en hund vara tam, bortsprungen, vara guide . Dessa uppsättningar av ytterligare beteenden kan läggas till hunden. Du kan beskriva dem på ett sådant sätt att du kan tillämpa dem på andra djur. Till exempel kan en katt vara tam och herrelös. Hunden och katten är skilda från varandra, men förblir i den allmänna kategorin däggdjur. Så, Млекопитающее är en klass, Собакаoch Кошка är klasser som ärvts från ett däggdjur. Men ovanstående beteenden är roller som kan läggas till klasser eller objekt skapade från klasser.
klass Däggdjur är ryggradsdjur { ... } klass Hund är däggdjur { ... } roll Pet { ... } roll Hemlös { ... } rollguide { _ ... }Roller läggs till i klasser och objekt med hjälp av does. För arv används nyckelordet is. Dessa ord återspeglar en skillnad i betydelsen av dessa språkdrag: att fästa en roll ger en klass beteendet som en roll, men betyder inte att klassen blir bokstavligen densamma som den rollen.
klass Ledarhund är ledarhund gör ledarhund { ... } # Underklass bifogar en roll. min $hund = Hund . ny (); $dog gör ledarhund ; # Objektet fäster rollen.Både roller och klasser är typer. En roll kan användas i en variabeldeklaration. Till exempel kan en roll Незрячийinnehålla ett attribut av typen Поводырь, som kan vara en ledarhund, en ledarhäst, en guideperson eller till och med en ledarbil.
class Human { har Hund $dog ; # Kan innehålla vilken typ av hund som helst - ... # det spelar ingen roll om det är en ledarhund eller inte. } role Blind { har Guide $guide ; # Kan innehålla vilket objekt som helst med rollen som ... # Guide - oavsett om det är en hund eller inte. }Reguljära uttryck och strängmanipulation har alltid varit en av Perls avgörande egenskaper. [60] Eftersom Perls mönster överträffade reguljära uttryck någon gång, [61] hänvisar Raku-dokumentationen helt enkelt till dem som regex , och tar avstånd från den formella definitionen av reguljära uttryck.
Raku utökar Perls funktionsuppsättning kring reguljära uttryck genom att kapsla in dem i ett större ramverk för att bygga parsers som kallas regler . [62] Regler tillhandahåller kontextkänsliga analysfunktioner (som det syntaktiska predikatet från PEG och ANTLR ) och beter sig som avslutningar om deras lexikaliska omfång . [63] Regler skrivs in med nyckelordet rule, som liknar att definiera en subrutin. Anonyma regler kan anges med nyckelordet regex(eller ) rxeller så kan de beskrivas som reguljära uttryck i Perl med operatorerna m(matcha) eller s(ersätt).
I Apocalypse 5 listar Larry Wall 20 problem med den nuvarande "regexkulturen". Bland annat var Perl reguljära uttryck "för kompakta och 'söta'", de "litade för mycket på för få specialtecken", de hade "dåligt stöd för namninfångning", "svagt grammatikstöd" och "dålig språkintegration" . ". [64]
Vissa Perl-konstruktioner i Raku har ändrats och optimerats för andra syntaktiska uttryck. Till exempel är parenteser, som krävdes i exekveringsordersatser , nu valfria. [49]
if is-true () { för @array { ... } }Operatorn ,(komma) är nu en listkonstruktor, så parenteser runt listor krävs inte.
@array = 1 , 2 , 3 , 4 ;Raku tillåter följande uttryck:
om 20 <= $temperatur <= 25 { säg "Temperaturen i rummet är mellan 20 och 25 grader!" }Detta uppfattas som sekventiella jämförelser från vänster till höger, följt av en förening genom ett logiskt OCH .
Raku använder en utvärderingsteknik för lata listor som liknar vissa funktionella språk som Haskell : [65]
@heltal = 0 .. inf ; # heltal från noll till oändligtDen här koden kommer inte att ge ett fel när du försöker lägga in en oändlig lista i en array @integers, och den kommer inte att hänga sig för att försöka utöka listan på obestämd tid om ett ändligt antal element efterfrågas.
Detta förenklar många vanliga uppgifter i Raku, inklusive I/O-operationer, listtransformationer och parameteröverföring.
Det är också möjligt att skapa lata listor med hjälp av nyckelorden gatheroch take. De liknar generatorerna i Icon och Python .
mina $kvadrater = lata samla för 0 .. Inf { take $_ * $_ ; };Här $squaresär en oändlig lista med kvadrater av naturliga tal (inklusive noll), men på grund av den lata karaktären hos denna lista, utvärderas elementen bara när de nås. [66]
Raku introducerar begreppet korsningar [67] ( eng. korsning - anslutning, korsning; i Raku är denna term också relaterad till konjunktion och disjunktion [65] ). Det är en överlagring av flera värden. [65] I sin enklaste form skapas en korsning av korsningsoperatorerna :
# Ett exempel på typkorsning | ("alla"): min $färg = 'vit' ; om inte $color eq 'vit' | 'svart' | 'gray' { die "Utskrift i denna färg stöds inte.\n" ; } # Ett exempel på ett kors som & ("alla"): mitt $password = 'hemligt!123' ; if $password ~~ /<:alpha>/ & / <:digit> / & / <:punct> / { säg "Ditt lösenord är tillräckligt starkt." ; }Operatören |uttrycker ett värde som är lika med antingen vänster eller höger argument, operatorn & - både vänster och höger. Dessa värden kan användas i kod varhelst ett värde är tänkt att vara semantiskt. Alla operationer med korsning verkar samtidigt på alla dess komponenter, och resultatet kombineras genom operatören av denna korsning. Ja, det ("apple"|"banana") ~ "s"kommer tillbaka "apples"|"bananas". Men i ett booleskt sammanhang returnerar kors endast ett värde, sant eller falskt: anydet returnerar sant om jämförelsen är sann för minst ett element; allreturnerar sant om jämförelsen är sann för alla element. [68]
Med hjälp av korsningar är det möjligt att utöka typsystemet med någon form av generisk programmering som begränsar variabler till typkorsningar.
delmängd Color of Any where RGB_Color | CMYK_Color ; sub get_tint ( Färg $color , Num $opacity ) { ... }Crossovers är speciella objekt som delar upp kodexekvering i potentiellt parallella trådar . Och de är designade specifikt för användning i ett booleskt sammanhang: du kan inte komma åt deras innehåll direkt utan att konvertera dem till en sträng, vilket skiljer dem till exempel från set och andra samlingar. [68]
I lågnivåspråk har makron blivit synonymt med textersättning i källkoden på grund av associationer till C-förprocessorn . Men i högnivåspråk som Lisp , som föregick C , var makron mer kraftfulla. [69] Det var detta Lisp-liknande koncept av makron som Raku drog fördel av. [48] Kraften i denna typ av makro är baserad på att använda programmet som en datastruktur på hög nivå snarare än text, och på tillgång till alla funktioner i språket.
En makrodefinition i Raku ser ut som en subrutin eller metoddefinition. Och ett sådant makro kan fungera med både källkod och ett abstrakt syntaxträd och en kombination av dessa två saker.
macro hej ( $what ) { quasi { säg "Hej {{{{$what}}} }" }; }I exemplet ovan analyseras makroargumentet innan makrot exekveras, vilket leder till mer informativa diagnostiska meddelanden från kompilatorn. Men eftersom exekveringen av makrokroppen sker vid kompileringstidpunkten (för varje användningsfall), kan en mängd olika optimeringstekniker tillämpas . Med hjälp av makron är det till och med möjligt att göra det mesta av vissa program innan de börjar köra .
I Raku kan identifierare även innehålla apostrof och bindestreck förutom bokstäver, siffror och understreck, så länge de följs av bokstäver. Bokstäver inkluderar "motsvarande" (vilket är implementeringsberoende) Unicode-tecken , som definieras i Rakudo och MoarVM som alla Unicode-tecken i kategorin "L". [70]
Användningen av bindestreck istället för understreck kallas " kebabfallet ". [71] [72] [73]
Metaoperatorer är operatorer som kan parametriseras av andra operatorer, precis som funktioner kan ta andra funktioner som parametrar. [74]
TilldelningsmetaoperatorPerl har ärvt C-språkoperatorer som +=, *=och så vidare. Raku generaliserar dem till en metaoperator. För vilken binär operator som helst kan opvi skriva:
$x op = $y ; # eller $x [op]= $yVad betyder:
$x = $x på $y ;Dessutom fungerar detta även för användardefinierade operatörer.
HyperoperatorerDe liknar operatören mapi Perl. Tvinga operatörer att arbeta på alla matrisvärden. Kan appliceras på både binära och unära operatorer. [75]
Till exempel kommer följande kod att skapa en array som innehåller alla element i arrayen @aökat med ett:
min @aPlusOne = @a "+" 1 ; # eller @a >>+>> 1Riktningen på vinkelparenteserna påverkar beteendet när arrayer av olika längd skickas som parametrar. [75] Dessa "pilar" visar var längden på resultatet av operationen kommer ifrån.
Ett exempel på att använda en hyperoperator med en unäroperator:
min @a = 1 , 2 , - 3 ; min @b = -<< @a ; # [-1 -2 3]Hyperoperatorer fungerar inte bara för platta arrayer utan också för kapslade arrayer. [76]
ReduktionsmetaoperatorReduktionsmetaoperatorn kan användas med vilken infix- operator som helst och konverterar den till en listreduktionsoperator . Det är som om operatorn tillämpades på de två första elementen, sedan på det resulterande värdet och det tredje elementet, och så vidare tills bara ett värde återstår. Summan, produkten, maximum, minimum, etc. kan fungera som en operatörsparameter. Detta är en extremt kraftfull mekanism som till exempel översätter operatorn +till en listsummaoperator, som i exemplet nedan.
säg "Summan av heltal från 0 till 99 är: " , [+] ^ 100 ; KorsoperatorDen beter sig både som en operatör och som en meta-operatör. [77]
Korsoperatorn [75] hittar den direkta produkten av listor ordnade på ett sådant sätt att uppräkningen av element från den högra operanden är snabbare än från den vänstra operanden, [77] returnerar en sekvens av listor:
1 .. 3 X <ab c> X <de f> ; # ((1 annons) (1 ae) (1 af) # (1 bd) (1 be) (1 bf) # (1 cd) (1 ce) (1 cf) # (2 ad) (2 ae) ( 2 af) # (2 bd) (2 be) (2 bf) # (2 cd) (2 ce) (2 cf) # (3 ad) (3 ae) (3 af) # (3 bd) (3 be) ) (3 bf) # (3 cd) (3 ce) (3 cf))Metaoperatorn kollapsar interna listor med parameteroperatorn: [77]
1 .. 3 X ~ <ab c> X ~ <de f> ; # (1ad 1ae 1af 1bd 1be 1bf 1cd 1ce 1cf # 2ad 2ae 2af 2bd 2be 2bf 2cd 2ce 2cf # 3ad 3ae 3af 3bd 3be 3bf 3cd 3ce 3ce ) Zip-operatörFrån engelska. dragkedja - dragkedja . [78]
Liksom korsoperatorn, kombinerar element av listor, [75] men returnerar en sekvens som innehåller först de första elementen i varje lista, sedan de andra elementen i varje lista, och så vidare. [79]
<ab c> Z <1 2 3 4> ; # ((a 1) (b 2) (c 3)) 100 , 200 Z + 42 , 23 ; # (142 223) Omvända operatorerMetaoperatorn R( eng. reversed ) låter dig byta argument för den ursprungliga operatorn.
säg "En dividerad med tre är lika med" , 3 R / 1 ; Nesting av meta-operatorerResultatet av att applicera en meta-operator på en operatör är en annan operatör, till vilken meta-operatorn kan appliceras igen, och så vidare. För att disambiguera syntaxen tillåts hakparenteser. [80]
min @a = 1 , 2 , 3 ; min @b = 5 , 6 , 7 ; @a >>>>> @b ; # Analysfel. @a >>[>]>> @b ; # [False False False] # Här appliceras hyperoperatorn >> >> på jämförelseoperatorn. # Cross-meta-operatorn gäller # för meta-tilldelningsoperatorn # parametriserad av additionsoperatorn: @a X [+=] @b ; # (6 12 19 7 13 20 8 14 21) # På grund av cross-meta-operatorn gjordes tilldelningen # för varje element i array @a med varje element i array @b, # vilket motsvarar att lägga till varje element i array @a # summan av elementen i array @b: säg [+] @b ; #18 säg @a ; # [19 20 21]Precis som andra moderna språk är Raku designad för att stödja samtidighet och asynkron programmering.
Raku tillhandahåller ett enkelt, modulärt API på hög nivå för att skriva samtidig kod, oberoende av hur den virtuella maskinen implementerar detta API. Dessutom kan vissa språkfunktioner implicit fungera asynkront. För att säkerställa hanterbarhet och kompatibilitet mellan dessa funktioner bör användarkod så långt det är möjligt undvika användningen av lågnivågränssnitt ( trådar , schemaläggare, lås ). [81]
Löften [82] [83] är den centrala högnivåmekanismen , som är resultatet av beräkningar som erhållits innan de faktiskt slutfördes. De kan ges, utföras och kränkas. Således har de tre möjliga tillstånd. Styrkan hos denna mekanism ligger i förmågan att kombinera dem och koppla dem till kedjor:
min $p1 = Löfte . ny (); min $p2 = $p1 . sedan ({ säg "Resultat av andra löftet." });Här thensäkerställer den exekvering $p2först efter exekvering av $p1.
Det finns även engelska. Supplies ("lager") och eng. Leverantörer ("leverantörer") - en mekanism för att skapa asynkrona dataflöden med möjligheten att behandla varje meddelande av flera mottagare samtidigt, liknande hur händelsehanterare fungerar i andra programmeringsspråk. [81] Denna mekanism kan användas för händelsestyrd programmering .
Slutligen är kanaler ( engelska kanaler ) trådsäkra FIFO- köer , liknande namngivna pipelines i operativsystem, men som fungerar inom den nuvarande processen. Den viktigaste skillnaden mot Supplyär att en läsning från en pipe är en dequeue, [81] d.v.s. ett värde kan endast läsas en gång.
Program "Hej världen!" används ofta för att demonstrera den grundläggande syntaxen för ett språk. I Raku ser det ut så här:
säg 'Hej världen' ;Även om det förstås finns mer än ett sätt att uttrycka det på. [84]
Faktoriell beräkning , definierad på flera sätt:
# Använda rekursion med en "om-annas"-konstruktion. sub fact ( UInt $n --> UInt ) { if $n == 0 { 1 } else { $n * fact ( $n-1 ) } } # Använda rekursion med "if" # som en uttrycksmodifierare. sub fact ( UInt $n --> UInt ) { return 1 if $n == 0 ; returnera $n * faktum ( $n-1 ); } # Använda rekursion med "när"-konstruktionen. subfakta ( UInt $ n --> UInt ) { när $n == 0 { 1 } standard { $n * fact ( $n-1 ) } } # Använda den ternära operatorn. sub fakta ( UInt $n --> UInt ) { $n == 0 ?? 1 !! $n * faktum ( $n-1 ) } # Använder flera utskick. multi fact ( 0 ) { 1 } multi fact ( UInt $n --> UInt ) { $n * fact ( $n - 1 ) } # Använda reduktionsmetaoperatorn. underfakta ( UInt $ n --> UInt ) { [*] 1 .. $n } # Definition av den faktoriella operatorn, # implementerad via reduktionsmetaoperatorn. subpostfix : <!>( UInt $n --> UInt ) { [*] 1 .. $n } # Använda nyckelordet "state" för memoisering. sub fact ( UInt $n --> UInt ) { state %known = 0 => 1 ; returnera %known { $n } om %known { $n }: finns ; %känd { $n } = $n * faktum ( $n-1 ); returnera %känd { $n }; }QuickSort är en välkänd sorteringsalgoritm. Dess implementering med hjälp av det funktionella paradigmet kan kortfattat skrivas [a] så här:
# En sorterad tom lista är en tom lista. multi quicksort ([]) { () } # Annars, ta det första elementet som pivot... multi quicksort ([ $pivot , * @rest ]) { # Dela upp elementen i en lista med de # mindre än pivoten och de # större än pivoten. mitt @före = @vila . grep (* före $pivot ); min @efter = @vila . grep (* efter $pivot ); # Sortera dessa underlistor och sammanfoga resultatet. platt ( quicksort ( @before ), $pivot , quicksort ( @after )) }Detta pussel används ofta för att introducera rekursion inom datavetenskap . Denna implementering använder multimetoder med en bokstavlig 0 som en del av .
multi sub hanoi ( 0 , $, $, $) { } # Inga diskar. Det finns inget att överföra. multi sub hanoi ( $n , $a = 'A' , $b = 'B' , $c = 'C' ) { # $n diskar och tre spön: A, B, C. hanoi $n - 1 , $ a , $c , $b ; # Flytta ($n - 1) enheter från A till B säger "Flytta enhet $n från $a till $c." ; # Flytta den sista disken från A till C. hanoi $n - 1 , $b , $a , $c ; # Flytta ($n - 1) diskar från B till C. } hanoi ( 5 ); # Lösning för fem diskar.Perl | |
---|---|
människor |
|
Saker | |
Ramar |
|
|