Permalink
Browse files

Ipmroved line and pagebreaking for chapter 5.

  • Loading branch information...
chromatic committed Dec 7, 2011
1 parent 339def8 commit b2e72048db45e9e9c401243a88571b0f6e157a9a
Showing with 200 additions and 219 deletions.
  1. +18 −18 sections/anonymous_functions.pod
  2. +9 −1 sections/autoload.pod
  3. +35 −31 sections/closures.pod
  4. +97 −105 sections/functions.pod
  5. +36 −61 sections/scope.pod
  6. +5 −3 sections/state.pod
@@ -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] }
@@ -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 );
}
@@ -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
@@ -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
@@ -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
@@ -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>>
@@ -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();
@@ -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
@@ -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
@@ -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
View
@@ -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:
@@ -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
View
@@ -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
@@ -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;
@@ -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
@@ -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];
}
}
@@ -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
@@ -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
{
@@ -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
@@ -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
@@ -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
Oops, something went wrong.

0 comments on commit b2e7204

Please sign in to comment.