Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update several documents #2930

Merged
merged 2 commits into from Aug 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
182 changes: 100 additions & 82 deletions doc/Language/101-basics.pod6
Expand Up @@ -4,7 +4,7 @@

=SUBTITLE A basic introductory example of a Perl 6 program

Suppose that you host a table tennis tournament. The referees tell you
Suppose that you host a table tennis tournament. The referees tell you
the results of each game in the format C<Player1 Player2 | 3:2>, which
means that C<Player1> won against C<Player2> by 3 to 2 sets. You need a
script that sums up how many matches and sets each player has won to
Expand All @@ -21,7 +21,7 @@ Dave Charlie | 3:0
Ana Charlie | 3:1
Beth Dave | 0:3

The first line is the list of players. Every subsequent line records a result
The first line is the list of players. Every subsequent line records a result
of a match.

Here's one way to solve that problem in Perl 6:
Expand Down Expand Up @@ -55,7 +55,9 @@ for $file.lines -> $line {
my @sorted = @names.sort({ %sets{$_} }).sort({ %matches{$_} }).reverse;

for @sorted -> $n {
say "$n has won %matches{$n} matches and %sets{$n} sets";
my $match-noun = %matches{$n} == 1 ?? 'match' !! 'matches';
my $set-noun = %sets{$n} == 1 ?? 'set' !! 'sets';
say "$n has won %matches{$n} $match-noun and %sets{$n} $set-noun";
}
=end code

Expand All @@ -64,15 +66,15 @@ This produces the output:
=for code :lang<text>
Ana has won 2 matches and 8 sets
Dave has won 2 matches and 6 sets
Charlie has won 1 matches and 4 sets
Beth has won 1 matches and 4 sets
Charlie has won 1 match and 4 sets
Beth has won 1 match and 4 sets

=head3 X<C<v6>|v6 (Basics)>

Every Perl 6 program should begin with a line similar to C<use v6;>. This line
tells the compiler which version of Perl the program expects. Should you
accidentally run the file with Perl 5, you'll get a helpful error message. 6.c
is an example of a Perl 6 version.
tells the compiler which version of Perl 6 the program expects. For instance,
6.c is an example of a Perl 6 version. Should you accidentally run the file
with Perl 5, you'll get a helpful error message.

=head3 X<C<statement>|statement (Basics)>

Expand All @@ -94,7 +96,7 @@ between curly braces C<{ }>.
=head3 X<C<sigil>> and X<C<identifier>|identifier (Basics)>

A variable name begins with a I<sigil>, which is a non-alpha-numeric
symbol such as C<$>, C<@>, C<%>, or C<&>--or occasionally the double
symbol such as C<$>, C<@>, C<%>, or C<&> E<mdash> or occasionally the double
colon C<::>. Sigils indicate the structural interface for the variable,
such as whether it should be treated as a single value, a compound value,
a subroutine, etc. After the sigil comes an I<identifier>, which may
Expand All @@ -115,10 +117,10 @@ values (as with an C<Array> or C<Hash>).

=head3 X<C<filehandle>> and X<C<assignment>>

The built-in function C<open> opens a file, here named C<scores>, and returns a
I<filehandle>--an object representing that file. The equality sign C<=>
I<assigns> that filehandle to the variable on the left, which means that
C<$file> now stores the filehandle.
The built-in function C<open> opens a file, here named C<scores.txt>,
and returns a I<filehandle> E<mdash> an object representing that file. The
equality sign C<=> I<assigns> that filehandle to the variable on the left,
which means that C<$file> now stores the filehandle.

=head3 X<C<string literal>>

Expand All @@ -132,18 +134,19 @@ my @names = $file.get.words;

=head3 X<C<array>>, X<C<method>|method (Basics)> and X<C<invocant>|invocant (Basics)>

The right-hand side calls a I<method> --a named group of behavior-- named C<get>
on the filehandle stored in C<$file>. The C<get> method reads and returns
one line from the file, removing the line ending. If you print the contents of C<$file>
after calling C<get>, you will see that the first line is no longer in there. C<words> is also a method,
called on the string returned from C<get>. C<words> decomposes its
I<invocant>--the string on which it operates--into a list of words, which
here means strings separated by whitespace.
It turns the single string C<'Beth Ana Charlie Dave'> into the list of
strings C<'Beth', 'Ana', 'Charlie', 'Dave'>.
The right-hand side calls a I<method> E<mdash> a named group of
behavior E<mdash> named C<get> on the filehandle stored in C<$file>. The C<get>
method reads and returns one line from the file, removing the line ending. If
you print the contents of C<$file> after calling C<get>, you will see that the
first line is no longer in there. C<words> is also a method, called on the
string returned from C<get>. C<words> decomposes its I<invocant> E<mdash>
the string on which it operates E<mdash> into a list of words, which here means
strings separated by whitespace. It turns the single string C<'Beth Ana Charlie
Dave'> into the list of strings C<'Beth', 'Ana', 'Charlie', 'Dave'>.

Finally, this list gets stored in the L<Array|/type/Array> C<@names>. The C<@> sigil marks
the declared variable as an C<Array>. Arrays store ordered lists.
Finally, this list gets stored in the L<Array|/type/Array> C<@names>.
The C<@> sigil marks the declared variable as an C<Array>.
Arrays store ordered lists.

=begin code
my %matches;
Expand All @@ -152,14 +155,14 @@ my %sets;

=head3 X<C<hash>>

These two lines of code declare two hashes. The C<%> sigil marks each variable
as a C<Hash>. A C<Hash> is an unordered collection of key-value pairs. Other
programming languages call that a I<hash table>, I<dictionary>, or I<map>. You
can query a hash table for the value that corresponds to a certain C<$key> with
C<%hash{$key}>.
These two lines of code declare two hashes. The C<%> sigil marks each variable
as a C<Hash>. A C<Hash> is an unordered collection of key-value pairs. Other
programming languages call that a I<hash table>, I<dictionary>, or I<map>.
You can query a hash table for the value that corresponds to a certain
C<$key> with C<%hash{$key}>.

In the score counting program, C<%matches> stores the number of matches each
player has won. C<%sets> stores the number of sets each player has won. Both
player has won. C<%sets> stores the number of sets each player has won. Both
of these hashes are indexed by the player's name.

=begin code :preamble<my $file>
Expand All @@ -172,9 +175,10 @@ for $file.lines -> $line {

C<for> produces a loop that runs the I<block> delimited by curly braces
once for each item of the list, setting the variable C<$line>
to the current value of each iteration. C<$file.lines> produces a list of the
lines read from the file C<scores.txt>, starting with the second line of the file
since we already called C<$file.get> once, and going all the way to the end of the file.
to the current value of each iteration. C<$file.lines> produces a list of
the lines read from the file C<scores.txt>, starting with the second line
of the file since we already called C<$file.get> once, and going all the way
to the end of the file.

During the first iteration, C<$line> will contain the string C<Ana Dave |
3:0>; during the second, C<Charlie Beth | 3:1>, and so on.
Expand All @@ -187,15 +191,13 @@ C<my> can declare multiple variables simultaneously. The right-hand side of the
assignment is a call to a method named C<split>, passing along the string
C<' | '> as an argument.

C<split> decomposes its invocant into a
list of strings, so that joining the list items with the separator C<' | '>
produces the original string.
C<split> decomposes its invocant into a list of strings, so that joining the
list items with the separator C<' | '> produces the original string.

C<$pairing> gets the first item of the returned list, and
C<$result> the second.
C<$pairing> gets the first item of the returned list, and C<$result> the second.

After processing the first line, C<$pairing> will hold the string C<Ana Dave>
and C<$result> C<3:0>.
and C<$result> will hold C<3:0>.

The next two lines follow the same pattern:

Expand All @@ -205,11 +207,10 @@ my ($r1, $r2) = $result.split(':');
=end code

The first extracts and stores the names of the two players in the variables
C<$p1> and C<$p2>. The second extracts the results for each player and stores
C<$p1> and C<$p2>. The second extracts the results for each player and stores
them in C<$r1> and C<$r2>.

After processing the first line of the file, the variables contain the values:
cell C<'0'>
=begin table
Variable Contents
$line 'Ana Dave \| 3:0'
Expand Down Expand Up @@ -238,19 +239,20 @@ The C<+=> assignment operator is a shortcut for:

=head3 X<C<Any>| Any (Basics)> and X<C<+=>>

C<+= $r1> means I<increase the value in the variable on the left by $r1>. In
C<+= $r1> means I<increase the value in the variable on the left by $r1>. In
the first iteration C<%sets{$p1}> is not yet set, so it defaults to a special
value called C<Any>. The addition and incrementing operators treat C<Any> as a
number with the value of zero; the strings get automatically converted to
numbers, as addition is a numeric operation.

=head3 X<C<fat arrow>>, X<C<pair>> and X<C<autovivification>>

Before these two lines execute, C<%sets> is empty. Adding to an entry that is not in
the hash yet will cause that entry to spring into existence just-in-time, with a
value starting at zero. (This is I<autovivification>). After these two lines
have run for the first time, C<%sets> contains C<< 'Ana' => 3, 'Dave' => 0 >>.
(The fat arrow C<< => >> separates key and value in a C<Pair>.)
Before these two lines execute, C<%sets> is empty. Adding to an entry that is
not in the hash yet will cause that entry to spring into existence
just-in-time, with a value starting at zero. (This is I<autovivification>).
After these two lines have run for the first time, C<%sets> contains C<< 'Ana'
=> 3, 'Dave' => 0 >>. (The fat arrow C<< => >> separates the key and the value
in a C<Pair>.)

=begin code :preamble<my $r1;my $r2;my $p1;my $p2;my %matches;>
if $r1 > $r2 {
Expand Down Expand Up @@ -280,17 +282,17 @@ my @sorted = @names.sort({ %sets{$_} }).sort({ %matches{$_} }).reverse;
=head3 X<C<variables, $_>>

This line consists of three individually simple steps. An array's C<sort>
method returns a sorted version of the array's contents. However, the default
sort on an array sorts by its contents. To print player names in winner-first
method returns a sorted version of the array's contents. However, the default
sort on an array sorts by its contents. To print player names in winner-first
order, the code must sort the array by the I<scores> of the players, not their
names. The C<sort> method's argument is a I<block> used to transform the array
elements (the names of players) to the data by which to sort. The array items
names. The C<sort> method's argument is a I<block> used to transform the array
elements (the names of players) to the data by which to sort. The array items
are passed in through the I<topic variable> C<$_>.

=head3 X<C<block>|block (Basics)>

You have seen blocks before: both the C<for> loop C<< -> $line { ... } >> and
the C<if> statement worked on blocks. A block is a self-contained piece of
the C<if> statement worked on blocks. A block is a self-contained piece of
Perl 6 code with an optional signature (the C<< -> $line >> part).

The simplest way to sort the players by score would be C<@names.sort({
Expand All @@ -302,46 +304,56 @@ tournament.
=head3 X<C<stable sort>>

When two array items have the same value, C<sort> leaves them in the same order
as it found them. Computer scientists call this a I<stable sort>. The program
as it found them. Computer scientists call this a I<stable sort>. The program
takes advantage of this property of Perl 6's C<sort> to achieve the goal by
sorting twice: first by the number of sets won (the secondary criterion), then
by the number of matches won.

After the first sorting step, the names are in the order C<Beth Charlie Dave
Ana>. After the second sorting step, it's still the same, because no one has
Ana>. After the second sorting step, it's still the same, because no one has
won fewer matches but more sets than someone else. Such a situation is entirely
possible, especially at larger tournaments.

C<sort> sorts in ascending order, from smallest to largest. This is the
C<sort> sorts in ascending order, from smallest to largest. This is the
opposite of the desired order. Therefore, the code calls the C<.reverse> method
on the result of the second sort, and stores the final list in C<@sorted>.

=begin code :preamble<my @sorted;my %matches;my %sets>
for @sorted -> $n {
say "$n has won %matches{$n} matches and %sets{$n} sets";
my $match-noun = %matches{$n} == 1 ?? 'match' !! 'matches';
my $set-noun = %sets{$n} == 1 ?? 'set' !! 'sets';
say "$n has won %matches{$n} $match-noun and %sets{$n} $set-noun";
}
=end code

=head3 X<C<say>| say (Basics)>, X<C<print>| say (Basics)> and X<C<put>|put (Basics)>

To print out the players and their scores, the code loops over C<@sorted>,
setting C<$n> to the name of each player in turn. Read this code as "For each
setting C<$n> to the name of each player in turn. Read this code as "For each
element of sorted, set C<$n> to the element, then execute the contents of the
following block." C<say> prints its arguments to the standard output (the
screen, normally), followed by a newline. (Use C<print> if you don't want the
newline at the end.)
following block." The variable C<$match-noun> will store either the string
I<match> if the player has won a single match or I<matches> if the player
has won zero or more matches. In order to do this, the I<ternary>
operator (C<?? !!>) is used. If C<%matches{$n} == 1> evaluates to C<True>,
then I<match> is returned. Otherwise, I<matches> is returned. Either way,
the returned value is stored in C<$match-noun>. The same approach applies
to <$set-noun>.

The statement C<say> prints its arguments to the standard output
(the screen, normally), followed by a newline. (Use C<print> if you don't
want the newline at the end.)

Note that C<say> will truncate certain data structures by calling the C<.gist>
method so C<put> is safer if you want exact output.

=head3 X<C<interpolation>>

When you run the program, you'll see that C<say> doesn't print the contents of
that string verbatim. In place of C<$n> it prints the contents of the variable
C<$n>-- the names of players stored in C<$n>. This automatic substitution of
code with its contents is I<interpolation>. This interpolation happens only in
strings delimited by double quotes C<"...">. Single quoted strings C<'...'> do
not interpolate:
that string verbatim. In place of C<$n> it prints the contents of the variable
C<$n> E<mdash> the names of players stored in C<$n>. This automatic substitution
of code with its contents is I<interpolation>. This interpolation happens only
in strings delimited by double quotes C<"...">. Single quoted strings C<'...'>
do not interpolate:

=head3 X<C<double-quoted strings>> and X<C<single-quoted strings>>

Expand All @@ -358,33 +370,38 @@ interpolated by placing them within curly braces.

Arrays within curly braces are interpolated with a single space character
between each item. Hashes within curly braces are interpolated as a series of
lines. Each line will contain a key, followed by a tab character, then the value
associated with that key, and finally a newline.
lines. Each line will contain a key, followed by a tab character, then the
value associated with that key, and finally a newline.

Let's see an example of this now.

In this example, you will see some special syntax that makes it easier
to make a list of strings. This is the C<< <...> >> L<quote-words|/language/operators#index-entry-qw-quote-words-quote-words> construct.
When you put words in between the < and > they are all assumed to be strings,
so you do not need to wrap them each in double quotes C<< "..." >>.
to make a list of strings. This is the
C«<...>» L<quote-words|/language/operators#index-entry-qw-quote-words-quote-words>
construct. When you put words in between the < and > they are all assumed
to be strings, so you do not need to wrap them each in double quotes
C«"..."».

=begin code :preamble<my %sets>
say "Math: { 1 + 2 }"; # OUTPUT: «Math: 3␤»
say "Math: { 1 + 2 }";
# OUTPUT: «Math: 3␤»

my @people = <Luke Matthew Mark>;
say "The synoptics are: {@people}"; # OUTPUT: «The synoptics are: Luke Matthew Mark␤»
say "The synoptics are: {@people}";
# OUTPUT: «The synoptics are: Luke Matthew Mark␤»

say "{%sets}␤"; # From the table tennis tournament
say "{%sets}␤";
# OUTPUT (From the table tennis tournament):

# Charlie 4
# Dave 6
# Ana 8
# Beth 4
=end code


When array and hash variables appear directly in a double-quoted string (and
not inside curly braces), they are only interpolated if their name is
followed by a postcircumfix -- a bracketing pair that follows a
followed by a postcircumfix E<mdash> a bracketing pair that follows a
statement. It's also ok to have a method call between the variable name and
the postcircumfix.

Expand All @@ -403,7 +420,7 @@ say "we have @flavors.sort()"; # OUTPUT: «we have peach vanilla␤»

# chained method calls:
say "we have @flavors.sort.join(', ')";
# OUTPUT: «we have peach, vanilla␤»
# OUTPUT: «we have peach, vanilla␤»
=end code


Expand All @@ -429,15 +446,16 @@ my @sorted = @names.sort({ %sets{$_} }).sort({ %matches{$_} }).reverse;
my @sorted = %sets.keys.sort({ %sets{$_} }).sort({ %matches{$_} }).reverse;
=end code

B<2.> Instead of deleting the redundant C<@names> variable, you can also use it to warn if a
player appears that wasn't mentioned in the first line, for example due to a
typo. How would you modify your program to achieve that?
B<2.> Instead of deleting the redundant C<@names> variable, you can also use it
to warn if a player appears that wasn't mentioned in the first line, for
example due to a typo. How would you modify your program to achieve that?

Hint: Try using L<membership operators|/language/operators#infix_(elem),_infix_∈>.

B<Answer:> Change C<@names> to C<@valid-players>. When looping through the lines of
the file, check to see that C<$p1> and C<$p2> are in C<@valid-players>. Note that
for membership operators you can also use C<(elem)> and C<!(elem)>.
B<Answer:> Change C<@names> to C<@valid-players>. When looping through the
lines of the file, check to see that C<$p1> and C<$p2> are in
C<@valid-players>. Note that for membership operators you can also use C<(elem)>
and C<!(elem)>.

=begin code :preamble<my $file>
...;
Expand Down