Raku By Example
View me onGitHub
## Lists and Arrays
#------------------

# Lists and arrays are collections of items. However lists and arrays differ 
# in that lists are ordered and inmutable collections of items while arrays 
# are mutables. Furthermore, lists are sort of ephemeral since they cease to
# exist as soon as they been used while arrays tend to persist throughout the
# program.

# Create a list by enumerating its values, separated by commas. Optionally
# enclose them in parentheses for delimitation. In the REPL:

#> 2, 3, 5
#(2 3 5)
#> (2, 3, 5) # same as before
#(2 3 5)
#> for 2, 3, 5 { print $_ }
#235

# To create an array, assign a collections of items to a variable prefixed with
# the sigil @. All the following accomplish the same thing, that is, creating
# an array:

my @bin-numerals = 0, 1;
my @dec-numerals = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
my @vowels = <a e i o v>; # use <> for items without spaces in them

# Arrays/lists are 0-indexed and items are accessed/updated by using the
# square bracket operator `[...]`:
say @bin-numerals[0]; # 0 
say @bin-numerals[1]; # 1
say @vowels[0];       # 'a'
say @vowels[4];       # 'v'. Oops, not a vowel!
@vowels[4] = 'u';     # assignment 
say @vowels[4];       # 'u'. This is the right vowel!

# Arrays can host values of different types:
my @mix-array = 'A', 12, 1E2;

# Or you can constraint their type so as to accept only a specific type:
my Int @only-integers = 1, 2, 3;

# Arrays can have fixed sizes. Specify it inside the square bracket during 
# declaration/initialization:
my @earth-moons[1];  # accepts only one element
@earth-moons[0] = 'The Moon';

my @mars-moons[2] = <Rhobos Deimos>;

# Arrays/lists can be nested:
my @nested-array = (1, 2, 3), ('a', 'b', 'c');
for @nested-array { say $_ }; # (1, 2, 3) (a b c) 

# Besides one-dimensional, arrays can be multidimensional (matrices). What would
# be columns are separated by ; inside of what would be rows:
my @students = ['Bob'; 75], ['Alice'; 80], ['Era'; 93];
say @students[0];     # [Bob 75]
say @students[0][0];  # 'Bob'
say @students[0][1];  # 75
say @students[2][0];  # 'Era'
say @students[2][1];  # 93

## Some methods
##-------------

my @planets = 'Earth';

# `elems` - counts the number of items of an array/list:
say @planets.elems; # 1
say elems @planets; # 1

# `push` - adds a new item to the end of the array.
@planets.push('Mars');
push @planets, 'Mars'; # same thing

# `pop` - removes an item from the end and return it.
@planets.pop;
pop @planets; # same thing

# `append` - add new item(s) to the end of the array.
@planets.append(<Mars Jupiter>);
append @planets, ('Saturn', 'Uranus', 'Neptune'); # similar thing

my @d =  ( [ 1 .. 3 ] );
@d.append( [ 4 .. 6 ] );
@d.append( [ 7 .. 9 ] );

for @d -> $item {
    say "$item[]";
}
@d.perl.say;

# 1
# 2
# 3
# 4
# 5
# 6
# 7
# 8
# 9
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

# 'unshift` - adds a new item to the beginning of the array.
@planets.unshift('Venus');
unshift @planets, 'Venus'; # same thing

# `shift` - removes an item from the beginning of the array and returns it.
@planets.shift;
shift @planets; # same thing

# `prepend` - add new item(s) to the beginning of the array.
@planets.prepend('Venus');
prepend @planets, 'Mercury';  # similar thing

# `head` - returns first n numbers of items from an array
say @planets.head;    # (Mercury)
say @planets.head(2); # (Mercury Venus)

# `tail` - returns last n numbers of items from an array
say @planets.tail;    # (Neptune)
say @planets.tail(2); # (Uranus Neptune)

## List comprehensions
##--------------------

my @numbers = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10;

# Statement modifiers and blocks can be combined to create list comprehensions.
my @squares = ($_ ** 2 for @numbers);

# Conditionals can be applied too.
my @squared-primes = ($_ ** 2 if $_.is-prime for @numbers);

# Nested comprehensions can be achieved in different ways. This one uses the 
# cross product operator `X`:
my @letters-nums = ([$_[0], $_[1]] for <A B> X <1 2>); # ([A 1] [A 2] [B 1] [B 2])

# To get an one-to-correspondence, use the zip operator `Z`:
my @oto-letters-nums = ([$_[0], $_[1]] for <A B> Z <1 2>); # ([A 1] [B 2])

## array methods
my @rray=17,21,34,47,58,69;

say 'the array has element' if  ? @rray;   # boolean context, Bool::True if array has any value in it, even if its a 0
say 'the array has ',+ @rray ~' element';  # numeric context, number of elements (like in Perl 5 scalar @a)
say ~ @rray;              # string context, you get content of all cells, stringified and joined, same as "@primes[]"

say @rray.elems;          # same as + @rray
say @rray.end;            # number of the last element, equal to @rray.elems-1, # 5
# say @rray.cat;          # same ~ @rray
say @rray.join('-');      # also same result, you can put another string as parameter that gets between all values
say @rray.unshift(7);     # prepend one value to the array, # 7 1 2 3 4 5 6
say @rray.shift;          # remove the first value and return it # 7
say @rray.push(8);        # add one value on the end # 1 2 3 4 5 6 8
say @rray.pop;            # remove one value from the end and return it # 8

my $n=2;
my $pos=1;
my @ind=0..3;
say @rray.splice($pos,$n);# remove on $pos $n values and replace them with values that follow that two parameter
say @rray:delete(@ind);   # delete all cell with indecies of @ind # 1 4 5 6
say @rray:exists(@ind);   # Bool::True if all indecies of @ind have a value (can be 0 or '')

say '-' x 18;
say @rray;
say @rray.pick([$n]);     # return $n (default is 1) randomly selected values, without duplication
say @rray.roll([$n]);     # return $n (default is 1) randomly selected values, duplication possible (就像掷筛子)
say @rray.reverse;        # all elements in reversed order
say @rray.rotate(-$n);    # returns a list where $n times first item is taken to last position if $n is positive, if negative the other way around
# @rray.sort($coderef); # returns a sorted list by a userdefined criteria, default is alphanumerical sorting
say @rray.min;            # numerical smallest value of that array
say @rray.max;            # numerical largest value of that array
my ($a,$b)= @rray.minmax;  # both at once, like in .sort . min or .max a sorting algorith can be provided
say $a,"   $b";
# @rray.map($coderef);  # high oder map function, runs $coderef with every value as $_ and returns the list or results
# @rray.classify($cr);  # kind of map, but creates a hash, where keys are the results of $cr and values are from @rray
# @rray.categorize($cr);# kind of classify, but closure can have no (Nil) or several results, so a key can have a list of values
say @rray.grep({$_>40});   # high order grep, returns only these elements that pass a condition ($cr returns something positive)
# @rray.first($coder);  # kind of grep, return just the first matching value
# say @rray.zip;            # join arrays by picking first element left successively from here and then there


my @primes = (2,3,5,7,11,13,17,19,23);   # an array gets filled like in Perl 5
# my @primes =  2,3,5,7,11,13,17,19,23 ; # same thing, since unlike P5 round braces just do group
# my @primes = <2 3 5 7 11 13 17 19 23>; # dito, <> is the new qw()

say @primes[];                           # 2 3 5 7 11 13 17 19 23
my $arrayref = [2,3,5,7,11,13,17,19,23]; # in scalar context you get automatically a reference
say @$arrayref;                          # 2 3 5 7 11 13 17 19 23

my $arrayref = item @primes;             # same thing, more explicit
say $arrayref;

my $arrayref = [13,];                    # comma is the new array generator
say $arrayref;

my @primes = 2;                          # array with one element
my @primes = [2,3,5,7,11,13,17,19,23];   # array with one element (arrayref)
say @primes;                             # 2 3 5 7 11 13 17 19 23

my @dev    = {'dan' => 'parrot'};        # array with one element (hashref)
say @dev;                                # ("dan" => "parrot").hash


my @data   = [1..5],[6..10],[11..15];    # Array of Arrays (AoA)
say @data.perl;                          # Array.new([1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15])

# my @list   = lol @data;                # no change
# say @list.perl;
my @list   = flat @data;                 # returns 1..15
say @list;

## index array

my @weekdays = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
@weekdays.kv.reverse.hash.{'Thursday'} # 3

my @a = $=finish.lines.words;

for @a.kv -> $key, $value {
    say $value if $value >= 20;
}

=finish
20 12 34
12 34 56
34 55 78

## loop three elements

my @a=<aa bb cc dd ee ff >;

for @a -> $x,$y,$z {
    say $x,$y,$z;
}

# aabbcc
# ddeeff

my  @primes=<1 3 5 7 9 11 13 15 17>;
say @primes;                       # all values as list
say @primes.values;                # same thing
say @primes.keys;                  # list of all indices
say "@primes[]";                   # insert all values in a string, uses [] as distinction from mail adresses
my  $prime = @primes[0];           # get the first prime
say $prime;

my $last_prime = @primes[*-1];    # get the last one
say $last_prime;

my @some = @primes[2..5];         # get several
say @some;

my @data   = [1..5],[6..10],[11..15];  # Array of Arrays (AoA)
my $cell = @data[1][2];                # get 8, third value of second value (list)
say $cell;

my  $same_cell = @data[1,2];           # same thing, shorten syntax
say $same_cell;                        # 6 7 8 9 10 11 12 13 14 15

my @numbers = @data[1];                # get a copy of the second subarray (6..10)
say @numbers;
my @copy = @data;                      # copy the whole AoA, no more reference passing, use binding instead
say @copy.perl;


## squish
.say for $=finish.lines.squish;

=finish
123
123
321
321
111
111
111

# comments inline
my @a = (
    1, #`(Index 1) 2, #`(Index 2) "Info",
    2, #`(Index 2) 3, #`(Index 3) "Text",
    3, #`(Index 3) 4, #`(Index 4) "Advb",
    4, #`(Index 4) 5, #`(Index 5) "Ling"
  );

.say for @a;