Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge branch 'master' into spellcheck
  • Loading branch information
coke committed Oct 17, 2016
2 parents 302a0d4 + fd7d6ba commit 8fb6e69
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 7 deletions.
15 changes: 8 additions & 7 deletions doc/Language/operators.pod6
Expand Up @@ -1053,18 +1053,19 @@ operation.
=head2 infix C«x»
=begin code :skip-test
proto sub infix:<x>(Any, Any) returns Str:D
multi sub infix:<x>(Any, Any)
multi sub infix:<x>(Str:D, Int:D)
sub infix:<x>($a, $b) returns Str:D
=end code
X<String repetition operator>.
Coerces C<$a> to L<Str> and C<$b> to L<Int> and repeats the string C<$b>
times. Return the empty string if C<< $b <= 0 >>.
Repeats the string C<$a> C<$b> times, if necessary coercing C<$a> to L«C<Str>|/type/Str»
and C<$b> L«C<Int>|/type/Int». Returns an empty string if C<< $b <= 0 >>.
say 'ab' x 3; # ababab
say 42 x 3; # 424242
say 'ab' x 3; # ababab
say 42 x 3; # 424242
my $a = 'a'.IO; my $b = 3.5;
say $a x $b; # aaa
=head2 infix C«xx»
Expand Down
35 changes: 35 additions & 0 deletions doc/Language/traps.pod6
Expand Up @@ -471,6 +471,41 @@ Due to the variables allowed to be called anything, this can cause some problems
for 1..4 { say "$^one $^two $^three $^four"; } # 2 4 3 1
=head1 Scope
=head2 Using a C<once> block
The C<once> block is a block of code that will only run once when it's parent block is run. As an example:
my $var = 0;
for 1..10 {
once { $var++; }
}
say "Variable = $var"; # "Variable = 1"
This functionallity also applies to other code blocks like C<sub> and C<while>, not just C<for> loops. Problems arise though, when trying to nest C<once> blocks inside of other code blocks:
my $var = 0;
for 1..10 {
do { once { $var++; } }
}
say "Variable = $var"; # "Variable = 10"
In the above example, the C<once> block was nested inside of a code block which was inside of a C<for> loop code block. This causes the C<once> block to run multiple times, beacuse the C<once> block uses state variables to determine whether it has run previously. This means that if the parent code block goes out of scope, then the state variable the C<once> block uses to keep track of if it has run previously, goes out of scope as well. This is why C<once> blocks and C<state> variables can cause some unwanted behaviour when burried within more than one code block.
If you want to have something that will emulate the functionality of a once block, but still work when burried a few code blocks deep, we can manually build the functionality of a C<once> block. Using the above example, we can change it so that it will only run once, even when inside the C<do> block by changing the scope of the C<state> variable.
my $var = 0;
for 1..10 {
state $run-code = True;
do { if ($run-code) { $run-code = False; $var++; } }
}
say "Variable = $var"; # "Variable = 1"
In this example, we essentially manually build a C<once> block by making a C<state> variable called C<$run-code> at the highest level that will be run more than once, then checking to see if C<$run-code> is C<True> using a regular C<if>. If the variable C<$run-code> is C<True>, then make the variable C<False> and continue with the code that should only be completed once.
The main difference between using a C<state> variable like the above example and using a regular C<once> block is what scope the C<state> variable is in. The scope for the C<state> variable created by the C<once> block, is the same as where you put the block (imagine that the word 'C<once>' is replaced with a state variable and an C<if> to look at the variable). The example above using C<state> variables works because the variable is at the highest scope that will be repeated; whereas the example that has a C<once> block inside of a C<do>, made the variable within the C<do> block which is not the highest scope that is repeated.
=end pod

# vim: expandtab shiftwidth=4 ft=perl6

0 comments on commit 8fb6e69

Please sign in to comment.