=begin _ This is a multi-line comment Hello Goodbye =end _ say "hello"; say "World!"; say "13 " x 3; my $sum = [+] 1..5; #prints 15 'hello world'.say; say 'John Doe'.uc; #upper cases say "John Doe".chars; # char cnt say 'John Doe'.flip; #reverses order of chars say 17.is-prime; #you guessed it... #apparently '%%' returns true or false for divisibility...nice #and 'div' gives the result of integer division say #`(This is an embedded comment) ""; #"~~" does the a smart match (I think this is regex) #"~" does concatenation my $string = "Hello my name is Alex, please grab my name: "; say $string ~ ($string ~~ /Alex/); my $bool = "This statement exists: "; say $bool~ ?$bool~"\n"; my $greetNum = "S'up, number "; say $greetNum~$_ for 0 .. 4; say ""; my @animals = 'camel','vicuña','llama'; say "The zoo contains " ~ @animals.elems ~ " animals"; say "The animals are: " ~ @animals; say "I will adopt an owl for the zoo"; @animals.push("owl"); say "Now my zoo has: " ~ @animals; say "The first animal we adopted was the " ~ @animals[0]; @animals.pop; say "Unfortunately the owl got away and we're left with: " ~ @animals; say "We're closing the zoo and keeping one animal only"; say "We're going to let go: " ~ @animals.splice(1,2) ~ " and keep the " ~ @animals~"\n"; =begin arraycmt something worth noting about arrays in Perl6 is that you can specify an array of fixed size. If you don't it can be given values at any location =end arraycmt my @arrTest[3]; #will yell at you if you try to reference 'arrTest[3]' #this is a multidimensional array, #where first dimension has a max of 3 values #and the second has a max of 2 vals my @tbl[3;2]; @tbl[0;0] = 1; @tbl[0;1] = "x"; @tbl[1;0] = 2; @tbl[1;1] = "y"; @tbl[2;0] = 3; @tbl[2;1] = "z"; say @tbl; say ""; =begin Hashes Hashes are Key/Value pairs, similar to Dictionaries in C#. The key (Ha) features of Hashes are that their lookup time is flat, but I don't think the order is maintained =end Hashes my %capitals = (UK => 'London', Germany => 'Berlin'); #Can also be done as "my %capitals = ('UK', 'London', 'Germany', 'Berlin');" %capitals.push: (France => 'Paris'); say %capitals.kv; #prints (Key Value ...) say %capitals.keys;#prints (Key ...) say %capitals.values; #prints (Value ...) say "The capital of France is: " ~ %capitals; say ""; =begin Typing Perl6 is a gradually typed language, meaning it allows both static and dynamic typing. Below is an example of static =end Typing #saying $var.WHAT reveals the type of a variable #but you can in fact force a variable to take a type... my Int $num = 123; say '$num is a '~$num.WHAT~'type'; $num = Nil; say '$num is now a '~$num~'type'; say ""; #also worth noting is Arrays and Hashes #can also be statically typed my Str @multilingual = "Hello","Salut","Hallo","您好","안녕하세요","こんにちは"; say @multilingual; say @multilingual.WHAT; my Int %country-codes = (UK => 44, Germany => 49); say %country-codes; say %country-codes.WHAT; say ""; =begin Binding1 Assignments vs. Bindings is like comparing C-style initialized variables with C-style constants. The key difference is that variables Can also be bound to other variables A thing to note is this is bidirectional =end Binding1 my $const := 123; say $const; #$var = 999; #this throws an error say ""; =begin Binding2 The key difference is that variables Can also be bound to other variables A thing to note is this is bidirectional =end Binding2 my $a; my $b; $b := $a; $a = 7; say $b; $b = 8; say $a; say ""; =begin FxnsVMutators Functions do not change the state of the object they were called on. Mutators modify the state of the object =end FxnsVMutators my @numbers = [7,2,4,9,11,3]; @numbers.push(99); #This is a mutator say '@numbers var contains '~@numbers; say 'result of sorting @numbers: '~@numbers.sort; #This is a function, say '@numbers var not having been sorted: '~@numbers;#and returns a set of sorted numbers #but not the actual array (note the "()") @numbers.=sort;#".=" enforces a fxn as a mutator say '@numbers having been sorted via enforced mutator: '~@numbers; say ""; =begin Conditionals A major difference between Perl 5 and 6 is that Perl 6 actually doesn't like parentheses around 'if' statements. It also forces the programmer to use {} to encapsulate the resultant action =end Conditionals my $age = 19; if $age > 18 { say 'Welcome' } #statements and conditions can still be inverted say 'Welcome' if $age > 18; #can do traditional if, elsif, else my $number-of-seats = 9; if $number-of-seats <= 5 { say 'I am a sedan' } elsif $number-of-seats <= 7 { say 'I am a 7 seater' } else { say 'I am a van' } say ""; my $clean-shoes = False; if not $clean-shoes { # or "!" say 'Clean your shoes' } #can also be written as: unless $clean-shoes { say 'Clean your shoes' } #"with" can check if a variable is defined, #instead of checking if $var is Nil my $variable; with $variable { say "Shouldn't happen" } say ""; #you can also use "orwith" in the same pattern #as "if" and "elsif" #for loops are pretty special. they can take #an iteration variable or you can use the "$_" #in simple cases my @array = [1,2,3]; for @array -> $item { say $item * 100 } for @array { say $_ * 100 } #you can even reduce basic statements to one-liners... say "Hi, $_" for @array; say ""; =begin givenBlocks "given" is like C's "switch-case block", except WAY more flexible. I believe C-style blocks only allows one value at a time, while Perl 6 allows broader options =end givenBlocks my $var = 42; given $var { when 0..50 { say 'Less than or equal to 50'} when Int { say "is an Int" } when 42 { say 42 } default { say "huh?" } } say ""; #using "proceed" is like not using a "break" #in a switch-case, it will continue to check #the other conditions $var = 42; given $var { when 0..50 { say 'Less than or equal to 50';proceed } when Int { say "is an Int";proceed } when 42 { say 42 } default { say "huh?" } } say ""; #"loop" allows for the classic C-style loop loop (my $i = 0; $i < 5; $i++) { say "The current number is $i" } =begin IO Now let's get on to I/O stuff! Fast I/O manipulation is arguably what made the Perl family so popular in the first place, and it's a broad topic =end IO #Let's start with what we've been using to print to #the console this whole time: "say" say 'Hello World!\n'; #Note the quotes: single means literal say "Hello World!\n"; #...while double mean interpolated #another way to write to the console... print "'print' doesn't automatically add a \\n char\n"; print "You have to add it yourself\n"; #use "get" to retrieve data from the command line my $name; say "Hi, what's your name?"; $name = get; say "Dear $name welcome to Perl 6"; #"prompt" is a combo between "say" and "get" my $food = prompt "What's your favorite food? "; say "Let's eat $food tonight!\n"; =begin ShellCommands Another cool feature is doing shell commands from within Perl! 'run' executes a command without involving a shell while 'shell' runs a command through a shell system, and is platform dependent =end ShellCommands $name = "Neo"; run 'echo', "$name executed this via the shell 'echo' command!"; shell "ls"; =begin FileIO The backbone of Perl's popularity springs from its ease of file reading and writing =end FileIO #To pull an entire text file into memory: my $data = slurp "datafile.txt"; say "Here's the slurped data:"; say "$data"; #...but this is normally not practical for large files #so, to read line-by-line, we do this: say "Now we will do the same line-by-line:"; for 'datafile.txt'.IO.lines -> $line { say $line; } =begin Alt another way to do this is: my $fh = open "datafile.txt", :r; for $fh.lines { say $_; } =end Alt #the simple way to write to a file is "spurt"... my $newdata = "New scores: Paul 10 Paulie 9 Paulo 11"; #spurt will create the file if it doesn't exist spurt 'newdatafile.txt', $newdata; #to list all files/folders in current directory: say "current directory contents: "~dir; #to do this for a specified one: my $dir = dir "/home/alex/Documents"; say "Contents of Documents folder: $dir"; #you can even alter directories straight from Perl6! mkdir "newfolder"; rmdir "newfolder"; #Note this will return an error if #not empty #you can check if something exists: my $ck = 'script123.pl6'.IO.e; say "Does script123.pl6 exist: $ck"; #you can also check if it's a file or directory: $ck = 'script123.pl6'.IO.f; say "Is script123.pl6 a file: $ck"; $ck = 'script123.pl6'.IO.d; say "Is script123.pl6 a directory: $ck"; $ck = 'folder123'.IO.d; say "Is folder123 a directory: $ck\n"; =begin Functions #Alright, enough with the baby stuff; #let's move on to subroutines, or what #ot my @final-array-v2 <== reverse() <== sort() <== unique() <== @array; say @final-array-v2;her languages call functions, methods, etc. =end Functions sub AlienGreeting { say "Hello earthlings"; } AlienGreeting; #notice in Perl6 you don't need to use () # if it doens't take any inputs =begin Signatures_1 unlike Perl 5, the preferred way to identify arguments in Perl 6 is through a signature. Since Perl 6 is gradually typed, you can choose whether to specify the type of each argument in the signature as well. =end Signatures_1 sub say-hello (Str $name) { say "Hello "~$name~"!!!!" } say-hello "Paul"; say ""; =begin Signatures_2 Like in C-style languages, different signatures allow for subroutines the same names. To allow this one must use the 'multi' keyword in place of 'sub' =end Signatures_2 multi greet($name) { say "Good morning $name" } multi greet($name, $title) { say "Good morning $title $name"; } greet "Johnnie"; greet "Kietra", "Ms."; say ""; =begin DefAndOptPars Perl 6 allows both f if $var == or optional and default parameters. Personally I find these features to be incredibly attractive in a language, because they prevent the need for multiple versions of the same subroutine in some cases, and make arg handling logic really simple =end DefAndOptPars { #an optional param example: sub SayHello($name?) { with $name { say "Hello " ~ $name } else { say "Hello Human" } } SayHello; SayHello("Laura"); say ""; } { #a param default example: sub SayHello($name="Alex") { say "Hello $name"; } SayHello; SayHello("Kietra"); #notice that () aren't explictly needed, regardless of #the number of arguments say ""; } =begin ReturnVals #return values in Perl 6 can be either explicit #or implicit. (implicit only happens if sub is #allowed to run to the end of its block) =end ReturnVals #implicit example: sub squaredEx($x) { $x ** 2; } say "7 squared is equal to " ~ squaredEx(7); #explicit example: sub squaredImp($x) { return $x ** 2; } say ""; #return types can also be static #using traits: sub factorial(Int $x) returns Int { my Int $out = 1; $out *= $_ for ((1..$x).reverse); return $out; } say "The factorial of 4 is " ~ factorial(4); #using the arrow: sub cubed($x --> Int) { return $x ** 3; } say "5 cubed is "~cubed(5); #We can even control the definedness of return values #if we want an Int to be strictly defined then we use #'Int:D', and 'Int:U' if undefined =begin FxnlPrgming Perl has always been an incredibly flexible language in that it allows for both object oriented and functional styles of programming. Here are some examples and cool features of the latter. =end FxnlPrgming =begin FirstClass Subroutines are first-class citizens in Perl 6, in that they can be passed as arguments, they can be returned from other subroutines, and they can be assigned to variables =end FirstClass #the 'map' function is a "higher order function", #it can accept another function as an argument { my @array = <1 2 3 4 5>; sub squared($x) { $x ** 2 } say "Using map with a function: " ~ map(&squared, @array); #output: (1 4 9 16 25) } #we can also make anonymous functions/lambdas in Perl 6 #or functions with no names #rewriting the 'map' example: { my @array = <1 2 3 4 5>; say "Using map with a lambda function: " ~ map(-> $x {$x ** 2}, @array); } #this is called a "pointy block", and can also be #used to assign subroutines to variables { my $squared = -> $x { $x ** 2 } say "nine squared is " ~ $squared(9); } #you can also chain functions in Perl 6, so #instead of doing this: { my @array = <7 8 9 0 1 2 4 3 5 6 7 8 9>; my @final-array = reverse(sort(unique(@array))); say @final-array; } #which is awkward to read, you can do this: { my @array = <7 8 9 0 1 2 4 3 5 6 7 8 9>; my @final-array = @array.unique.sort.reverse; say @final-array; } #another example of this is the feed operator: { my @array = <7 8 9 0 1 2 4 3 5 6 7 8 9>; @array ==> unique() ==> sort() ==> reverse() ==> my @final-array; say @final-array; } #this can also be done in reverse, if you prefer a #more traditional comprehension scheme: { my @array = <7 8 9 0 1 2 4 3 5 6 7 8 9>; my @final-array-v2 <== reverse() <== sort() <== unique() <== @array; say @final-array-v2; } #Perl6 has a Hyper operator, which allows one to #call a method on all elements of a list, and return #a list of the results. { my @array = <0 1 2 3 4 5 6 7 8 9 10>; sub is-even($var) { $var %% 2 }; say '@array vals, identifying if prime: ' ~ @array>>.is-prime; say '@array vals, identifying if even: ' ~ @array>>.&is-even; #note the '&' for a non-built-in subroutine } #NOTE: Perl 6 guarantees that the order of the results is #the same as that of the original list. However, there #is no guarantee that Perl 6 will actually call the #methods in list order or in the same thread. So, be #careful with methods that have side-effects, such as #'say' or 'print'. #A junction is a logical superposition of values #'1|2|3' is a junction, that means "any of these values" { my $var = 2; if $var == 1|2|3 { say "The variable is 1 or 2 or 3" } #$a&$b means "all of these values" say "The variable is divisible by 1 and 2" if $var %% 1&2; } =begin LazyLists Perl6 has a feature that is incredibly efficient called "lazy lists", which are lists that are not evaluated until it is required, and avoids repeating evaluations by storing results in a lookup table. This allows for potentially infinite data structures without the cost. the operator is '...', has an initial value, generator value, and endpoint value. =end LazyLists { #from 1 to 10 my $lazyList = (1 ... 10); say $lazyList; #from 1 to INFINITY $lazyList = (1 ... Inf); say $lazyList; #from 0 to 10, in increments of 2. Note this isn't #using a generator, but the interpretor was able to #infer the incrementation pattern based on the first #two values $lazyList = (0, 2... 10); say $lazyList; #THIS example uses a generator: $lazyList = (0, {$_ + 3} ... 12); say $lazyList; #WARNING: the endpoint must be one of the values that #the generator can return or it will never stop } #in Perl6 all code objects are closures, meaning they can #reference lexical veriables from an outer scope. An example: { sub generate-greeting { my $name = "John Doe"; sub greeting { say "Good Morning $name"; }; return &greeting; } my $generated = generate-greeting; $generated(); } #returns "Good Morning John Doe" =begin closureNote $generated is a closure, which combines a Subroutine and the Environment in which that subroutine was created. $generated is a closured that incorporates both the 'greeting' subroutine and the "John Doe" string that existed when the closure was created =end closureNote #a more interesting example: a subroutine factory! #$morning an $evening actually share the same subroutine #body, but store different environments! { sub greeting-generator($period) { return sub ($name) { return "Good $period $name" } } my $morning = greeting-generator("Morning"); my $evening = greeting-generator("Evening"); say $morning("John"); say $evening("Jane"); } =begin OOP So far we have talked about Functional Programming, the core style of Perl6, but like C++ and Python, Perl6 also supports the Object Oriented Programming paradigm. This is what we will talk about next! =end OOP =begin twigils you use the "class" keyword to identify a class, the "has" keyword to identify an attribute of a class. Secondary sigils called "twigils" identify encapsulation rules for a given attribute. A "." after the "$/@/%" automatically generates an accessor method for the attribute. A "!" after the "$/@/%"" explicitly declares that the attribute is private =end twigils { class Human { has $.name; has $.age; has $.sex; has $.nationality; } #note that just like in several other languages, #a default constructor is created for a class if one #is not explicitly made. "new" is normally the constructor #name my $john = Human.new(name => 'John', age => 23, sex => 'M', nationality => 'American'); say $john; say $john.age; } #note a class can be given lexical scope by using "my" #by default the constructor only accepts named parameters #(meaning you HAVE to specify which attribute you are #supplying data to). if you want to use positional arguments #like in C, you need to create another constructor that #accepts positional arguments: { class Human { has $.name; has $.age; has $.sex; has $.nationality; # new constructor that overrides the default one. method new ($name,$age,$sex,$nationality) { self.bless(:$name,:$age,:$sex,:$nationality); } } my $john = Human.new('John',23,'M','American'); say $john; }