Skip to content

Commit

Permalink
Minor corrections to the data structure doc
Browse files Browse the repository at this point in the history
Added the newline character to the output of the code examples
where the statement 'say' was used. Also fixed some
minor typos and changed some wording.
  • Loading branch information
uzluisf committed May 29, 2018
1 parent 9afe5ee commit ed55bff
Showing 1 changed file with 44 additions and 44 deletions.
88 changes: 44 additions & 44 deletions doc/Language/structures.pod6
Expand Up @@ -6,8 +6,8 @@
=head1 Scalar structures
Some classes do not have any I<internal> structure, and to access parts
of them specific methods have to be used. Numbers, strings, and some
Some classes do not have any I<internal> structure and to access parts
of them, specific methods have to be used. Numbers, strings, and some
other monolithic classes are included in that class. They use the C<$>
sigil, although complex data structures can also use it.
Expand All @@ -34,7 +34,7 @@ An interesting side effect, or maybe intended feature, is that scalarization
conserves identity of complex structures.
for ^2 {
my @list =(1,1);
my @list = (1,1);
say @list.WHICH;
} # OUTPUT: «Array|93947995146096␤Array|93947995700032␤»
Expand All @@ -43,20 +43,20 @@ in the sense that C<===> will say it is; as it is shown, different values of the
internal pointer representation are printed. However
for ^2 {
my $list =(1,1);
my $list = (1,1);
say $list.WHICH
} # OUTPUT: «List|94674814008432␤List|94674814008432␤»
} # OUTPUT: «List|94674814008432␤List|94674814008432␤»
In this case, C<$list> is using the Scalar sigil and thus will be an C<Scalar>. Any scalar will the same value will be exactly the same, as shown when printing the pointers.
In this case, C<$list> is using the Scalar sigil and thus will be a C<Scalar>. Any scalar with the same value will be exactly the same, as shown when printing the pointers.
=head1 Complex data structures
Complex data structures fall in two different broad categories
Complex data structures fall in two different broad categories:
L<Positional|/type/Positional>, or list-like and
L<Associative|/type/Associative>, or key-value pair like, according to how you
access its first-level elements. In general, complex data structures, including
objects, will be a combination of both, with object properties assimilated to
key-value pairs. While all objects subclass L<Mu>, in general complex objects are instances of subclasses of L<Any>. While it is theoretically possible to mix in C<Positional> or C<Associative> without doing so, most methods who apply to complex data structures are implemented in C<Any>.
key-value pairs. While all objects subclass L<Mu>, in general complex objects are instances of subclasses of L<Any>. While it is theoretically possible to mix in C<Positional> or C<Associative> without doing so, most methods applicable to complex data structures are implemented in C<Any>.
Navigating these complex data structures is a challenge, but Perl 6 provides a couple of functions that can be used on them: L<C<deepmap>|/routine/deepmap> and L<C<duckmap>|/routine/duckmap>. While the former will go to every single element, in order, and do whatever the block passed requires,
Expand All @@ -67,7 +67,7 @@ which returns 1 because it goes to the deeper level and applies C<elems> to
them, C<deepmap> can perform more complicated operations:
say [[1,2,[3,4]],[[5,6,[7,8]]]].duckmap:
-> $array where .elems == 2 { $array.elems }
-> $array where .elems == 2 { $array.elems };
# OUTPUT: «[[1 2 2] [5 6 2]]␤»
In this case, it dives into the structure, but returns the element itself if it
Expand All @@ -76,17 +76,18 @@ elements of the array if it does (the two C<2>s at the end of each subarray).
Since C<d(eep|uck)map> are C<Any> methods, they also apply to Associative arrays:
say %( first => [1,2], second => [3,4]).deepmap( *.elems )
say %( first => [1,2], second => [3,4] ).deepmap( *.elems );
# OUTPUT: «{first => [1 1], second => [1 1]}␤»
Only in this case, they will be applied to every list or array that is a value, leaving the keys alone.
C<Positional> and C<Associative> can be turned into each other.
say %( first => [1,2], second => [3,4]).list[0]# OUTPUT: «second => [3 4]␤»
say %( first => [1,2], second => [3,4] ).list[0];
# OUTPUT: «second => [3 4]␤»
However, in this case, and for Rakudo >= 2018.05, it will return a different
value every time you run. A hash will be turned into a list of the key-value
value every time it runs. A hash will be turned into a list of the key-value
pairs, but it is guaranteed to be disordered. You can also do the operation in
the opposite direction, as long as the list has an even number of elements (odd
number will result in an error):
Expand All @@ -104,7 +105,7 @@ Complex data structures are also L<Iterable>. Generating an L<iterator> out of
them will allow the program to visit the first level of the structure, one by
one:
.say for 'א'..'ס' # OUTPUT: «א␤ב␤ג␤ד␤ה␤ו␤ז␤ח␤ט␤י␤ך␤כ␤ל␤ם␤מ␤ן␤נ␤ס␤»
.say for 'א'..'ס'; # OUTPUT: «א␤ב␤ג␤ד␤ה␤ו␤ז␤ח␤ט␤י␤ך␤כ␤ל␤ם␤מ␤ן␤נ␤ס␤»
C<'א'..'ס'> is a L<Range>, a complex data structure, and with C<for> in front it
will iterate until the list is exhausted. You can use C<for> on your complex
Expand All @@ -130,11 +131,11 @@ in most cases it is elided for the sake of simplicity; this sigil elimination is
always allowed in the case of C<Callables>.
my &a-func= { (^($^þ)).Seq };
say a-func(3), a-func(7)# OUTPUT: «(0 1 2)(0 1 2 3 4 5 6)␤»
say a-func(3), a-func(7); # OUTPUT: «(0 1 2)(0 1 2 3 4 5 6)␤»
L<Block>s are the simplest callable structures, since C<Callable>s cannot be
instantiated. In this case we implement a block that logs events and can
retrieve them
retrieve them:
my $logger = -> $event, $key = Nil {
state %store;
Expand All @@ -145,38 +146,37 @@ retrieve them
}
}
$logger( "Stuff" );
$logger( "More stuff");
say $logger( Nil, "2018-05-28"); # OUTPUT: «(Stuff More stuff)»
»
$logger( "More stuff" );
say $logger( Nil, "2018-05-28" ); # OUTPUT: «(Stuff More stuff)␤»
A C<Block> has a L<Signature>, in this case two arguments, the first of
which is the event that is going ot be logged, and the second is the key
which is the event that is going to be logged, and the second is the key
to retrieve the events. They will be used in an independent way, but its
intention is to showcase the use of a L<state variable|/syntax/state>
that is kept from every invocation to the next. This state variable is
encapsulated within the block, and cannot be accessed from outside
except by using the simple API the block provides: calling the block
with a second argument. The two first invocations log two events, the
third invocation at the bottom of the example use this second type of
call to retrieve the stored values. C<Block>s can be cloned
call to retrieve the stored values. C<Block>s can be cloned:
=begin code :preamble<my $logger = sub ( $a, $b ){ return $a, $b }>
=begin code :preamble<my $logger = sub ( $a, $b ){ return $a, $b }>
my $clogger = $logger.clone;
$clogger( "Clone stuff" );
$clogger( "More clone stuff");
say $clogger( Nil, "2018-05-28");
# OUTPUT: «(Clone stuff More clone stuff)»
$clogger( "More clone stuff" );
say $clogger( Nil, "2018-05-28" );
# OUTPUT: «(Clone stuff More clone stuff)»
=end code
And cloning will reset the state variable; instead of cloning, we can create
I<façades> that change the API. For instance, eliminate the need to use C<Nil>
as first argument to retrieve the log for a certain date:
=begin code :preamble<my $logger = sub ( $a, $b ){ return $a, $b }>
=begin code :preamble<my $logger = sub ( $a, $b ){ return $a, $b }>
my $gets-logs = $logger.assuming( Nil, * );
$logger( %(changing => "Logs") );
say $gets-logs( "2018-05-28" );
# OUTPUT: «({changing => Logs} Stuff More stuff)»
# OUTPUT: «({changing => Logs} Stuff More stuff)»
=end code
L<C<assuming>|/type/Block#(Code)_method_assuming> wraps around a block
Expand All @@ -187,13 +187,13 @@ are calling C<$logger> I<assuming> the first argument is C<Nil>". We can
slightly change the appearance of these two Blocks to clarify they are
actually acting on the same block:
=begin code :preamble<my $logger = sub ( $a, $b ){ return $a, $b }>
=begin code :preamble<my $logger = sub ( $a, $b ){ return $a, $b }>
my $Logger = $logger.clone;
my $Logger::logs = $Logger.assuming( *, Nil );
my $Logger::get = $Logger.assuming( Nil, * );
$Logger::logs( <an array> );
$Logger::logs( %(key => 42 ) );
say $Logger::get( "2018-05-28");
$Logger::logs( %(key => 42) );
say $Logger::get( "2018-05-28" );
=end code
Although C<::> is generally used for invocation of class methods, it is
Expand All @@ -213,7 +213,7 @@ As such first class data structures, callables can be used anywhere another type
Regexes are actually a type of callable:
say /regex/.does( Callable );#OUTPUT: «True␤»
say /regex/.does( Callable ); # OUTPUT: «True␤»
And in the example above we are calling regexes stored in an array, and
applying them to a string literal.
Expand All @@ -223,14 +223,14 @@ Callables are composed by using the L<function composition operator ∘|/languag
=begin code :preamble<my $Logger::logs = sub ( $a ) { $a }>
my $typer = -> $thing { $thing.^name ~ ' → ' ~ $thing };
my $Logger::withtype = $Logger::logs ∘ $typer;
$Logger::withtype( Pair.new( 'left', 'right' ));
$Logger::withtype( Pair.new( 'left', 'right' ) );
$Logger::withtype( ¾ );
say $Logger::get( "2018-05-28" );
# OUTPUT: «(Pair → left right Rat → 0.75)»
# OUTPUT: «(Pair → left right Rat → 0.75)»
=end code
We are composing C<$typer> with the C<$Logger::logs> function defined
above, obtaining a function that logs an object prececed by its type,
above, obtaining a function that logs an object preceded by ts type,
which can be useful for filtering, for instance. C<$Logger::withtype>
is, in fact, a complex data structure composed of two functions which
are applied in a serial way, but every one of the callables composed can
Expand All @@ -248,10 +248,10 @@ mixes roles or values into a value or a variable:
=begin code
my %not-scalar := %(2 => 3) but Associative[Int,Int];
say %not-scalar.^name; # OUTPUT: «Hash+{Associative[Int,Int]}␤»
say %not-scalar.of; # Associative[Int,Int]»
%not-scalar{3}=4;
%not-scalar<thing>=3;
say %not-scalar; # OUTPUT: «{2 => 3, 3 => 4, thing => 3}␤»
say %not-scalar.of; # OUTPUT: «Associative[Int,Int]»
%not-scalar{3} = 4;
%not-scalar<thing> = 3;
say %not-scalar; # OUTPUT: «{2 => 3, 3 => 4, thing => 3}␤»
=end code
In this case, C<but> is mixing in the C<Associative[Int,Int]> role;
Expand All @@ -275,8 +275,8 @@ role Lastable {
}
}
my %hash-plus := %( 3 => 33, 4 => 44) but Lastable;
say %hash-plus.sort[0]; # OUTPUT: «3 => 33»
say %hash-plus.last; # OUTPUT: «4 => 44»
say %hash-plus.sort[0]; # OUTPUT: «3 => 33»
say %hash-plus.last; # OUTPUT: «4 => 44»
=end code
In C<Lastable> we use the universal C<self> variable to refer to
Expand All @@ -303,7 +303,7 @@ say $one-fraction; # OUTPUT: «0.333333␤»
On the other hand, C<my OneOver $ = ⅔;> will cause a type-check error.
Subsets can use C<Whatever>, that is, C<*>, to refer to the argument;
but this will be instantiated every time you use it to a different
argument, so if we used it twice in the definition we would get an
argument, so if we use it twice in the definition we would get an
error. In this case we are using the topic single variable, C<$_>, to
check the instantiation. Subsetting can be done directly, without the
need of declaring it, in L<signatures|/language/typesystem#subset>.
Expand Down Expand Up @@ -420,7 +420,7 @@ mentioned above:
=for code
my $fh = "/tmp/bar".IO.open;
my $lines = $fh.lines;
say "Read $lines.elems() lines"; #reifying before closing handle
say "Read $lines.elems() lines"; # reifying before closing handle
close $fh;
say $lines[0]; # no problem!
Expand All @@ -438,13 +438,13 @@ Languages that allow
L<introspection|https://en.wikipedia.org/wiki/Introspection> like Perl 6
have functionalities attached to the type system that let the developer
access container and value metadata. This metadata can be used in a
program to carry out different actions depending on their value. As is
program to carry out different actions depending on their value. As it is
obvious from the name, metadata are extracted from a value or container
via the metaclass.
my $any-object = "random object";
my $metadata = $any-object.HOW;
say $metadata.^mro; # OUTPUT: «((ClassHOW) (Any) (Mu))␤
say $metadata.^mro; # OUTPUT: «((ClassHOW) (Any) (Mu))␤»
say $metadata.can( $metadata, "uc" ); # OUTPUT: «(uc uc)␤»
With the first C<say> we show the class hierarchy of the metamodel class, which
Expand All @@ -458,7 +458,7 @@ other cases, when roles are mixed in directly into a variable. For instance, in
the L<case of C<%hash-plus> defined above|#Defining_and_constraining_data_structures>:
=for code :preamble<my %hash-plus>
say %hash-plus.^can("last"); # OUTPUT «(last)␤»
say %hash-plus.^can("last"); # OUTPUT: «(last)␤»
In this case we are using the I<syntactic sugar> for C<HOW.method>, C<^method>,
to check if your data structure responds to that method; the output, which shows
Expand Down

0 comments on commit ed55bff

Please sign in to comment.