Slide 1

Slide 1 text

Raku for Beginners: a hands-on tutorial (A small introduction to a big language) The Perl and Raku Conference
 
 2022-06-22

Slide 2

Slide 2 text

Raku for Beginners PLEASE DOWNLOAD THESE SLIDES! 
 http://speakerdeck.com/util
 <<< >>> >>> <<<

Slide 3

Slide 3 text

Preface

Slide 4

Slide 4 text

Preface (This is the beginning of the Song...)

Slide 5

Slide 5 text

Raku for Beginners: a hands-on tutorial (A small introduction to a big language) The Perl and Raku Conference
 
 2022-06-22

Slide 6

Slide 6 text

Raku for Beginners: a hands-on tutorial (A small introduction to a big language) The Perl and Raku Conference
 
 2022-06-22

Slide 7

Slide 7 text

Raku for Beginners: a hands-on tutorial (A small introduction to a big language) The Perl and Raku Conference
 
 2022-06-22

Slide 8

Slide 8 text

pruh-nuhn-see-ey-shuhn [ rah-koo ] / ˈrɑ ku / [ rey-koo ] / ˈreɪ ku / !8

Slide 9

Slide 9 text

Bruce Gray (Util)

Slide 10

Slide 10 text

Jonathan Worthington (jnthn) Patrick Michaud (Pm)

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

About the course ∞ NOT FOUND Discussion encouraged! Questions encouraged! !12

Slide 13

Slide 13 text

Hands on: Try It And See # From https://rakudo.org/star # or https://rakudo.org/downloads $ raku Welcome to Rakudo™ v2022.04. Implementing the Raku® Programming Language v6.d. Built on MoarVM version 2022.04. To exit type 'exit' or '^D' [0] > say 42; 42 !13

Slide 14

Slide 14 text

!14 •https://glot.io/new/raku
 •Docker: •REPL on any system: •docker run --rm -it rakudo-star •Script on Mac or Unix: • docker run --rm -v "$(pwd):/script" rakudo-star raku /script/a.raku •Script on Windows: • docker run --rm -v "%cd%:/script" rakudo-star raku /script/a.raku REPL alternatives

Slide 15

Slide 15 text

Raku for Beginners

Slide 16

Slide 16 text

Values

Slide 17

Slide 17 text

Numerics Integers: -5 0 1 42 !17

Slide 18

Slide 18 text

Numerics Integers: -5 0 1 42 Rationals (one integer divided by another): 0.25 5.05 !18

Slide 19

Slide 19 text

Numerics Integers: -5 0 1 42 Rationals (one integer divided by another): 0.25 5.05 Floating-point numbers (via Scientific Notation): 1.23e4 123e2 12300e0 !19

Slide 20

Slide 20 text

Values know their type > say 1.WHAT; (Int) > say 0.25.WHAT; (Rat) > say 1.23e4.WHAT; (Num) !20

Slide 21

Slide 21 text

Basic calculations say 35 + 7; # 42 say 1.2 - 0.3; # 0.9 say 2.1e5 * 3.3e2; # 69300000 say 168 / 4; # 42 say 169 % 4; # 1 say 3 ** 3; # 27 !21

Slide 22

Slide 22 text

!22 • How big can integers get?
 (Hint: try raising to a large power!)
 • What type do you get when you divide two integers?
 • Try 0.1 + 0.2 == 0.3 in some other language, then try it in Raku. What do you observe? Try it and see!

Slide 23

Slide 23 text

Floating-Point Cage Match !23

Slide 24

Slide 24 text

Floating-Point Cage Match python -c 'print( 0.3 - (0.1 + 0.2) )' !24

Slide 25

Slide 25 text

Floating-Point Cage Match python -c 'print( 0.3 - (0.1 + 0.2) )' -5.551115123125783e-17 !25

Slide 26

Slide 26 text

Floating-Point Cage Match python -c 'print( 0.3 - (0.1 + 0.2) )' -5.551115123125783e-17 perl -E 'say 0.3 - (0.1 + 0.2)' -5.55111512312578e-17 !26

Slide 27

Slide 27 text

Floating-Point Cage Match python -c 'print( 0.3 - (0.1 + 0.2) )' -5.551115123125783e-17 perl -E 'say 0.3 - (0.1 + 0.2)' -5.55111512312578e-17 raku -e 'say 0.3 - (0.1 + 0.2)' 0 !27

Slide 28

Slide 28 text

Floating-Point Cage Match python -c 'print( 0.3 - (0.1 + 0.2) )' -5.551115123125783e-17 perl -E 'say 0.3 - (0.1 + 0.2)' -5.55111512312578e-17 raku -e 'say 0.3 - (0.1 + 0.2)' 0 raku -e 'say 3e-1 - (1e-1 + 2e-1)' -5.551115123125783e-17 !28

Slide 29

Slide 29 text

Improved calculations say 6 % 3 !29

Slide 30

Slide 30 text

Improved calculations say (6 % 3) == 0 # True !30

Slide 31

Slide 31 text

Improved calculations say (6 % 3) == 0 # True say 6 %% 3; # True say 7 %% 3; # False say 8 %% 3; # False !31

Slide 32

Slide 32 text

Improved calculations say (6 % 3) == 0 # True say 6 %% 3; # True say 7 %% 3; # False say 8 %% 3; # False say (8 / 3).Int # 2 !32

Slide 33

Slide 33 text

Improved calculations say (6 % 3) == 0 # True say 6 %% 3; # True say 7 %% 3; # False say 8 %% 3; # False say (8 / 3).Int # 2 say 8 div 3; # 2 !33

Slide 34

Slide 34 text

Numeric routines ceiling floor truncate round abs sign sqrt exp log log10 log2 sin sinh asin asinh cos cosh acos acosh tan tanh atan atanh atan2 sec sech asec asech cosec cosech acosec acosech cotan cotanh acotan acotanh cis polar unpolar roots conj !34

Slide 35

Slide 35 text

Strings say 'Gangnam style!'; say "Much wow!"; !35

Slide 36

Slide 36 text

Strings say 'Gangnam style!'; say "Much wow!"; say 'Me\t&\tBobby McGee'; Me\t&\tBobby McGee say "Me\t&\tBobby McGee"; Me & Bobby McGee !36

Slide 37

Slide 37 text

Stitching strings together String concatenation operator: ~ say 'in' ~ 'finite'; # infinite !37

Slide 38

Slide 38 text

!38 •What happens if you forget about the tilde `~`, and instead try to use the dot `.` to concatenate two strings?
 •What happens if you completely forget to put an operator between the two strings? Think-o: Try it and see!

Slide 39

Slide 39 text

Awesome error messages! > say "a" . "b"; ===SORRY!=== Error while compiling: Unsupported use of . to concatenate strings. In Raku please use: ~. ------> say "a" .⏏ "b"; !39

Slide 40

Slide 40 text

Awesome error messages! > say "a" "b"; ===SORRY!=== Error while compiling: Two terms in a row ------> say "a"⏏ "b"; expecting any of: infix infix stopper postfix statement end statement modifier statement modifier loop !40

Slide 41

Slide 41 text

Some common string operations say uc('nyanCat'); # NYANCAT say lc('nyanCat'); # nyancat say tclc('nyanCat'); # Nyancat say substr('nyanCat', 2, 3); # anC say chars('nyanCat'); # 7 !41

Slide 42

Slide 42 text

Some common string operations say uc 'nyanCat'; # NYANCAT say lc 'nyanCat'; # nyancat say tclc 'nyanCat'; # Nyancat say substr 'nyanCat', 2, 3; # anC say chars 'nyanCat'; # 7 !42

Slide 43

Slide 43 text

Some common string operations say 'nyanCat'.uc; # NYANCAT say 'nyanCat'.lc; # nyancat say 'nyanCat'.tclc; # Nyancat say 'nyanCat'.substr(2, 3); # anC say 'nyanCat'.chars; # 7 !43

Slide 44

Slide 44 text

Burned dessert Brûlée !44

Slide 45

Slide 45 text

!45 • Graphemes: Things that a human would think of as "a character"
 • Codepoints: Things Unicode gives a number to (letters, numbers, marks, diacritics, symbols)
 • Bytes: The way codepoints are represented on disk, on the wire, etc. What does .chars really tell you?

Slide 46

Slide 46 text

!46 • Graphemes: Things that a human would think of as "a character"
 What does .chars really tell you?

Slide 47

Slide 47 text

Dessert dissected Brûlée B r û l é e !47

Slide 48

Slide 48 text

Dessert dissected Brûlée B r û l é e 42 72 c3bb 6c c3a9 65 !48

Slide 49

Slide 49 text

Booleans Raku provides True and False values of type Bool. say False.WHAT; # (Bool) say True.WHAT; # (Bool) All types know how to "boolify" themselves. You can ask them to with the `?` operator, or `!` to also negate that boolification. say ?42; # True say ?0; # False say !0; # True say so 0; # False ( lower precedence form of ? ) say not 0; # True ( lower precedence form of ! ) !49

Slide 50

Slide 50 text

Coercions ? so Force to Boolean ! not Force to Boolean and negate + Force to Numeric - Force to Numeric and negate ~ Force to String !50

Slide 51

Slide 51 text

Coercions Numifying a string that does not contain a valid number gives a `Failure` (a lazy exception, which is thrown if the value is used, but can be "defused" by testing it; more later!) > say +' 5 '; 5 > say +' 5 Wow!'; Cannot convert string to number:
 trailing characters after number
 in ' 5⏏ Wow!' (indicated by ⏏) !51

Slide 52

Slide 52 text

!52 • What string values are True and False? • ?'' • ?'0' • ?'False' • What types do you get for these?
 (Hint: be careful with precedence;
 .WHAT binds tighter than a prefix operator.) • +'42' • +'1.5' • +'4.2e4' • What do True and False numify to? Coercions: Try it and see!

Slide 53

Slide 53 text

Infix, Prefix, Postfix Operators say 5 ** 2; # power(5, 2) say 2 + 2; # add(2, 2) say +( '9' ~ '9' ); # make_numeric( # concat('9','9') # ) !53

Slide 54

Slide 54 text

https://www.ozonehouse.com/ mark/periodic/

Slide 55

Slide 55 text

No content

Slide 56

Slide 56 text

No content

Slide 57

Slide 57 text

No content

Slide 58

Slide 58 text

No content

Slide 59

Slide 59 text

No content

Slide 60

Slide 60 text

Variables

Slide 61

Slide 61 text

Variables (Because we are not Haskell)

Slide 62

Slide 62 text

Scalars hold a single item $answer = 42; !62

Slide 63

Slide 63 text

Scalars hold a single item $answer = 42; !63

Slide 64

Slide 64 text

Scalars hold a single item $answer = 42; ===SORRY!=== Error while compiling: Variable '$answer' is not declared ------> ⏏$answer = 42; !64

Slide 65

Slide 65 text

Scalars hold a single item my $answer; $answer = 42; !65

Slide 66

Slide 66 text

Scalars hold a single item my $answer; $answer = 42; say $answer; # 42 !66

Slide 67

Slide 67 text

Scalars hold a single item my $answer; $answer = 42; say $answer; # 42 $answer = $answer - 5; !67

Slide 68

Slide 68 text

Scalars hold a single item my $answer; $answer = 42; say $answer; # 42 $answer = $answer - 5; !68

Slide 69

Slide 69 text

Scalars hold a single item my $answer; $answer = 42; say $answer; # 42 $answer = $answer - 5; $answer -= 5; !69

Slide 70

Slide 70 text

Scalars hold a single item my $answer; $answer = 42; say $answer; # 42 $answer = $answer - 5; $answer -= 5; say $answer; # 37 !70

Slide 71

Slide 71 text

Vars untyped unless specified my $answer; $answer = 42; say $answer; # 42 $answer = $answer - 5; $answer -= 5; say $answer; # 37 my $age = "I'm thirty seven -- I'm not old!"; !71

Slide 72

Slide 72 text

Typed Vars my Int $speed = 125; my Str $singer = 'Hagar'; !72

Slide 73

Slide 73 text

Typed Vars my Int $speed = 125; my Str $singer = 'Hagar'; $speed /= 2; !73

Slide 74

Slide 74 text

!74 • What happens if you declare a variable with a type, like `my Int $age;`, then try to assign it a value of a different type?
 • What is the value in a variable that has been declared but not initialized?
 (Hint: use .raku method to look)
 • Same question, but the variable was declared with a type. Typed vars: Try it and see

Slide 75

Slide 75 text

Typed Vars my Int $speed = 125; my Str $singer = 'Hagar'; $speed /= 2; Type check failed in assignment to $speed; expected Int but got Rat (62.5) !75

Slide 76

Slide 76 text

Typed Vars my Numeric $speed = 125; my Str $singer = 'Hagar'; $speed /= 2; # is now 62.5 !76

Slide 77

Slide 77 text

Scalars: Behind the Scenes (skipped!)

Slide 78

Slide 78 text

Arrays my @countries; !78

Slide 79

Slide 79 text

Arrays my @countries = 'UK', 'Peru', 'Spain', 'Sweden'; !79

Slide 80

Slide 80 text

Arrays my @countries = 'UK', 'Peru', 'Spain', 'Sweden'; say @countries.WHAT; # (Array) say @countries.elems; # 4 !80

Slide 81

Slide 81 text

Array indexing my @countries = 'UK', 'Peru', 'Spain', 'Sweden'; say @countries[0]; # UK say @countries[*-1]; # Sweden !81

Slide 82

Slide 82 text

Array indexing my @countries = 'UK', 'Peru', 'Spain', 'Sweden'; @countries[4] = 'Czech Republic'; say @countries.elems; # 5 !82

Slide 83

Slide 83 text

Array indexing my @countries = 'UK', 'Peru', 'Spain', 'Sweden'; @countries[1, 2] = @countries[2, 1]; say @countries[0, 1, 2]; # UK Spain Peru say @countries[0..2]; !83

Slide 84

Slide 84 text

Arrays and binding When you assign into an array, each element is a `Scalar` container. You can therefore bind array elements. my $first := @countries[0]; $first = 'England'; say @countries[0]; # England Again, you probably won't do this much yourself. However, it is the mechanism that is behind things like: @values[$idx]++; !84

Slide 85

Slide 85 text

Quote words my @countries = 'UK', 'Peru', 'Spain', 'Sweden'; !85

Slide 86

Slide 86 text

Quote words my @countries = 'UK', 'Peru', 'Spain', 'Sweden'; my @countries = ; !86

Slide 87

Slide 87 text

Quote words my @countries = 'UK', 'Peru', 'Spain', 'Sweden'; my @countries = ; my @countries = < United Kingdom Peru Spain Sweden >; !87

Slide 88

Slide 88 text

Quote words my @countries = 'UK', 'Peru', 'Spain', 'Sweden'; my @countries = ; my @countries = << 'United Kingdom' Peru Spain Sweden >>; !88

Slide 89

Slide 89 text

Quote words my @countries = 'UK', 'Peru', 'Spain', 'Sweden'; my @countries = ; my @countries = << 'United Kingdom' Peru Spain Sweden >>; my @countries = « 'United Kingdom' Peru Spain Sweden »; !89

Slide 90

Slide 90 text

Stack/queue behavior You can `push`/`pop` at the end of an array: my @values; @values.push(35); @values.push(7); @values.push(@values.pop + @values.pop); We could have used the `push`/`pop` functions also. At the start of an array, we can use `unshift` and `shift`. Using `push` and `shift` in combination, you get queue semantics. !90

Slide 91

Slide 91 text

Stack/queue behavior !91 0 1 2 3 4 Ariel Belle Cinderella Dumbo Eeyore shift unshift push pop

Slide 92

Slide 92 text

Stack of Disney my @disney = ; @disney.push(@disney.pop ~ @disney.pop); !92 0 1 2 3 4 Ariel Belle Cinderella Dumbo Eeyore shift unshift push pop

Slide 93

Slide 93 text

!93 • What happens if you assign to slot 0 and 3 of an array? What is `.elems`, and what do the slots 1 and 2 contain?
 • If you assign one array to another, do you get a fresh set of scalars?
 • What happens if you bind an array to another array?
 • What happens if you bind a quote-words list directly to an `@variable`? Can you assign to its elements?
 Arrays: Try it and see!

Slide 94

Slide 94 text

@array %hash Positional Associative

Slide 95

Slide 95 text

COBOL SNOBOL

Slide 96

Slide 96 text

Hashes my %capitals; !96

Slide 97

Slide 97 text

Hashes my %capitals; !97

Slide 98

Slide 98 text

Hashes my %capitals; my %capitals = ; !98

Slide 99

Slide 99 text

Hashes my %capitals; my %capitals = ; my %capitals = UK => 'London', Peru => 'Lima', ; !99

Slide 100

Slide 100 text

Pair ABC => 'XYZ' !100

Slide 101

Slide 101 text

Pair ABC => 'XYZ' !101

Slide 102

Slide 102 text

Pair ABC => 'XYZ' > say ( ABC => 'XYZ' ).WHAT; !102

Slide 103

Slide 103 text

Pair ABC => 'XYZ' > say ( ABC => 'XYZ' ).WHAT; (Pair) !103

Slide 104

Slide 104 text

Pair ABC => 'XYZ' > say ( ABC => 'XYZ' ).WHAT; (Pair) > say ( ABC => 'XYZ' ).[0]; > say ( ABC => 'XYZ' ).[1]; !104

Slide 105

Slide 105 text

Pair ABC => 'XYZ' > say ( ABC => 'XYZ' ).WHAT; (Pair) > say ( ABC => 'XYZ' ).[0]; > say ( ABC => 'XYZ' ).[1]; !105

Slide 106

Slide 106 text

Pair ABC => 'XYZ' > say ( ABC => 'XYZ' ).WHAT; (Pair) > say ( ABC => 'XYZ' ).key; !106

Slide 107

Slide 107 text

Pair ABC => 'XYZ' > say ( ABC => 'XYZ' ).WHAT; (Pair) > say ( ABC => 'XYZ' ).key; ABC !107

Slide 108

Slide 108 text

Pair ABC => 'XYZ' > say ( ABC => 'XYZ' ).WHAT; (Pair) > say ( ABC => 'XYZ' ).key; ABC > say ( ABC => 'XYZ' ).value; !108

Slide 109

Slide 109 text

Pair ABC => 'XYZ' > say ( ABC => 'XYZ' ).WHAT; (Pair) > say ( ABC => 'XYZ' ).key; ABC > say ( ABC => 'XYZ' ).value; XYZ !109

Slide 110

Slide 110 text

Pair > my $p = ABC => 'XYZ'; > say $p.WHAT; # (Pair) > say $p.key; # ABC > say $p.value; # XYZ !110

Slide 111

Slide 111 text

Hashes my %capitals; my %capitals = ; my %capitals = UK => 'London', Peru => 'Lima', ; !111

Slide 112

Slide 112 text

Hashes my %capitals = UK => 'London', Peru => 'Lima', ; !112

Slide 113

Slide 113 text

Hashes my %capitals = UK => 'London', Peru => 'Lima'; . !113

Slide 114

Slide 114 text

Indexing and slicing my %capitals = UK => 'London', Peru => 'Lima'; say %capitals{'UK'}; # London a !114

Slide 115

Slide 115 text

Indexing and slicing my %capitals = UK => 'London', Peru => 'Lima'; say %capitals{'UK'}; # London say %capitals{'UK', 'Peru'}; # London Lima !115

Slide 116

Slide 116 text

Indexing and slicing my %capitals = UK => 'London', Peru => 'Lima'; say %capitals{'UK'}; # London say %capitals{'UK', 'Peru'}; # London Lima !116

Slide 117

Slide 117 text

Indexing and slicing my %capitals = UK => 'London', Peru => 'Lima'; say %capitals{'UK'}; # London say %capitals{'UK', 'Peru'}; # London Lima say %capitals; say %capitals; !117

Slide 118

Slide 118 text

Indexing and slicing my %capitals = UK => 'London', Peru => 'Lima'; say %capitals{'UK'}; # London say %capitals{'UK', 'Peru'}; # London Lima say %capitals; say %capitals; say %capitals{$country}; !118

Slide 119

Slide 119 text

Existence and deletion There is no `exists` function or method in Raku. Instead, you use the normal indexing syntax and add the `:exists` adverb: > say %capitals:exists; True > say %capitals:exists; False > say %capitals:exists; (True True False) !119

Slide 120

Slide 120 text

Existence and deletion The same goes for deletion: %capitals = %capitals; %capitals = 'Edinburgh'; %capitals:delete; !120

Slide 121

Slide 121 text

Other useful Hash methods my %capitals = UK => 'London', Peru => 'Lima'; say %capitals.keys; # (Peru UK) say %capitals.values;# (Lima London) say %capitals.pairs; # (Peru => Lima UK => London) say %capitals.kv; # (Peru Lima UK London) !121

Slide 122

Slide 122 text

!122 • Are pairs first-class objects in Raku?
 Hint: (UK => 'London').WHAT
 • Suppose you declare the hash in our examples, and have
 `my $a = 'UK';`. Think about what `%capitals{$a}` will do compared to `%capitals<$a>`. 
 Try it and see if you guessed correctly!
 • What happens if you assign one hash to another?
 What if you assign a hash to an array?
 How about an array to a hash?
 • What happens if you use any of these on an array?
 .keys .values .kv .pairs Pairs & Hashes: Try it and see!

Slide 123

Slide 123 text

BTW: Constants constant $speed-of-light = 299792458; constant @middle_three = 'M'..'O'; !123

Slide 124

Slide 124 text

BTW: Constants # Perl 5: use constant E => exp(1); use constant PI => 4 * atan2(1, 1); use constant TAU => 2 * atan2(0,-1); !124

Slide 125

Slide 125 text

BTW: Constants # Perl 5: use constant E => exp(1); use constant PI => 4 * atan2(1, 1); use constant TAU => 2 * atan2(0,-1); # Raku: 𝑒 e π pi τ tau !125

Slide 126

Slide 126 text

Interpolation basics There are numerous advantages to variables having sigils. One of them is easy **interpolation** of variables in strings. First off, **single quoted** strings do not interpolate: my $who = 'your mom'; say '$who ate the pie'; # $who ate the pie In double-quoted strings, strings interpolate pretty much as you'd expect: say "$who ate the pie"; # your mom ate the pie !126

Slide 127

Slide 127 text

Interpolation of arrays and hashes It's possible to interpolate arrays and hashes, but you need to make a little more effort than with scalars. That way, we don't mangle email addresses. say "Contact [email protected]"; # Contact [email protected] Instead, you need to index. Note that the empty index, known as the **zen slice**, allows you to get all elements. my @winners = ; say "The winner is @winners[0]"; say "Top 3 were @winners[]"; The same rules apply for hashes. !127

Slide 128

Slide 128 text

Interpolating method calls You can also interpolate method calls on any kind of variable: my @winners = ; say "Top 3 are: @winners.join(', ')"; say "CONGRATULATIONS @winners[0].uc()!"; Note that this will not happen if you don't put the parentheses on, so we will not screw up things involving file extensions: my $fh = open "$file.txt"; # Does not try and call .txt !128

Slide 129

Slide 129 text

Try it and see * You can embed code inside an interpolated string using curlies `{ … }`. Try doing a calculation inside of one; summing $x and $y .
 * `"$name"` is the one common gotcha from the Raku interpolation rules. What happens if you try it?
 Why does it happen?
 Can you find a solution? !129

Slide 130

Slide 130 text

Very Basic I/O

Slide 131

Slide 131 text

The standard handles Use `say` to write a line to standard output, and `note` to write a line to standard error. say "it again"; note "Uh-oh…"; A convenient way to write out a prompt and read a line from standard input is the `prompt` function: my $color = prompt "Name a color: "; !131

Slide 132

Slide 132 text

Working with files We can read a file entirely into a scalar using `slurp`, or into an array of lines by getting an IO handle and calling `lines`: my $whole-file = slurp $filename; my @lines = $filename.IO.lines; The opposite of `slurp` is `spurt`: spurt $filename, $stuff; Naturally, you can do much more than this - but it's enough for now. !132

Slide 133

Slide 133 text

> say .raku for 'a.dat'.IO.slurp; "abc\ndef\n" > say .raku for 'a.dat'.IO.lines; "abc" "def" !133

Slide 134

Slide 134 text

Flow control

Slide 135

Slide 135 text

Comparisons Numeric String Equal == eq Not equal != ne Less than < lt Less than or equal <= le Greater than > gt Greater than or equal >= ge !135

Slide 136

Slide 136 text

Aside: general design rule Perl has generally followed the view that different semantics means different operator. This means that you know how the program will behave even if you don't know the exact types of the data. There's no question that `==` means numeric equality and `eq` means string equality, or that `+` is addition and `~` is concatenation. In Raku we've de-confused a few things from Perl 5. say 'edam'.flip; # made say (1, 2, 3).reverse; # 3 2 1 say 'omg' x 2; # (string 'omgomg') say 'omg' xx 2; # (a list containing 'omg' twice) !136

Slide 137

Slide 137 text

if, elsif, else my $num = prompt 'Enter a number: '; if $num < 0 { say 'Negative'; } elsif $num > 0 { say 'Positive'; } else { say 'Zero'; } !137

Slide 138

Slide 138 text

if, elsif, else Condition ?? WhenTrue !! WhenFalse $a < 3 ?? complain() !! cheer(); if $a < 3 { complain(); } else { cheer(); } !138

Slide 139

Slide 139 text

if, elsif, else my $num = prompt 'Enter a number: '; my $s = $num < 0 ?? 'Negative' !! $num > 0 ?? 'Positive' !! 'Zero'; say $s; !139

Slide 140

Slide 140 text

if, elsif, else my $num = prompt 'Enter a number: '; say $num < 0 ?? 'Negative' !! $num > 0 ?? 'Positive' !! 'Zero'; !140

Slide 141

Slide 141 text

if, elsif, else my $num = prompt 'Enter a number: '; say [1 + ($num <=> 0)]; !141

Slide 142

Slide 142 text

Postfix If shout() if you_need_something(); $a = 5 if $b > 12; say "It's alive!" unless $it-is-not-alive; warn "Printer on fire?" unless $printer_printed; !142

Slide 143

Slide 143 text

If, with pointy blocks my $name = get-user-name($user-id); if $name { … } !143

Slide 144

Slide 144 text

If, with pointy blocks my $name = get-user-name($user-id); if $name { … } … … … … … … … … !144

Slide 145

Slide 145 text

If, with pointy blocks my $name = get-user-name($user-id); if $name { … } if ( my $name = get-user-name($user-id) ) { … } !145

Slide 146

Slide 146 text

If, with pointy blocks my $name = get-user-name($user-id); if $name { … } if ( my $name = get-user-name($user-id) ) { … } if get-user-name($user-id) -> $name { … } !146

Slide 147

Slide 147 text

If, with pointy blocks my $name = get-user-name($user-id); if $name { … } if ( my $name = get-user-name($user-id) ) { … } if get-user-name($user-id) -> my $name { … } !147

Slide 148

Slide 148 text

If, with pointy blocks my $name = get-user-name($user-id); if $name { … } if ( my $name = get-user-name($user-id) ) { … } if get-user-name($user-id) -> Str $name { … } !148

Slide 149

Slide 149 text

given/when given prompt 'Enter a number: ' { when * < 0 { say 'Negative'; } when * > 0 { say 'Positive'; } default { say 'Zero'; } } !149

Slide 150

Slide 150 text

Loops: loop The `loop` statement is for writing an infinite loop. loop { print 'OVER HANG'; } !150

Slide 151

Slide 151 text

The good old days 10 PRINT "HIT BULLS" 20 GOTO 10 !151

Slide 152

Slide 152 text

Loops: loop The `loop` statement is for writing an infinite loop. loop { print 'OVER HANG'; } You can also use it for C-style loops: loop ( my $i = 10 ; $i > 0 ; $i-- ) { print $i, ' '; } say 'LIFT OFF!'; !152

Slide 153

Slide 153 text

Loops: while/until The `while` loop is rather unsurprising: my @tasks; while @tasks.elems < 5 { @tasks.push( prompt('Enter a task: ') ); } Sometimes, `until` is more natural: my @tasks; until @tasks.elems >= 5 { @tasks.push( prompt('Enter a task: ') ); } !153

Slide 154

Slide 154 text

Loops: while/until with pointy blocks We can also test a value for truth and capture it into a variable only visible inside the block loop: my @tasks; while prompt('Enter a task (blank if done): ') -> $t { @tasks.push($t); } !154

Slide 155

Slide 155 text

Loops: while/until with pointy blocks my @tasks; constant $request_task = 'Enter a task (blank if done): '; while prompt($request_task) -> $t { @tasks.push($t); } !155

Slide 156

Slide 156 text

Try it and see! Write the classic "guess my number" game. Pick a random number between 1 and 100 (hint: `my $number = (1..100).pick`). Let the user make up to 7 guesses. If they get it right, say they won and `exit;`. If not, state they are too high or too low. If they don't get it in 7 guesses, tell them they suck. If you finish this, investigate using `last` instead of `exit`. After this refactor, try to implement giving the option to play again "yes/no". If you're still way ahead, make it multi-player, reading in two player names and letting them take turns. !156

Slide 157

Slide 157 text

Iteration for @tasks -> $task { say $task.tclc; } !157

Slide 158

Slide 158 text

Iteration for @tasks -> $task is rw { say $task.tclc; } !158

Slide 159

Slide 159 text

Iteration for @tasks -> $task is rw { say $task.tclc; } for @tasks <-> $task { say $task.tclc; } !159

Slide 160

Slide 160 text

Iteration for @tasks { say .tclc; } !160

Slide 161

Slide 161 text

Iteration for @tasks { # uses topic $_ say .tclc; } !161

Slide 162

Slide 162 text

Iteration for @tasks { say .tclc; } say .tclc for @tasks; !162

Slide 163

Slide 163 text

Loops: loop The `loop` statement is for writing an infinite loop. loop { print 'OVER HANG'; } You can also use it for C-style loops: loop ( my $i = 10 ; $i > 0 ; $i-- ) { print $i, ' '; } say 'LIFT OFF!'; !163

Slide 164

Slide 164 text

Loops: loop loop ( my $i = 10 ; $i > 0 ; $i-- ) { print $i, ' '; } say 'LIFT OFF!'; !164

Slide 165

Slide 165 text

Loops: loop loop ( my $i = 10 ; $i > 0 ; $i-- ) { print $i, ' '; } say 'LIFT OFF!'; !165

Slide 166

Slide 166 text

Loops: loop loop ( my $i = 10 ; $i > 0 ; $i-- ) { print $i, ' '; } say 'LIFT OFF!'; !166

Slide 167

Slide 167 text

Loops: loop loop ( my $i = 10 ; $i > 0 ; $i-- ) { print $i, ' '; } say 'LIFT OFF!'; !167

Slide 168

Slide 168 text

Loops: loop loop ( my $i = 10 ; $i > 0 ; $i-- ) { print $i, ' '; } say 'LIFT OFF!'; !168

Slide 169

Slide 169 text

Loops: loop loop ( my $i = 10 ; $i > 0 ; $i-- ) { print $i, ' '; } say 'LIFT OFF!'; !169

Slide 170

Slide 170 text

Loops: loop loop ( my $i = 10 ; $i > 0 ; $i-- ) { print $i, ' '; } say 'LIFT OFF!'; !170

Slide 171

Slide 171 text

Loops: loop loop ( my $i = 10 ; $i > 0 ; $i-- ) { print $i, ' '; } say 'LIFT OFF!'; !171

Slide 172

Slide 172 text

Loops: loop loop ( my $i = 10 ; $i > 0 ; $i-- ) { print $i, ' '; } say 'LIFT OFF!'; !172

Slide 173

Slide 173 text

Loops: loop loop ( my $i = 10 ; $i > 0 ; $i-- ) { print $i, ' '; } say 'LIFT OFF!'; !173

Slide 174

Slide 174 text

Loops: loop loop ( my $i = 10 ; $i > 0 ; $i-- ) { print $i, ' '; } say 'LIFT OFF!'; !174

Slide 175

Slide 175 text

For loops with Ranges loop ( my $i = 10 ; $i > 0 ; $i-- ) { print $i, ' '; } for ????? -> $i { print $i, ' '; } say 'LIFT OFF!'; !175

Slide 176

Slide 176 text

For loops with Ranges loop ( my $i = 10 ; $i > 0 ; $i-- ) { print $i, ' '; } for 1..10 -> $i { print $i, ' '; } say 'LIFT OFF!'; !176

Slide 177

Slide 177 text

For loops with Ranges loop ( my $i = 10 ; $i > 0 ; $i-- ) { print $i, ' '; } for reverse 1..10 -> $i { print $i, ' '; } say 'LIFT OFF!'; !177

Slide 178

Slide 178 text

For loops with Ranges loop ( my $i = 10 ; $i > 0 ; $i-- ) { print $i, ' '; } for reverse 1..10 -> $i { print $i, ' '; } print $i, ' ' for reverse 1..10; say 'LIFT OFF!'; !178

Slide 179

Slide 179 text

For loops with Ranges loop ( my $i = 10 ; $i > 0 ; $i-- ) { print $i, ' '; } for reverse 1..10 -> $i { print $i, ' '; } print $i, ' ' for reverse 1..10; print $i, ' ' for (1..10).reverse; say 'LIFT OFF!'; !179

Slide 180

Slide 180 text

Clarifying ranges say (1..10).WHAT; # Range 1 .. 5 # 1, 2, 3, 4, 5 1 ^.. 5 # 2, 3, 4, 5 1 ..^ 5 # 1, 2, 3, 4 1 ^..^ 5 # 2, 3, 4 ^5 # 0, 1, 2, 3, 4 (short for 0..^5) !180

Slide 181

Slide 181 text

No content

Slide 182

Slide 182 text

Negaverse Infinity Gauntlet > -∞ .. 42 -Inf..42 > (-∞ .. 42).head(5) (-Inf -Inf -Inf -Inf -Inf) > say ( -∞ .. 42 ).reverse.head(5); (42 41 40 39 38) !182

Slide 183

Slide 183 text

Smartmatch on Range: "Inside" 7 ~~ 1..9 7 >= 1 and 7 <= 9 4 ^.. 7 > 4 ~~ 4 ^.. 7 # False > 4.1 ~~ 4 ^.. 7 # True !183

Slide 184

Slide 184 text

!184 • What do you expect this code to do?
 for ^8 -> $a {
 say $a;
 }
 Try it!
 • What if you edit both occurrences of `$a` in the code, typing `$a, $b` in place of `$a`?
 • Same question, but `$a, $b, $c` ! You-pick-two: Try it and see!

Slide 185

Slide 185 text

REPL'ed: N-at-a-time > for ^8 -> $a { say $a } 0 1 2 3 4 5 6 7 > for ^8 -> $a, $b { say $a, $b } 01 23 45 67 !185

Slide 186

Slide 186 text

REPL'ed: N-at-a-time > for ^8 -> $a, $b, $c { say $a, $b, $c } 012 345 Too few positionals passed; expected 3 arguments but got 2 in block at line 1 > for ^8 -> $a, $b, $c? { say $a, $b, $c } 012 345 67(Mu) !186

Slide 187

Slide 187 text

TPRC Bonus! use 5.36.0; use experimental qw; for my ($x, $y) ('A'..'F') { say $x, $y; } !187

Slide 188

Slide 188 text

https://rjbs.cloud/blog/2022/05/perl-5.36/ use 5.36.0; use experimental qw; for my ($x, $y) ('A'..'F') { say $x, $y; } AB CD EF !188

Slide 189

Slide 189 text

REPL'ed: N-at-a-time > for ^8 -> $a, $b, $c { say $a, $b, $c } 012 345 Too few positionals passed; expected 3 arguments but got 2 in block at line 1 > for ^8 -> $a, $b, $c? { say $a, $b, $c } 012 345 67(Mu) !189

Slide 190

Slide 190 text

.kv

Slide 191

Slide 191 text

Lists have Keys, too! for .kv -> $num, $name { say "$num. $name"; } !191

Slide 192

Slide 192 text

Sarah is Number One! for .kv -> $num, $name { say "$num. $name"; } 0. Bruce 1. Sarah !192

Slide 193

Slide 193 text

Zer0 , from Borderlands 2 for .kv -> $num, $name { say "$num. $name"; } 0. Bruce 1. Sarah !193

Slide 194

Slide 194 text

Hash.kv my %capitals = UK => 'London', Peru => 'Lima'; for %capitals.kv -> $country, $city { say "$city is the capital of $country"; say "$city's capital is $country"; say "{$city}'s capital is $country"; } !194

Slide 195

Slide 195 text

Not just for .kv You can take two (or three, or more) at a time from any array, not just with `.kv`. For example, suppose we wanted to shuffle and randomly pair up people to dance together, we could do: my @dancers = ; for @dancers.pick(*) -> $first, $second { say "$first dances with $second"; } Note that this will fail if there are an odd number of dancers. Soon, we'll discover that the pointy block arguments are just a special case of Raku signatures, and you can make one optional or set a default. !195

Slide 196

Slide 196 text

!196 • 5..8 + 12
 •(5..8) + 12
 •(5..8) * 3
 •(5..8) / 12
 •(5..8) + (8..9) Back to Ranges: Try it and See!

Slide 197

Slide 197 text

Try it and see! Create a file with various words in. Loop over the words with a `for` loop (hint: you can put one word per line in the file and use `lines('file'.IO)`). Use a hash to count how many times you've seen each word (use the `++` increment operator). Then loop over the hash to show how many times each word was seen. If you get done: make it case insensitive, and implement some means to filter out very common words ('a', 'the', 'is', etc'). !197

Slide 198

Slide 198 text

Subs and signatures

Slide 199

Slide 199 text

Subs and signatures "Callable" code

Slide 200

Slide 200 text

Callable Code: Sub sub dance_with ( $partner ) { say "Dancing with $partner"; } !200

Slide 201

Slide 201 text

Callable Code: Sub sub dance_with ( $partner ) { say "Dancing with $partner"; } !201

Slide 202

Slide 202 text

Callable Code: Sub sub dance_with ( $partner ) { say "Dancing with $partner"; } !202

Slide 203

Slide 203 text

Callable Code: Sub sub dance_with ( $partner ) { say "Dancing with $partner"; } !203

Slide 204

Slide 204 text

Callable Code: Sub sub dance_with ( $partner ) { say "Dancing with $partner"; } > dance_with('Sarah'); !204

Slide 205

Slide 205 text

Callable Code: Sub sub dance_with ( $partner ) { say "Dancing with $partner"; } > dance_with('Sarah'); Dancing with Sarah !205

Slide 206

Slide 206 text

Callable Code: Sub sub dance_with ( $partner ) { say "Dancing with $partner"; } > dance_with('Sarah'); Dancing with Sarah !206

Slide 207

Slide 207 text

Callable Code: Sub sub dance_with ( $partner ) { say "Dancing with $partner"; } > dance_with('Sarah'); Dancing with Sarah > dance_with('Sarah', 'Jill'); !207

Slide 208

Slide 208 text

Callable Code: Sub sub dance_with ( $partner ) { say "Dancing with $partner"; } > dance_with('Sarah'); Dancing with Sarah > dance_with('Sarah', 'Jill'); Calling dance_with(Str, Str) will never work with declared signature ($partner) !208

Slide 209

Slide 209 text

Callable Code: Sub sub dance_with ( $partner ) { say "Dancing with $partner"; } > dance_with('Sarah'); Dancing with Sarah > dance_with('Sarah', 'Jill'); Calling dance_with(Str, Str) will never work with declared signature ($partner) !209

Slide 210

Slide 210 text

Pointy blocks can go solo We've already seen that "pointy blocks" can go on `for`/`while` loops, `if` statements, and so forth. However, writing one alone gives you a callable piece of code. You can store it in a variable: my $greeter = -> $greeting, $name { say "$greeting, $name!" }; And later call it: $greeter('Hej', 'Carl'); # Hej, Carl! Of course, there's a more convenient way… !210

Slide 211

Slide 211 text

Sub declarations We can use the `sub` keyword to declare a subroutine: sub truncate($text) { $text.chars > 100 ?? "$text.substr(0, 100)…" !! $text } We can then call it in one of the following ways: my $short = truncate($text); # Function call form my $short = truncate $text; # List op form !211

Slide 212

Slide 212 text

Syntax rules for calls There are a couple of consistent rules about how calls are parsed. First, `foo(…)` is **always** a call. It even beats keywords. sub if($cond, $code) { if $cond { $code() } } if(True, -> { say "Wow, a sub called 'if'!" }); Second, whitespace after the sub name will **always** make it a list op. This XXX code say substr "craft", 1; # Correct, substr gets 2 args say substr ("craft", 1); # WRONG, substr gets 1 arg (a list) !212

Slide 213

Slide 213 text

Returning results Our `truncate` sub worked fine because by default a sub returns the value produced by its final statement. We could have been more explicit by using `return`: sub truncate($text) { return $text.chars > 100 ?? "$text.substr(0, 10)…" !! $text } In this case, it's a matter of personal preference. However, in other cases you may need `return` in order to return from a nested block. Note that **pointy blocks are transparent to `return`**. You can not `return` out of a pointy block, only out of a routine (that is, a `sub` or a `method`, which we'll see soon). !213

Slide 214

Slide 214 text

Passing arrays and hashes sub trim-to-shortest ( @a, @b ) { pop @a while @a > @b; pop @b while @b > @a; } my @x = 1..9; my @y = 5..7; trim-to-shortest(@x, @y); say @x; # 1 2 3 say @y; # 5 6 7 !214

Slide 215

Slide 215 text

Passing arrays and hashes sub trim-to-shortest ( @a, @b ) { pop @a while @a > @b; pop @b while @b > @a; } my @x = 1..9; my @y = 5..7; trim-to-shortest(@x, @y); say [ :@x, :@y ].raku; # [:x([1, 2, 3]), :y([5, 6, 7])] !215

Slide 216

Slide 216 text

!216 • argument: thing you are passing when you call a sub (or other code)
 • 
 • 
 
 • A note on terminology

Slide 217

Slide 217 text

!217 • argument: thing you are passing when you call a sub (or other code)
 • argument list: list of zero or more arguments
 • 
 
 • A note on terminology

Slide 218

Slide 218 text

!218 • argument: thing you are passing when you call a sub (or other code)
 • argument list: list of zero or more arguments
 • Parameter: thing you declare that receives the argument
 • A note on terminology

Slide 219

Slide 219 text

!219 • argument: thing you are passing when you call a sub (or other code)
 • argument list: list of zero or more arguments
 • Parameter: thing you declare that receives the argument
 • Signature: list of zero or more Parameters A note on terminology

Slide 220

Slide 220 text

!220 • argument: thing you are passing when you call a sub (or other code)
 • argument list: list of zero or more arguments
 • Parameter: thing you declare that receives the argument
 • Signature: list of zero or more Parameters A note on terminology

Slide 221

Slide 221 text

!221 • argument: thing you are passing when you call a sub (or other code)
 • argument list: list of zero or more arguments
 • Parameter: thing you declare that receives the argument
 • Signature: list of zero or more Parameters Petrified Lingo

Slide 222

Slide 222 text

Try it and see! See how a couple of possible failure modes work out: * What happens if you call a sub with the wrong number of arguments? Do you get an error? Is it compile time or runtime? * Make a typo when calling a sub. Do we find it at compile time or runtime? Next, refactor your word frequency program into two subs: `calculate-frequencies` and `display- frequencies`. !222

Slide 223

Slide 223 text

Functional Programming (Higher-Order Raku)

Slide 224

Slide 224 text

grep my @odds = grep { $_ !%% 2 }, 0..9; !224

Slide 225

Slide 225 text

Optional parameters When we put a `?` on a parameter, we make it optional. If no argument is passed for it, then it will contain `Any`. This "undefined" value is false in boolean context, so we can do this: XXX Move to API!!! No, needed for MAIN my @dancers = ; for @dancers.pick(*) -> $first, $second? { if $second { say "$first dances with $second"; } else { say "$first dances alone"; } } !225

Slide 226

Slide 226 text

Default values Another way to make a parameter optional is to supply a **default**: my @dancers = ; for @dancers.pick(*) -> $first, $second = 'the teacher' { say "$first dances with $second"; } Defaults are evaluated per call. Further, since we bind left to right, it is possible to default to a previous parameter: sub log-event($event, $occurred = now, $logged = $occurred) { # … } !226

Slide 227

Slide 227 text

Named arguments/parameters It's also possible to use named arguments and parameters. These are typically used for extra configuration and options, and so they are **optional by default**. sub truncate($text, :$limit = 100, :$trailer = '…') { $text.chars > $limit ?? "$text.substr(0, $limit)$trailer" !! $text } say truncate("Drink a beer", limit => 11); # Drink a bee… !227

Slide 228

Slide 228 text

Other ways to pass named arguments We have a number of different syntaxes for named arguments. limit => 11 # fat arrow syntax :limit(11) # colon pair syntax The colon pair syntax has some special cases for booleans: :global # same as :global(True) :!global # same as :global(False) And also one for passing on a variable with the same name as the parameter: :$global # same as :global($global) !228

Slide 229

Slide 229 text

Slurpy parameters Also we have slurpy parameters, when we want to accept any number of arguments. There are a few forms of these. For example, we can take all positionals: sub join-and-truncate($joiner, $limit, *@values) { truncate(@values.join($joiner), limit => $limit); } Or perhaps also all the named arguments: sub join-and-truncate($joiner, *@values, *%options) { # … but how to pass the options on to truncate? } !229

Slide 230

Slide 230 text

Flattening arguments The "opposite" of slurping is flattening an array or hash into an argument list. This is done with the `|` prefix operator (which is only meaningful inside of an argument list). sub join-and-truncate($joiner, *@values, *%options) { truncate(@values.join($joiner), | %options); } !230

Slide 231

Slide 231 text

Slurpy positionals and flattening It's sometimes important to remember that `*@pos` will flatten incoming arrays into a single array. Therefore, if you want to write this: sub check-array-lengths(*@arrays) { for @arrays -> @arr { die "Oh no it's too long!" if @arr.elems > 5; } } my @a = 1..4; my @b = 1..3; check-array-lengths(@a, @b); You'll end up in a mess, with `@arrays` containing 7 `Int`s! !231

Slide 232

Slide 232 text

Non-flattening slurpy positional You can prevent this steam-rollering by using `**@arrays` instead: sub check-array-lengths(*@arrays) { for @arrays -> @arr { die "Oh no it's too long!" if @arr.elems > 5; } } my @a = 1..4; my @b = 1..3; check-array-lengths(@a, @b); !232

Slide 233

Slide 233 text

Code arguments To pass along a subroutine as an argument to another subroutine, pass it by putting the `&` before its name. On the parameter side, you could happily use a `Scalar`, but using the `&` sigil there too offers convenient calling. sub run-without-banned-options(&run, %options, @banned) { my %filtered = %options; %filtered{@banned}:delete; run(|%filtered); } sub operate(:$force, :$strip, :$verbose) { say $force, $strip, $verbose; } my %opts = force => 1, verbose => 1; my @banned = 'force', 'strip'; run-without-banned-options(&operate, %opts, @banned); !233

Slide 234

Slide 234 text

is copy Note how we made a copy of the `%options` hash on the previous slide. We did this so as to avoid modifying the existing one that was passed to us. We can achieve this more easily with `is copy`: sub run-without-banned-options(&run, %options is copy, @banned) { %options{@banned}:delete; run(|%options); } sub operate(:$force, :$strip, :$verbose) { say $force, $strip, $verbose; } my %opts = force => 1, verbose => 1; my @banned = 'force', 'strip'; run-without-banned-options(&operate, %opts, @banned); !234

Slide 235

Slide 235 text

Try it and see First, try to write a sub `inc` that, when passed a variable as an argument, adds one to it in place (so `my $a = 41; inc($a); say $a;` gives 42). What happens? Try using `is copy` and see how it changes (but does not fix) the problem. Then try out `is rw`. Next, make your word frequency filter take the list of blocked words as a named parameter. Also add a `threshold` named parameter (defaulted to zero), and don't return any words with frequencies below the threshold. !235

Slide 236

Slide 236 text

Classes, attributes, and methods (or, "Object-Oriented" programming)

Slide 237

Slide 237 text

–Alan Kay “I'm sorry that I long ago coined the term 'objects' for this topic because it gets many people to focus on the lesser idea. The big idea is 'messaging'…”

Slide 238

Slide 238 text

What are objects? Objects are autonomous components with internal state - which we aren't meant to care about from the outside. Instead, we communicate with an object entirely by sending it messages. In Raku parlance, as in many other languages, we call message sends "method calls". But we get better OO designs if we think of them as sending a message to some independent agent. !238

Slide 239

Slide 239 text

Declaring a class with attributes We'll build a simple score keeper for a game where players earn points. Write class to declare a class, and `has` to introduce state private to it. Note the `!` twigil means "this is private to the class". class ScoreKeeper { has %!player-points; } There are various other forms of attribute declaration, but the real name of an attribute is always:
 $!foo @!foo %!foo &!foo !239

Slide 240

Slide 240 text

Adding methods When players earn points, we want to add them. We also want a method to get the standings. Methods look very much like subs, except you declare them with method. method score($player, $points) { %!player-points{$player} += $points; } method ranking() { %!player-points.pairs.sort({ -.value }) } !240

Slide 241

Slide 241 text

BUILD Finally, we need to initialize all players to zero points. (Yes, Raku does have auto-vivification, but if we rely on that then our ranking will lack players who never earn points). We write a `submethod` (a method only callable directly on the class, not inherited) with the special name BUILD to do this: submethod BUILD(:@players) { for @players -> $player { %!player-points{$player} = 0; } } !241

Slide 242

Slide 242 text

Creating an instance We can now create a new instance by calling the new method, which we always inherit. Any named arguments we pass will make it to BUILD: my $game = ScoreKeeper.new(players => ); We can then use the object as follows: $game.score('jnthn', 100); $game.score('lizmat', 150); for $game.ranking -> $s { say "$s.key(): $s.value() points"; } !242

Slide 243

Slide 243 text

Try it and see! Write a `DaySchedule` class for scheduling hourly appointments.
 It should work as follows: my $sched = DaySchedule.new(opening => 9, closing => 17); $sched.add-appointment(10, 'Fred'); # Works fine $sched.add-appointment( 8, 'Brad'); # Dies: too early $sched.add-appointment(17, 'Anna'); # Dies: too late $sched.add-appointment( 9, 'Lena'); # Works fine $sched.add-appointment(10, 'Adam'); # Dies: conflict If you have free time, add a method that describes the schedule. !243

Slide 244

Slide 244 text

Roles A role is a collection of methods, and perhaps attributes, that can be incorporated into a class. Suppose we wanted to handle point-earning games like those we have so far, along with games where the winner is the first to reach a goal. We can get some re-use by factoring the scoring functionality out into a role. role Scoring { has %!player-points; method !zero-scores(@players) { for @players -> $player { %!player-points{$player} = 0; } } method score($player, $points) { … } method ranking() { … } } !244

Slide 245

Slide 245 text

Doing a role The `does` keyword is used to incorporate a role into a class. class SimpleScoreKeeper does Scoring { submethod BUILD(:@players) { self!zero-scores(@players); } } You can incorporate many roles into a class. Any *conflicts* - where two roles try to provide a method of the same name - will be identified at compile time. !245

Slide 246

Slide 246 text

Re-using Scoring Here's how we can implement the "first to meet the goal" score class. class FirstToGoalScoreKeeper does Scoring { has $!goal; submethod BUILD(:@players, :$!goal) { self!zero-scores(@players); } method winners() { %!player-points.grep({ .value >= $!goal }) .map({ .key }) } } !246

Slide 247

Slide 247 text

Going further

Slide 248

Slide 248 text

!248 • https://docs.raku.org/
 The primary source for Raku documentation. • https://examples.raku.org/
 Many examples, including RosettaCode language comparisons. • https://raku.org/resources/ and https://raku.org/
 Books, videos, blogs, guides for newcomers, a free course, and much more! Where to learn more

Slide 249

Slide 249 text

!249 • IRC: The channels #raku-beginner and #raku on irc.libera.org are a great places to get help. Many Raku contributors and users are there, and there is a friendly atmosphere (please help keep it that way!)
 • Discord: https://discord.gg/VzYpdQ6 , usually bridged to the IRC channels too!
 • Mailing list: the perl6-users list is great for questions are larger than one line, and answers can be more expansive. Consider subscribing just to see other people's questions, at https://raku.org/community/ Where to ask questions

Slide 250

Slide 250 text

Q & A ? (vs. Bonus Topic)

Slide 251

Slide 251 text

Bonus Topics Cool bits I skipped, that I can speak on easily

Slide 252

Slide 252 text

Bonus topics !252 Sequences Reduction Operators Hyper Operators Regex Complex Numbers Creating Operators List Comprehensions
 (ala Python, but better) Flip-flip Operator .pick, .roll, and rand Sorting Sets, Bags, and Mixes

Slide 253

Slide 253 text

Non-topics Each one worth ½ hour or more, so not today

Slide 254

Slide 254 text

Non-topics !254 Asynchrony
 Promises+Supplies+Channel s
 https://docs.raku.org/ language/concurrency Hyper, Race Grammars Meta Operators NativeCall Unicode AST

Slide 255

Slide 255 text

Thank you for coming!

Slide 256

Slide 256 text

Copyright Information: Images • Camelia • © 2009 by Larry Wall
 http://github.com/perl6/mu/raw/master/misc/camelia.txt • Periodic Table of the Operators • © 2004, 2009 by Mark Lentczner
 https://www.ozonehouse.com/mark/periodic/ • Zii and the Troublemakers • (In the style of Josie and the Pussycats)
 © by @GiseleLagace (art) and @shourimajo (color)
 http://www.ma3comic.com/strips-ma3/zii_and_the_troublemakers

Slide 257

Slide 257 text

LICENSE • The license has not yet been discussed (oops).
 Until I talk with Johnathan and Patrick, this talk is not licenced, with copyright shared between the three of us. If you don't see this slide replaced with something like CC-BY, you need permission from all three of us. Hope to resolve before the end of the conference.