Skip to content

Commit

Permalink
Ipmroved line and pagebreaking for chapter 5.
Browse files Browse the repository at this point in the history
  • Loading branch information
chromatic committed Dec 7, 2011
1 parent 339def8 commit b2e7204
Show file tree
Hide file tree
Showing 6 changed files with 200 additions and 219 deletions.
36 changes: 18 additions & 18 deletions sections/anonymous_functions.pod
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ input with behavior:
plus => \&add_two_numbers,
minus => \&subtract_two_numbers,
times => \&multiply_two_numbers,
# ... and so on
);

sub add_two_numbers { $_[0] + $_[1] }
Expand All @@ -34,8 +33,7 @@ input with behavior:
{
my ($left, $op, $right) = @_;

die "Unknown operation!"
unless exists $dispatch{ $op };
return unless exists $dispatch{ $op };

return $dispatch{ $op }->( $left, $right );
}
Expand Down Expand Up @@ -72,8 +70,8 @@ This dispatch table offers some degree of security; only those functions mapped
within the table are available for users to call. If your dispatch function
blindly assumed that the string given as the name of the operator corresponded
directly to the name of a function to call, a malicious user could conceivably
call any function in any other namespace by crafting an operator name of
C<'Internal::Functions::some_malicious_function'>.
call any function in any other namespace by passing
C<'Internal::Functions::malicious_function'>.

=end tip

Expand All @@ -93,7 +91,7 @@ You may also see anonymous functions passed as function arguments:
}

invoke_anon_function( \&named_func );
invoke_anon_function( B<sub { say 'I am an anonymous function' }> );
invoke_anon_function( B<sub { say 'Who am I?' }> );

=end programlisting

Expand All @@ -110,8 +108,8 @@ named or anonymous with introspection:

sub show_caller
{
my ($package, $filename, $line, $sub) = caller(1);
say "Called from $sub in $package at $filename : $line";
my ($package, $file, $line, $sub) = caller(1);
say "Called from $sub in $package:$file:$line";
}

sub main
Expand All @@ -136,8 +134,10 @@ introspection.

The result may be surprising:

Called from ShowCaller::B<main> in ShowCaller at anoncaller.pl : 20
Called from ShowCaller::B<__ANON__> in ShowCaller at anoncaller.pl : 17
Called from ShowCaller::B<main>
in ShowCaller:anoncaller.pl:20
Called from ShowCaller::B<__ANON__>
in ShowCaller:anoncaller.pl:17

X<CPAN; C<Sub::Name>>

Expand Down Expand Up @@ -193,8 +193,8 @@ functions. Consider the CPAN module C<Test::Fatal>:
my $croaker = exception { die 'I croak!' };
my $liver = exception { 1 + 1 };

like( $croaker, qr/I croak/, 'die() should throw an exception' );
is( $liver, undef, 'simple addition should not' );
like( $croaker, qr/I croak/, 'die() should croak' );
is( $liver, undef, 'addition should live' );

done_testing();

Expand All @@ -217,14 +217,13 @@ This syntax allows you to pass named functions by reference as well:
=begin programlisting

B<sub croaker { die 'I croak!' }>

B<sub liver { 1 + 1 }>

my $croaker = exception \&croaker;
my $liver = exception \&liver;

like( $croaker, qr/I croak/, 'die() should throw an exception' );
is( $liver, undef, 'simple addition should not' );
like( $croaker, qr/I croak/, 'die() should die' );
is( $liver, undef, 'addition should live' );

=end programlisting

Expand All @@ -247,8 +246,8 @@ will contain, and so will throw an exception.

=begin screen

Type of arg 1 to Test::Fatal::exception must be block or sub {}
(not private variable)
Type of arg 1 to Test::Fatal::exception
must be block or sub {} (not private variable)

=end screen

Expand All @@ -260,7 +259,8 @@ multiple arguments cannot have a trailing comma after the function block:
use Test::More;
use Test::Fatal 'dies_ok';

dies_ok { die 'This is my boomstick!' } 'No movie references here';
dies_ok { die 'This is my boomstick!' }
'No movie references here';

=end programlisting

Expand Down
10 changes: 9 additions & 1 deletion sections/autoload.pod
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,13 @@ C<AUTOLOAD()> with the C<subs> pragma:

=end programlisting

=begin tip Now You See Them

Forward declarations are only useful in the two rare cases of attributes and
autoloading (L<autoload>).

=end tip

That technique has the advantage of documenting your intent but the
disadvantage that you have to maintain a static list of functions or methods.
Overriding C<can()> (L<universal>) sometimes works better:
Expand Down Expand Up @@ -288,7 +295,8 @@ error:

=begin screen

Use of inherited AUTOLOAD for non-method I<slam_door>() is deprecated
Use of inherited AUTOLOAD for non-method
I<slam_door>() is deprecated

=end screen

Expand Down
66 changes: 35 additions & 31 deletions sections/closures.pod
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,11 @@ You've probably already created and used closures without realizing it:

=begin programlisting

{
package Invisible::Closure;
package Invisible::Closure;

my $filename = shift @ARGV;
my $filename = shift @ARGV;

sub get_filename
{
return $filename;
}
}
sub get_filename { return $filename }

=end programlisting

Expand All @@ -55,8 +50,9 @@ invoked, will return the next item in the iteration:
}
}

my @cousins = qw( Rick Alex Kaycee Eric Corey Mandy Christine )
my $cousins = make_iterator( @cousins );
my $cousins = make_iterator(
qw( Rick Alex Kaycee Eric Corey Mandy Christine )
);

say $cousins->() for 1 .. 5;

Expand All @@ -73,14 +69,12 @@ lexical environment:

=begin programlisting

my @aunts = qw( Carole Phyllis Wendy Sylvia Monica Lupe );
my $cousins = make_iterator( @cousins );
my $aunts = make_iterator( @aunts );
my $aunts = make_iterator(
qw( Carole Phyllis Wendy Sylvia Monica Lupe )
);

say $cousins->();
say $aunts->();
say $cousins->();
say $aunts->();

=end programlisting

Expand Down Expand Up @@ -140,10 +134,10 @@ elements you need:
{
for my $calc (@fibs .. $item)
{
$fibs[$calc] = $fibs[$calc - 2] + $fibs[$calc - 1];
$fibs[$calc] = $fibs[$calc - 2]
+ $fibs[$calc - 1];
}
}

return $fibs[$item];
}
}
Expand All @@ -162,8 +156,7 @@ returns the calculated or cached value. If you extract the behavior specific to
Fibonacci values, this code can provide any arbitrary code with a
lazily-iterated cache.

Extract the function C<generate_caching_closure()> and rewrite C<gen_fib()> to
use it:
Extracting the function C<generate_caching_closure()> produces:

=begin programlisting

Expand All @@ -175,12 +168,25 @@ use it:
{
my $item = shift;

$calc_element->($item, \@cache) unless $item < @cache;
$calc_element->($item, \@cache)
unless $item < @cache;

return $cache[$item];
};
}

=end programlisting

=begin tip Fold, Apply, and Filter

In one sense, the builtins C<map>, C<grep>, and C<sort> are themselves
higher-order functions. Compare them to C<gen_caching_closure()>.

=end tip

Now C<gen_fib()> can become:

=begin programlisting

sub gen_fib
{
Expand All @@ -193,7 +199,8 @@ use it:

for my $calc ((@$fibs - 1) .. $item)
{
$fibs->[$calc] = $fibs->[$calc - 2] + $fibs->[$calc - 1];
$fibs->[$calc] = $fibs->[$calc - 2]
+ $fibs->[$calc - 1];
}
},
@fibs
Expand All @@ -206,14 +213,7 @@ The program behaves as it did before, but the use of function references and
closures separates the cache initialization behavior from the calculation of
the next number in the Fibonacci series. Customizing the behavior of code--in
this case, C<gen_caching_closure()>--by passing in a function allows tremendous
flexibility and abstraction.

=begin tip Fold, Apply, and Filter

In one sense, the builtins C<map>, C<grep>, and C<sort> are themselves
higher-order functions. Compare them to C<gen_caching_closure()>.

=end tip
flexibility.

=head2 Closures and Partial Application

Expand Down Expand Up @@ -243,8 +243,12 @@ arguments that never change.

X<partial application>

I<Partial application> binds some of the arguments to a function and allows you
to provide the rest later:
A technique called I<partial application> allows you to bind I<some> of the
arguments to a function so that you can provide the others later. Wrap the
function you intend to call in a closure and pass the bound arguments.

Consider an ice cream cart which only serves French Vanilla ice cream over
Cavendish bananas:

=begin programlisting

Expand Down
Loading

0 comments on commit b2e7204

Please sign in to comment.