Raku (tidligere Perl 6) | |
---|---|
Sprog klasse | Multi-paradigme |
Dukkede op i | Udviklingen har stået på siden 2000. Den første udgivelse fandt sted den 25. december 2015 |
Forfatter | Larry Wall |
Udvikler | Larry Wall og Audrey Tan |
Filtypenavn _ | .raku, .rakumod, .rakudoc, .rakutesteller.t |
Frigøre | 6.d (24. februar 2020 ) |
Type system | dynamisk, statisk |
Blev påvirket |
haskel , JavaScript , Perl , Ruby , Smalltalk , J |
påvirket | Perl , Haskell , AntLang |
Licens | GNU General Public License , kunstnerisk licens |
Internet side | raku.org |
OS | på tværs af platforme |
Raku (fra japansk 楽土, pron. rakudo - Paradise , [1] [2] og fra 楽, pron. raku - happiness, ease, sukha [3] [4] ) er et programmeringssprog fra familien af Perl -lignende sprog . En større revision af både designet og implementeringen af Perl-sproget, der bryder baglæns kompatibilitet med det, selvom kompatibilitetstilstand stadig skulle eksistere indtil 2010. [5]
Ligesom Perl-sproget efterlader Raku en masse frihed til programmører . Det lader dig stadig udtrykke dig selv kortfattet, herunder at skrive one-liners, men det forenkler også skrivning af store programmer takket være statisk skrivning og forbedret OOP -understøttelse .
Rakus tidligere navn var Perl 6. [6] I mange år har der været vittigheder i Perl-samfundet om udgivelsesdatoen. På spørgsmålet "hvornår Perl 6 udkommer" var det sædvanlige svar "i julen", men uden et år. [7] [8] I 2015, altså efter femten års venten, blev den såkaldte "jule"-version endelig offentliggjort. [9] [10] [11]
I Perl 6 besluttede vi, at det var bedre at rette sproget end at rette brugeren.Larry Wall [12]
Udviklingen af Perl 6 blev først annonceret af Larry Wall den 19. juli 2000, den fjerde dag af det års Perl-konference, [13] i hans State of the Onion -foredrag . [14] På det tidspunkt var prioriteterne: at fjerne de "historiske vorter" fra sproget; "enkle ting skal forblive simple, komplekse ting skal blive enklere, og umulige ting skal blive komplekse"; generel rengøring af indvendigt design og API . Processen startede med en række RFC'er . Denne proces var åben for alle deltagere, og intet aspekt af sproget blev lukket for ændringer. [femten]
Der blev modtaget 361 anmodninger, som alle blev gennemgået af Wall. Han begyndte derefter processen med at skrive flere "Apokalypser", et kristent udtryk, der betyder "at afsløre gode nyheder for gode mennesker." [16] Selvom det oprindelige mål var at skrive en Apocalypse for hvert kapitel i en:Programming Perl- bogen , blev det tydeligt, at da hver Apocalypse blev skrevet, blev tidligere Apocalypse tilsidesat af senere ændringer. Af denne grund blev der udgivet et sæt synopser, som hver refererer til en enkelt apokalypse, men inkluderer rettelser fra nye apokalypser. I dag er Raku-specifikationen drevet af "roast"-testsuiten, [17] mens synopses opbevares som historisk reference. [atten]
Der er også en serie af eksegese skrevet af Damian Conway , der forklarer indholdet af hver Apocalypse i form af praktisk brug. Hver eksegese består af kodeeksempler med en diskussion af deres brug og betydning. [19]
Hovedmålet, som Wall foreslog i sin oprindelige tale, var at fjerne "historiske vorter". Disse omfattede forvirring i sigilerne af arrays og hashes, tvetydighed i funktioner select, problemer med brugen af blottede [20] (uden tegnsætning [21] ) filbeskrivelser. Wall nævnte også mange andre problemer i sin tale, som Perl-programmører har diskuteret i årevis.
Konsekvensen af disse mål var tabet af bagudkompatibilitet. Da bagudkompatibilitet normalt er underforstået, når softwaren forbedres, skulle ændringerne i Perl 6, der bryder den, have været udtrykkeligt angivet. Efterhånden blev forskellen mellem Perl 5 og Perl 6 så stor, at Perl 6 blev omdøbt til Raku den 12. oktober 2019 . [6]
I årenes løb har udviklingsvektoren for Raku ændret sig flere gange. Introduktionen af koncepter fra Python og Ruby var en tidlig indflydelse. [22] [23] [24] Derudover er Pugs, den første Raku-tolk, skrevet på det funktionelle sprog Haskell , og mange elementer af funktionel programmering er blevet absorberet af Raku-udviklingsteamet. [25] [26]
Tungens maskot er insektet Camellia. [27] Dens navn er en henvisning til Perl-sprogets emblem, kamelen ("Kamelen"), og dens form, i traditionen fra det ordspil -elskende Perl-samfund, afspejler ordet " bug ". De spiralmønstre, der er indskrevet i dens sommerfuglelignende vinger, minder om "P6"-karaktererne, og det divergerende skelen er et bevidst ordspil på "Wall-eyed". [28]
Et af målene med det livlige og farverige logodesign var at modvirke kvindehad i samfundet og give folk med "maskuline overbevisninger" mulighed for at vise deres følsomme side. [29]
Rakudo er den mest udviklede implementering, [30] hvilket ikke gør det til den officielle version af sproget, som sproget er ikke defineret af implementeringen, men af testpakken. [31]
Rakudo giver dig mulighed for at udføre [32] kode i virtuelle MoarVM-, JVM- og Node.js - maskiner . [33] MoarVM er en virtuel maskine bygget specifikt til Rakudo og NQP-kompileren. [34] [35] NQP (Not Quite Perl 6 ) compileren implementerer en delmængde af sproget, der inkluderer Raku-regler for kildekodeparsing, abstrakt syntakstræmanipulation og backend-specifik kodegenerering . Meget af Rakudo er skrevet i Raku og NQP. Rakudo er ikke en selvstændig compiler, og der er ingen planer om at promovere compileren på nuværende tidspunkt.
Efter version "2015.02" droppede Rakudo understøttelsen af den virtuelle Parrot -maskine [36] (forgængeren til MoarVM), bygget på den fejlagtige antagelse, at Perl 6 ville ligne Perl 5. [37] [38]
Den første implementering af Raku var Pugs [39] , en fortolker og compiler skrevet i Haskell . Var den mest avancerede implementering, men der er kun lavet minimale rettelser siden 2007 for at holde trit med nye versioner af GHC , og fra november 2014 er Pugs ikke understøttet. [40] I august 2006 opdelte Yichun Zhang Pugs-testfilerne i fragmenter, vedhæftede de relevante Synapsis-afsnit til dem, [41] [42] og i januar 2008 blev disse test integreret i de officielle test af sproget (“roast) ”). [43] [44] I februar 2015 erklærede fællesskabet sprogtest for at være en specifikation. [45]
Raku og Perl er fundamentalt forskellige, selvom hensigten var at beholde Raku som Perl. De fleste af ændringerne har til formål at normalisere sproget, så det er lettere at forstå for både nybegyndere og erfarne programmører, og at gøre "enkle ting nemmere og komplekse ting mere mulige."
Den største ikke-tekniske forskel er, at Raku startede som en specifikation. [31] Dette betyder, at Raku kan genimplementeres, hvis det er nødvendigt, og også at programmører ikke behøver at læse kildekoden for at få fuld kontrol over nogen af dens funktioner. I tilfælde af Perl-sproget beskriver den officielle dokumentation kun den aktuelle tolks adfærd. Eventuelle uoverensstemmelser mellem dokumentationen og implementeringen kan resultere i, at enten det ene eller det andet bliver ændret, hvilket er drivkraften bag den løbende udvikling og forbedring af Perl-udgivelser.
I Raku er det dynamiske typesystem blevet suppleret med statiske typer . [46] For eksempel:
min Int $i = 0 ; min Rotte $r = 3.142 ; min Str $s = "Hej verden" ;Statiske typer forbliver dog valgfrie, så programmører kan gøre det meste uden eksplicit at angive typer.
min $i = "25" + 10 ; #$i er 35I Perl har subrutiner ingen formelle parametre , selvom simpel kontrol af antallet og typer af parametre er mulig ved hjælp af subrutineprototyper. [47] I stedet for er de faktiske parametre, der sendes ved reference, skjult bag array-elementerne @_i subrutinelegemet.
Reelle formelle parametre vises i Raku. [48] For eksempel:
sub do_something ( Str $thing , Int $other ) { ... }Ligesom i Perl videregives parametre i Raku ved reference, men som standard i Raku er de konstante , dvs. deres værdier kan ikke ændres. De kan udtrykkeligt erklæres for at tillade, at den oprindelige værdi ændres ( is rw) eller som kopier ( is copy), hvilket svarer til at passere med værdi.
Måder at videregive parametreDer er tre måder at videregive parametre i Raku: positional, named og slurpy .
Positionelle parametre er kun en ordnet liste, som i de fleste programmeringssprog. Selv de kan passeres i en vilkårlig rækkefølge, så længe deres navne er angivet. Parametre, der kun kan overføres ved navn, er angivet med et symbol :før sigilet for den formelle parameter. Squishing parametre er en måde at skabe variable funktioner i Raku. De er angivet med et symbol *før sigilet for den formelle parameter. Den slurpy-hash vil fange de navngivne parametre, der ikke er nævnt i subrutineerklæringen, og slurpy-arrayet vil fange de efterfølgende positionelle faktiske parametre.
I det følgende eksempel er alle tre metoder til stede, inklusive et slurpy array.
sub somefunction ( $a , $b , : $c , : $d , * @e ) { ... } en eller anden funktion ( 1 , 2 , : d ( 3 ), 4 , 5 , 6 ); # $a=1, $b=2, $d=3, @e=(4,5,6)Positionelle parametre er påkrævet som standard, medmindre parameternavnet efterfølges af et spørgsmålstegn. Navngivne standardparametre er på den anden side valgfrie, medmindre navnet efterfølges af et udråbstegn. Squishy-parametre er altid valgfrie.
Blokke og lukningerParametre kan også overføres til alle kodeblokke, der opfører sig som lukninger . Især for eksempel organerne af cyklusser forer whilelukninger. I det følgende eksempel tager løkken tre elementer fra listen ad gangen og sender dem til blokken som variablerne $a, $bog $c. [49]
for @list -> $a , $b , $c { ... }Dette kaldes "pointy sub" eller "pointy block", og pilen i den opfører sig lidt som et nøgleord sub, der introducerer en anonym lukning (eller en anonym subrutine i Perl-terminologi). [48]
I Perl ændres sigils (tegnsætningstegn, der vises før variabelnavne) afhængigt af, hvordan variablen bruges .
# Perl-kode mit @ array = ('a', 'b', 'c'); mit $element = $ array[1]; # returnerer 'b', mit @ekstrakt = @array [ 1, 2]; # returnerer ('b', 'c') mit $element = @array [1]; # returnerer 'b' med advarsel (siden 5.10)I Raku er sigiler invariante: både et array og et array-element vil have det samme sigil. [46]
# Raku kode mit @ array = 'a', 'b', 'c'; mit $element = @array [1]; # $element er skrevet 'b' mit @ekstrakt = @array [ 1]; # @extract er skrevet ('b') mit @ekstrakt = @array [ 1, 2]; # @extract er skrevet ('b', 'c')Variabiliteten af sigils i Perl er inspireret af talkonventionen på engelsk og mange andre naturlige sprog .
" Det er et æble." #$a er sandt " Disse æbler." # @en sand " Dette er det tredje æble." # $a[3] er sandt " Dette er det tredje æble." # @a[3] er ikke korrektDette koncept brydes dog, når referencer kommer i spil, da de kan referere til datastrukturer, mens de er skalarer. Arbejde med indlejrede datastrukturer kan således kræve, at både ental og flertal udtrykkes i samme term:
# Perl-kode: Hentning af et array fra et hash-element. # Denne hash gemmer hashes, der indeholder arrays. mine @trans_verbs = @ { $ordbog { 'verbum' }{ 'transitive' } };Sådanne konstruktioner har ingen analoger i almindelige naturlige sprog, hvilket forårsager en høj kognitiv belastning ved skrivning af kode. Den samme Raku-kode:
# Raku-kode: Henter et array fra et hash-element. # Denne hash gemmer hashes, der indeholder arrays. mine @trans_verbs = %ordbog<verb><transitive><> ;I Perl-sproget understøttes objektorienteret programmering gennem en funktion, der gør enhver variabel til et objekt af en bestemt klasse, hvorfra de metoder , der er erklæret i klassen, blessbliver tilgængelige til at kalde . [halvtreds]
Selvom den er ekstremt kraftfuld, gør denne mekanisme det på samme tid svært at beskrive selv den mest basale OOP - simple strukturlignende objekter med tilhørende procedurer. Fordi Perl ikke gør nogen antagelser om objektmodellen, kan metodekald ikke optimeres af compileren.
Raku bevarer metoden på lavt niveau bless, men giver også en mere restriktiv objektmodel til almindelige brugstilfælde. [51] [52] For eksempel kan en klasse, der indkapsler et punkt i et kartesisk koordinatsystem, defineres som følger:
klasse Punkt er rw { har $.x ; har $.y ; metodeafstand ( Punkt $p ) { sqrt ( ( $!x - $p . x ) ** 2 + ( $!y - $p . y ) ** 2 ) } metode distance-to-center { selv . afstand: Punkt . ny ( x => 0 , y => 0 ) } } mit $point = Punkt . ny ( x => 1,2 , y => - 3,7 ); sige "Punktposition: (" , $punkt . x , ', ' , $punkt . y , ')' ; # Punktposition: (1,2, -3,7) # Skift x og y (ved at bruge "x" og "y" metoderne): $point . x = 3 ; $point . y = 4 ; sige "Punktposition: (" , $punkt . x , ', ' , $punkt . y , ')' ; # Punktposition: (3, 4) mit $andet-punkt = Punkt . ny ( x => -5 , y => 10 ); $point . afstand ( $andet-punkt ); #=> 10 $point . afstand til centrum ; #=> 5I Perl påkaldes metoder med en pil: $object->method(). Raku bruger en prik i stedet for en pil ligesom mange andre sprog (såsom Java og Python).
I Raku-terminologien $.xkaldes det en attribut. Metoden der bruges til at få adgang til en attribut kaldes en accessor [53] (fra engelsk access - access). Den oprettes automatisk (når en attribut er erklæret med en prik [54] ) og hedder det samme som attributten. Det fungerer som en getter , og når en klasse eller attribut is rwovertager egenskaberne fra en setter og kan bruges i venstre side af en opgave. I stedet for automatiske accessorer kan programmøren definere sine egne brugerdefinerede metoder. Også i klassens krop kan alle attributter, uanset hvordan de er deklareret, tilgås direkte ved hjælp af $!.
Arv, roller og klasserArv er en teknik, hvor objekter eller typer genbruger logik eller definitioner fra andre objekter eller typer. For eksempel kan en programmør lave en standardtype med en valgfri attribut. I sprog som Java leveres arv af klasser, som kan være underklasser af andre eksisterende klasser.
Raku giver også arv gennem klasser, svarende til klasser i andre programmeringssprog, såvel som gennem roller.
Roller i Raku overtager funktionen af grænseflader i Java, mixins i Ruby, træk [55] i PHP og Squeak (en dialekt af Smalltalk-sproget ). De ligner klasser, men giver en sikrere sammensætningsmekanisme end nedarvning, der forhindrer attribut- og metodenavnekonflikter. [56] [57] Roller er ikke indbygget i en arvekæde. Roller refererer til det nominelle typesystem (se en:Nominelt typesystem ), ikke det strukturelle typesystem, som f.eks. bruges i Go . De giver semantiske navne for sæt af adfærd og tilstande. Den grundlæggende forskel mellem roller og klasser er, at roller ikke instansierer objekter. [58]
Selvom roller er forskellige fra klasser, er det muligt at skrive kode, der skaber et objekt ud fra en rolle. Forsøg på at bruge en rolle til at oprette et objekt vil resultere i oprettelsen af en klasse med samme navn. Raku-dokumentationen kalder denne mekanisme automatisk rollespilning. den genererede klasse er et ordspil. [59]
I bund og grund er roller bundter af attributter og potentielt abstrakte metoder, der kan føjes til en klasse uden at bruge arv. En rolle kan endda tilføjes til et enkelt objekt. I sidstnævnte tilfælde vil Raku oprette en anonym underklasse, tilføje en rolle til den og erstatte objektets klasse med den anonyme underklasse.
For eksempel er en hund et pattedyr , fordi hunde arver visse egenskaber fra pattedyr, såsom mælkekirtler og, gennem deres hvirveldyrs forfædre , rygsøjlen . På den anden side kan hunde have forskellige former for adfærd, som kan ændre sig over tid. For eksempel kan en hund være tam, omstrejfende, være en guide . Disse sæt af yderligere adfærd kan føjes til hunden. Du kan beskrive dem på en sådan måde, at du kan anvende dem på andre dyr. For eksempel kan en kat være tam og herreløs. Hunden og katten er adskilt fra hinanden, men forbliver i den generelle kategori af pattedyr. Så Млекопитающее er en klasse, Собакаog Кошка er klasser arvet fra et pattedyr. Men ovenstående adfærd er roller, der kan tilføjes til klasser eller objekter, der er oprettet fra klasser.
klasse Pattedyr er hvirveldyr { ... } klasse Hund er pattedyr { ... } rolle Pet { ... } rolle hjemløs { ... } rolleguide { _ ... }Roller tilføjes til klasser og objekter ved hjælp af does. Til arv bruges søgeordet is. Disse ord afspejler en forskel i betydningen af disse sprogtræk: at tilknytte en rolle giver en klasse en rolles adfærd , men betyder ikke, at klassen bliver bogstaveligt talt den samme som den rolle.
klasse førerhund er førerhund gør førerhund { ... } # Underklasse tillægger en rolle. min $hund = Hund . ny (); $dog gør førerhund ; # Objektet tillægger rollen.Både roller og klasser er typer. En rolle kan bruges i en variabeldeklaration. En rolle Незрячийkan f.eks. indeholde en attribut af typen Поводырь, som kunne være en førerhund, en førerhest, en førerperson eller endda en førervogn.
klasse Menneske { har Hund $hund ; # Kan indeholde enhver form for hund - ... # det er lige meget om det er en førerhund eller ej. } rolle Blind { har guide $guide ; # Kan indeholde ethvert objekt med rollen som ... # Guide - uanset om det er en hund eller ej. }Regulære udtryk og strengmanipulation har altid været en af Perls definerende egenskaber. [60] Fordi Perls mønstre overgik regulære udtryk på et tidspunkt, [61] refererer Raku-dokumentationen simpelthen til dem som regexes , og tager afstand fra den formelle definition af regulære udtryk.
Raku udvider Perls funktionssæt omkring regulære udtryk ved at indlejre dem i en større ramme til at bygge parsere kaldet regler . [62] Regler giver kontekstfølsomme parsing-funktioner (såsom det syntaktiske prædikat fra PEG og ANTLR ) og opfører sig som lukninger om deres leksikale omfang . [63] Regler indtastes ved hjælp af nøgleordet rule, som i brug svarer til at definere en underrutine. regexAnonyme regler kan indtastes ved hjælp af (eller ) nøgleordet rx, eller de kan beskrives som regulære udtryk i Perl ved hjælp af m(match) eller s(erstat) operatorerne.
I Apocalypse 5 lister Larry Wall 20 problemer med den nuværende "regex-kultur". Blandt andet var Perl regulære udtryk "for kompakte og 'søde'", de "stolede for meget på for få specialtegn", de havde "dårlig navngivne capture support", "svag grammatikunderstøttelse" og "dårlig sprogintegration" . ". [64]
Nogle Perl-konstruktioner i Raku er blevet ændret og optimeret til andre syntaktiske udtryk. For eksempel er parenteser, som var påkrævet i udførelsesordreerklæringer , nu valgfrie. [49]
if is-true () { for @array { ... } }Operatoren ,(komma) er nu en listekonstruktør, så parenteser omkring lister er ikke påkrævet.
@array = 1 , 2 , 3 , 4 ;Raku tillader følgende udtryk:
hvis 20 <= $temperatur <= 25 { sig "Temperaturen i rummet er mellem 20 og 25 grader!" }Dette opfattes som sekventielle sammenligninger fra venstre mod højre, efterfulgt af en forening gennem et logisk OG .
Raku bruger en doven liste-evalueringsteknik, der ligner nogle funktionelle sprog, såsom Haskell : [65]
@heltal = 0 .. inf ; # heltal fra nul til uendeligDenne kode vil ikke give en fejl ved at forsøge at sætte en uendelig liste ind i et array @integers, og den vil ikke hænge ved at prøve at vokse listen i det uendelige, hvis der anmodes om et endeligt antal elementer.
Dette forenkler mange almindelige opgaver i Raku, herunder I/O-operationer, listetransformationer og parameteroverførsel.
Det er også muligt at lave dovne lister ved at bruge søgeordene gatherog take. De ligner generatorerne i Icon og Python .
mine $kvadrater = doven samle for 0 .. Inf { take $_ * $_ ; };Her $squareser en uendelig liste over kvadrater af naturlige tal (inklusive nul), men på grund af denne listes dovne karakter bliver elementerne kun evalueret, når de tilgås. [66]
Raku introducerer begrebet junctions [67] ( eng. junction - forbindelse, skæring; i Raku er dette udtryk også relateret til konjunktion og disjunktion [65] ). Det er en superposition af flere værdier. [65] I sin enkleste form skabes et kryds af krydsoperatorerne :
# Et eksempel på typekrydsning | ("enhver"): min $farve = 'hvid' ; medmindre $color eq 'white' | 'sort' | 'gray' { die "Udskrivning i denne farve understøttes ikke.\n" ; } # Et eksempel på et kryds som & ("alle"): mit $password = 'hemmeligt!123' ; if $password ~~ /<:alpha>/ & / <:digit> / & / <:punct> / { sig "Dit kodeord er stærkt nok." ; }Operatoren |udtrykker en værdi, der er lig med enten venstre eller højre argument, operatoren & - både venstre og højre. Disse værdier kan bruges i kode, hvor en værdi formodes at være semantisk. Enhver operation med krydsning virker samtidigt på alle dens komponenter, og resultatet kombineres gennem operatøren af denne overgang. Ja, den ("apple"|"banana") ~ "s"vender tilbage "apples"|"bananas". Men i en boolesk kontekst returnerer kryds kun én værdi, sand eller falsk: anyden returnerer sand, hvis sammenligningen er sand for mindst ét element; allreturnerer sand, hvis sammenligningen er sand for alle elementer. [68]
Ved at bruge crossovers er det muligt at udvide typesystemet med en form for generisk programmering , der begrænser variabler til typekrydsninger.
undersæt Farve af Enhver , hvor RGB_Color | CMYK_Farve ; sub get_tint ( Farve $farve , Num $opacitet ) { ... }Crossovers er specielle objekter, der opdeler kodeudførelse i potentielt parallelle tråde . Og de er designet specifikt til brug i en boolesk kontekst: Du kan ikke få direkte adgang til deres indhold uden at konvertere dem til en streng, som adskiller dem for eksempel fra sæt og andre samlinger. [68]
På sprog på lavt niveau er makroer blevet synonyme med teksterstatning i kildekoden på grund af tilknytninger til C-forprocessoren . Men i sprog på højt niveau som Lisp , der gik forud for C , var makroer mere kraftfulde. [69] Det var dette Lisp-lignende koncept af makroer, som Raku benyttede sig af. [48] Kraften ved denne type makro er baseret på at betjene programmet som en datastruktur på højt niveau frem for tekst, og på adgang til alle sprogets funktioner.
En makrodefinition i Raku ligner en subrutine eller metodedefinition. Og sådan en makro kan fungere med både kildekode og et abstrakt syntakstræ og en kombination af disse to ting.
makro hej ( $hvad ) { kvasi { sig "Hej { {{{$hvad}}} }" }; }I eksemplet ovenfor analyseres makroargumentet, før makroen udføres, hvilket fører til mere informative kompilatordiagnosemeddelelser. Men da udførelsen af makrokroppen sker på kompileringstidspunktet (for hvert brugstilfælde), kan en lang række optimeringsteknikker anvendes . Ved hjælp af makroer er det endda muligt at udføre det meste af arbejdet i nogle programmer, før de begynder at udføre .
I Raku kan identifikatorer også indeholde apostrof og bindestreger ud over bogstaver, tal og understregninger, så længe de efterfølges af bogstaver. Bogstaver inkluderer "tilsvarende" (som er implementeringsafhængig) Unicode-tegn , som er defineret i Rakudo og MoarVM som alle Unicode-tegn i "L"-kategorien. [70]
Brugen af bindestreger i stedet for understregninger kaldes " kebabsagen ". [71] [72] [73]
Meta-operatorer er operatorer, der kan parametreres af andre operatorer, ligesom funktioner kan tage andre funktioner som parametre. [74]
OpgavemetaoperatorPerl har arvet C-sprogoperatorer som +=, *=og så videre. Raku generaliserer dem til en metaoperator. For enhver binær operator kan opvi skrive:
$x op = $y ; # eller $x [op]= $yHvad betyder:
$x = $x op $y ;Desuden fungerer dette også for brugerdefinerede operatører.
HyperoperatorerDe ligner operatøren mapi Perl. Tving operatører til at operere på alle matrixværdier. Kan anvendes på både binære og unære operatorer. [75]
For eksempel vil følgende kode oprette en matrix, der indeholder alle elementerne i matrixen @aforøget med én:
min @aPlusOne = @a "+" 1 ; # eller @a >>+>> 1Retningen af vinkelparenteserne påvirker adfærden, når arrays af forskellig længde sendes som parametre. [75] Disse "pile" viser, hvor længden af resultatet af operationen kommer fra.
Et eksempel på brug af en hyperoperator med en unær operator:
min @a = 1 , 2 , - 3 ; min @b = -<< @a ; # [-1 -2 3]Hyperoperatorer fungerer ikke kun for flade arrays, men også for indlejrede arrays. [76]
Reduktion meta-operatorReduktions-meta-operatoren kan bruges med enhver infix- operator, der konverterer den til en listereduktionsoperator . Det er, som om operatoren blev anvendt på de første to elementer, derefter på den resulterende værdi og det tredje element, og så videre, indtil der kun er én værdi tilbage. Summen, produktet, maksimum, minimum osv. kan fungere som en operator-parameter. Dette er en ekstremt kraftfuld mekanisme, der for eksempel oversætter operatoren +til en listesumoperator, som i eksemplet nedenfor.
sige "Summen af heltal fra 0 til 99 er: " , [+] ^ 100 ; KrydsoperatorDen opfører sig både som en operatør og som en meta-operatør. [77]
Krydsoperatoren [75] finder det direkte produkt af lister ordnet på en sådan måde, at opregning af elementer fra højre operand er hurtigere end fra venstre operand, [77] returnerer en sekvens af lister:
1 .. 3 X <ab c> X <de f> ; # ((1 ad) (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))Metaoperatoren kollapser interne lister ved hjælp af parameteroperatoren: [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) Zip-operatørFra engelsk. lynlås - lynlås . [78]
Ligesom krydsoperatoren kombinerer elementer af lister, [75] , men returnerer en sekvens, der først indeholder de første elementer af hver liste, derefter de andre elementer af hver liste, og så videre. [79]
<ab c> Z <1 2 3 4> ; # ((a 1) (b 2) (c 3)) 100 , 200 Z + 42 , 23 ; # (142 223) Inverse operatorerMeta-operatoren R( eng. reversed ) giver dig mulighed for at bytte argumenterne fra den oprindelige operator.
sig "En divideret med tre er lig med" , 3 R / 1 ; Indlejring af meta-operatorerResultatet af at anvende en meta-operator til en operator er en anden operator, som meta-operatoren kan anvendes til igen, og så videre. For at tvetydige syntaksen er firkantede parenteser tilladt. [80]
min @a = 1 , 2 , 3 ; min @b = 5 , 6 , 7 ; @a >>>>> @b ; # Parse fejl. @a >>[>]>> @b ; # [False False False] # Her anvendes hyperoperatoren >> >> på sammenligningsoperatoren. # Cross-meta-operatoren gælder # for meta-tildelingsoperatoren # parametreret af additionsoperatoren: @a X [+=] @b ; # (6 12 19 7 13 20 8 14 21) # På grund af cross-meta-operatoren blev tildelingen udført # for hvert element i array @a med hvert element i array @b, # hvilket svarer til at tilføje til hvert element i array @a # summen af elementerne i array @b: sig [ +] @b ; #18 sig @a ; # [19 20 21]Ligesom andre moderne sprog er Raku designet til at understøtte samtidighed og asynkron programmering.
Raku leverer en enkel, modulær API på højt niveau til at skrive samtidig kode, uafhængigt af hvordan den virtuelle maskine implementerer denne API. Derudover kan nogle sprogfunktioner implicit fungere asynkront. For at sikre håndterbarhed og kompatibilitet mellem disse funktioner, bør brugerkode så vidt muligt undgå brugen af grænseflader på lavt niveau ( tråde , skemalæggere, låse ). [81]
Løfter [82] [83] er den centrale mekanisme på højt niveau , som er resultaterne af beregninger opnået før deres faktiske afslutning. De kan gives, udføres og krænkes. De har således tre mulige tilstande. Styrken ved denne mekanisme ligger i evnen til at kombinere dem og forbinde dem i kæder:
min $p1 = Løfte . ny (); min $p2 = $p1 . derefter ({ sig "Resultat af andet løfte." });Her thensikrer den $p2kun udførelse efter udførelse af $p1.
Der er også engelsk. Forsyninger ("lagre") og eng. Leverandører ("leverandører") - en mekanisme til at skabe asynkrone datastrømme med evnen til at behandle hver besked af flere modtagere på én gang, svarende til hvordan hændelseshandlere fungerer i andre programmeringssprog. [81] Denne mekanisme kan bruges til hændelsesdrevet programmering .
Endelig er kanaler ( Engelske kanaler ) trådsikre FIFO - køer , der ligner navngivne pipelines i operativsystemer, men fungerer inden for den nuværende proces. Den vigtigste forskel fra Supplyer, at en læsning fra en pipe er en dequeue, [81] dvs. én værdi kan kun læses én gang.
Program "Hej verden!" bruges ofte til at demonstrere et sprogs grundlæggende syntaks. I Raku ser det sådan ud:
sig 'Hej verden' ;Selvom der selvfølgelig er mere end én måde at udtrykke det på. [84]
Faktoriel beregning , defineret på flere måder:
# Brug af rekursion med en "hvis-else"-konstruktion. sub fact ( UInt $n --> UInt ) { if $n == 0 { 1 } else { $n * fact ( $n-1 ) } } # Brug af rekursion med "hvis" # som en udtryksmodifikator. sub fact ( UInt $n --> UInt ) { return 1 if $n == 0 ; returnere $n * faktum ( $n-1 ); } # Brug af rekursion med "when"-konstruktionen. sub fact ( UInt $n --> UInt ) { when $n == 0 { 1 } default { $n * fact ( $n-1 ) } } # Brug af den ternære operator. underfakta ( UInt $n --> UInt ) { $n == 0 ?? 1 !! $n * faktum ( $n-1 ) } # Brug af flere forsendelser. multi fact ( 0 ) { 1 } multi fact ( UInt $n --> UInt ) { $n * fact ( $n - 1 ) } # Brug af reduktions-meta-operatoren. underfakta ( UInt $n --> UInt ) { [*] 1 .. $n } # Definition af den faktorielle operator, # implementeret via reduktions-meta-operatoren. sub postfix: <!>( UInt $n --> UInt ) { [*] 1 .. $n } # Brug af nøgleordet "state" til huskeseddel. sub fact ( UInt $n --> UInt ) { state %known = 0 => 1 ; returner %kendt { $n } hvis %kendt { $n }: eksisterer ; %kendt { $n } = $n * faktum ( $n-1 ); returner %kendt { $n }; }QuickSort er en velkendt sorteringsalgoritme. Dens implementering ved hjælp af det funktionelle paradigme kan kortfattet skrives [a] sådan:
# En sorteret tom liste er en tom liste. multi quicksort ([]) { () } # Ellers, tag det første element som pivot... multi quicksort ([ $pivot , * @rest ]) { # Opdel elementerne i en liste over dem # mindre end pivoten og dem # større end pivoten. min @ før = @rest . grep (* før $pivot ); min @efter = @hvile . grep (* efter $pivot ); # Sorter disse underlister og sammensæt resultatet. flad ( quicksort ( @before ), $pivot , quicksort ( @after )) }Dette puslespil bruges ofte til at introducere rekursion i datalogi . Denne implementering bruger multimetoder med en bogstavelig 0 som en del af .
multi sub hanoi ( 0 , $, $, $) { } # Ingen diske. Der er ikke noget at overføre. multi sub hanoi ( $n , $a = 'A' , $b = 'B' , $c = 'C' ) { # $n diske og tre stænger: A, B, C. hanoi $n - 1 , $ a , $c , $b ; # Flyt ($n - 1) drev fra A til B siger "Flyt drev $n fra $a til $c." ; # Flyt den sidste disk fra A til C. hanoi $n - 1 , $b , $a , $c ; # Flyt ($n - 1) diske fra B til C. } hanoi ( 5 ); # Løsning til fem diske.Perl | |
---|---|
Mennesker |
|
Ting | |
Rammer |
|
|