Skip to content

Commit

Permalink
Some minor grammar tweaks and other little bits in the MMD chapter.
Browse files Browse the repository at this point in the history
  • Loading branch information
jnthn committed Oct 18, 2009
1 parent 97f1702 commit 639cb7a
Showing 1 changed file with 23 additions and 19 deletions.
42 changes: 23 additions & 19 deletions src/multi-dispatch.pod
Expand Up @@ -9,9 +9,11 @@ converting Perl 6 data structures to JSON. The other part of that module,
which parses JSON and turns it into Perl 6 data structures, will be presented
later (TODO: reference grammar chapter).

The full code, containing additionally containing documentation and tests,
can be found at L<http://github.com/moritz/json/>.
The full code, containing additional documentation and tests, can be found at
L<http://github.com/moritz/json/>.

# TODO: Clarify numeric types. Only need one of the following two, but
# maybe s/Num/Numeric/.
multi to-json(Num $d) { ~$d }
multi to-json(Int $d) { ~$d }
multi to-json(Bool $d) { $d ?? 'true' !! 'false'; }
Expand Down Expand Up @@ -47,13 +49,13 @@ The various candidates all look like
multi to-json(Bool $data) { code here }
multi to-json(Num $data) { code here }

Which one is actually called depends on the type of the data passed to
Which one is actually called depends on the type of the data passed to the
subroutine. So if you call C<to-json(Bool::True)>, the first one is called. If
you pass a C<Num> to it, the second one is called.

The candidates for handling C<Num> and C<Int> are very simple: since JSON's
The candidates for handling C<Num> and C<Int> are very simple; since JSON's
and Perl 6's number formats coincide, the JSON converter can simply rely on
Perls conversion of these numbers to strings. The C<Bool> candidate returns
Perl's conversion of these numbers to strings. The C<Bool> candidate returns
the literal strings C<'true'> or C<'false'>.

The C<Str> candidate does a bit more work: it add quotes at the begin and the
Expand All @@ -77,18 +79,18 @@ again by recursing into C<to-json>.

This candidate adds something new: it doesn't contain a type defintion, and
thus the type of the parameter defaults to C<Any>, which is the root of the
"normal" branch of the type hierarchy (more on that $later). More
"normal" branch of the type hierarchy (more on that later). More
interestingly there's the C<where undef> clause, which is a so-called
I<subset type>: it matches only some values of the type C<Any>.

The verbose version of that is C<$d where { $d ~~ undef }>, so the
C<where undef> part is actually translated to a smart match. And yes, the
curly braces can contain arbirary code. Whenever the compiler performs a type
check on the parameter C<$d>, it first checks the I<nominal> type (which is
C<Any> here), and if that check succeeds, it calls the code block. Only if
that returns a true value, the whole type check is considered successful.
C<Any> here), and if that check succeeds, it calls the code block. The whole
type check will only be considered successful if that returns a true value.

You can abuse that count how often a type check is performed:
You can abuse this to count how often a type check is performed:

my $counter = 0;
multi a(Int $x) { };
Expand All @@ -102,9 +104,9 @@ You can abuse that count how often a type check is performed:

This piece of code defines three multis, one of which increases a counter
whenever its C<where> clause, also called I<constraint>, is executed.
Any Perl 6 compiler is free to
optimize away type checks it knows to succeed, but if it does not, the second
line with C<say> prints a higher number than the first.
Any Perl 6 compiler is free to optimize away type checks it knows will succeed,
but if it does not, the second line with C<say> prints a higher number than
the first.

(TODO: insert side note "Don't do that at home, kids! Type checks with side
effects are a B<really> bad idea in real world code")
Expand All @@ -130,17 +132,18 @@ C<Bool> and C<Any>.

If you try it out, you'll find that the dispatcher (which is the part of the
compiler that decides which candidate to call) still calls the C<Int>
candidate.
candidate. It's not about going through them in order either - you can even
move the last catch-all candidate to be first and the code still works.

The explanation is that since C<Int> is a type that conforms to C<Any>, it is
considered a narrower match for an integer. More generally speaking if you have
two types C<A> and C<B>, and C<A> conforms to C<B> (or C<A ~~ B> is the Perl 6
two types C<A> and C<B>, and C<A> conforms to C<B> (or C<A ~~ B>, as the Perl 6
programmer says), then an object which conforms to C<A> does so more
narrowly than to C<B>. And in the case of a multi dispatch the narrowest match
always wins.

Also a successfully evaluated constraint makes a match narrower than the
absence of a constraint, so in the case
absence of a constraint, so in the case of

multi to-json($d) { ... }
multi to-json($d where undef) { ... }
Expand Down Expand Up @@ -201,8 +204,8 @@ and scissors can't cut stone, but go blunt trying. If both players select the
same item, it's a draw.

The example code above creates a type for each possible object by declaring a
class. For each combination of chosen objects for which Player One wins
there's a candidate of the form
class (more on this in a later chapter). For each combination of chosen objects
for which Player One wins there's a candidate of the form

multi wins(Scissors $, Paper $) { 1 }

Expand Down Expand Up @@ -275,9 +278,9 @@ binds its first argument as C<rw>:
multi substr($str is rw, $start, $length, $substitution) { ... }

This is also an example of candidates with different arity (that is, expecting
a different number of arguments). This quite seldom really necessary, because
a different number of arguments). This is seldom really necessary, because
it is often a better alternative to make parameters optional. Cases where an
arbitrary number of arguments is allowed are handled with slurpy parameters
arbitrary number of arguments are allowed are handled with slurpy parameters
instead:

sub mean(*@values) {
Expand Down Expand Up @@ -311,6 +314,7 @@ lexical scopes, whereas it looks for methods in the class of the invocant, and
recursively in any parent classes.

# XXX should this explanation moved to the OO tutorial?
# XXX jnthn: in my opinion, yes

# TODO: Multi method dispatch example

Expand Down

0 comments on commit 639cb7a

Please sign in to comment.