├── .gitignore
├── CREDITS
├── README
├── activestate.yaml
├── book.conf
├── build
├── css
│ └── style.css
├── epub
│ └── .gitignore
├── html
│ └── style.css
├── latex
│ ├── copyright.tex
│ └── modern_perl_commands.sty
├── pdf
│ └── .gitignore
├── tools
│ ├── build_chapters.pl
│ ├── build_epub.pl
│ ├── build_html.pl
│ ├── build_html_book.pl
│ ├── build_pdf.pl
│ └── open_browser.pl
└── xhtml
│ └── .gitignore
├── images
├── mp_cover_full.png
├── mp_cover_med.png
└── mp_cover_thumb.png
├── outline.pod
└── sections
├── advanced_oo.pod
├── anonymous_functions.pod
├── arrays.pod
├── attributes.pod
├── autoload.pod
├── automatic_dereferencing.pod
├── barewords.pod
├── blessed_references.pod
├── builtins.pod
├── chapter_00.pod
├── chapter_01.pod
├── chapter_02.pod
├── chapter_03.pod
├── chapter_04.pod
├── chapter_05.pod
├── chapter_06.pod
├── chapter_07.pod
├── chapter_08.pod
├── chapter_09.pod
├── chapter_10.pod
├── chapter_11.pod
├── chapter_12.pod
├── closures.pod
├── code_generation.pod
├── coercion.pod
├── context_philosophy.pod
├── control_flow.pod
├── cpan.pod
├── credits.pod
├── distributions.pod
├── exceptions.pod
├── expressivity.pod
├── files.pod
├── functions.pod
├── globals.pod
├── handling_warnings.pod
├── hashes.pod
├── idioms.pod
├── implicit_ideas.pod
├── indirect_objects.pod
├── method_sub_equivalence.pod
├── missing_defaults.pod
├── modules.pod
├── moose.pod
├── names.pod
├── nested_data_structures.pod
├── next_steps.pod
├── operator_characteristics.pod
├── operator_types.pod
├── overloading.pod
├── packages.pod
├── perl_community.pod
├── perldoc.pod
├── pragmas.pod
├── prototypes.pod
├── references.pod
├── reflection.pod
├── regular_expressions.pod
├── scalars.pod
├── scope.pod
├── smart_match.pod
├── state.pod
├── style.pod
├── taint.pod
├── testing.pod
├── tie.pod
├── universal.pod
├── values.pod
└── variables.pod
/.gitignore:
--------------------------------------------------------------------------------
1 | build/chapters
2 | build/html/*.html
3 | build/pdf/*.pdf
4 | examples/
5 | !build/pdf/.gitignore
6 | !build/epub/.gitignore
7 |
--------------------------------------------------------------------------------
/CREDITS:
--------------------------------------------------------------------------------
1 | Please add yourself to this file.
2 |
3 | N: chromatic
4 | E: chromatic@wgz.org
5 |
6 | N: Felipe
7 | E: fegolac@gmail.com
8 |
9 | N: Jeremiah Foster
10 | E: jeremiah@jeremiahfoster.com
11 |
12 | N: Alex Muntada
13 | E: alexm@cpan.org
14 |
15 | N: Bruce Gray
16 | E: bruce.gray@acm.org
17 |
18 | N: John McNamara
19 | E: jmcnamara@cpan.org
20 |
21 | N: Josh McAdams
22 | E: joshua.mcadams@gmail.com
23 |
24 | N: Nelo Onyiah
25 | E: nelo.onyiah@gmail.com
26 |
27 | N: sunnavy
28 | E: sunnavy@gmail.com
29 |
30 | N: Doug Wilson
31 | E: doug@somethingdoug.com
32 |
33 | N: John SJ Anderson
34 | E: genehack@genehack.org
35 |
36 | N: Moritz Lenz
37 | E: moritz@faui2k3.org
38 |
39 | N: Carl Mäsak
40 | E: cmasak@gmail.com
41 |
42 | N: Bryan Summersett
43 | E: bsummersett@gmail.com
44 |
45 | N: Alex Balhatchet
46 | E: kaoru@slackwise.net
47 |
48 | N: Vasily Chekalkin
49 | E: bacek@bacek.com
50 |
51 | N: Tim Heaney
52 | E: oylenshpeegul@gmail.com
53 |
54 | N: Sam Vilain
55 | E: sam@vilain.net
56 |
57 | N: Colin Wetherbee
58 | E: cww@cpan.org
59 |
60 | N: Dan Scott
61 | E: dan@coffeecode.net
62 |
63 | N: Shlomi Fish
64 | E: shlomif@iglu.org.il
65 |
66 | N: Scott Thomson
67 | E: scott@dearie.me.uk
68 |
69 | N: Michael Hind
70 | E: mike.hind@gmail.com
71 |
72 | N: Frank Wiegand
73 | E: fwie@cpan.org
74 |
75 | N: Shawn M Moore
76 | E: sartak@bestpractical.com
77 |
78 | N: Mark A. Stratman
79 | E: mark@sporkstorms.org
80 |
81 | N: Jan Krynicky
82 | E: Jenda@Krynicky.cz
83 |
84 | N: Curtis Jewell
85 | E: csjewell@cpan.org
86 |
87 | N: James E Keenan
88 | E: jkeenan@cpan.org
89 |
90 | N: Yary Hluchan
91 | E: not.com@gmail.com
92 |
93 | N: Yuval Kogman
94 | E: nothingmuch@woobling.org
95 |
96 | N: Chas. Owens
97 | E: chas.owens@gmail.com
98 |
99 | N: John Gabriele
100 | E: jmg3000@gmail.com
101 |
102 | N: Jeff Lavallee
103 | E: jeff@zeroclue.com
104 |
105 | N: Phillip Smith
106 | E: phillip@communitybandwidth.ca
107 |
108 | N: Sawyer X
109 | E: xsawyerx@cpan.org
110 |
111 | N: Paulo Custodio
112 | E: pscust@cpan.org
113 |
114 | N: Jean-Baptiste Mazon
115 | E: ?
116 |
117 | N: ww from PerlMonks
118 | E: ?
119 |
120 | N: Andrew Savige
121 | E: asavige@cpan.org
122 |
123 | N: Matthias Bloch
124 | E: matthias.bloch@puffin.ch
125 |
126 | N: Peter Aronoff
127 | E: telemachus@arpinum.org
128 |
129 | N: Audrey Tang
130 | E: cpan@audreyt.org
131 |
132 | N: Lee Aylward
133 | E: lee@laylward.com
134 |
135 | N: Mark Fowler
136 | E: mark@twoshortplanks.com
137 |
138 | N: Dmitry Chestnykh
139 | E: dmitry@codingrobots.com
140 |
141 | N: harleypig
142 | E: harleypig@gmail.com
143 |
144 | N: Jess Robinson
145 | E: castaway@desert-island.me.uk
146 |
147 | N: David Yingling
148 | E: deeelwy@yahoo.com
149 |
150 | N: Marko Zagozen
151 | E: ?
152 |
153 | N: Alex-ander Scott-Johns
154 | E: alexander.scott.johns@googlemail.com
155 |
156 | N: Larry Wall
157 | E: larry@wall.org
158 |
159 | N: Gabrielle Roth
160 | E: gorthx@gmail.com>
161 |
162 | N: Mohammed Arafat Kamaal
163 | E: makamaal.linux@gmail.com
164 |
165 | N: Christopher E. Stith
166 | E: cstith@gmail.com
167 |
168 | N: Mike Huffman
169 | E: mhuffman@aracnet.com
170 |
171 | N: E. Choroba
172 | E: choroba on PerlMonks
173 |
174 | N: hbm
175 | E: hbm on PerlMonks
176 |
177 | N: Ask Bjørn Hansen
178 | E: ask@develooper.com
179 |
180 | N: Ævar Arnfjörð Bjarmason
181 | E: avar@cpan.org
182 |
183 | N: Gareth McCaughan
184 | E: gareth.mccaughan@pobox.com
185 |
186 | N: Robert Hicks
187 | E: rlhicks@wehicks.com
188 |
189 | N: Chris Niswander
190 | E: cnp1@chrisniswander.com
191 |
192 | N: Andrew Grangaard
193 | E: spazm@cpan.org
194 |
195 | N: Mark Hindess
196 | E: soft-cpan@temporalanomaly.com
197 |
198 | N: John Bokma
199 | E: contact@johnbokma.com
200 |
201 | N: Lorne Schachter
202 | E: lorne.schachter@citi.com
203 |
204 | N: Dave Rolsky
205 | E: autarch@urth.org
206 |
207 | N: Ben Tilly
208 | E: btilly@gmail.com
209 |
210 | N: Michael Lang
211 | E: michi@jackal-net.at
212 |
213 | N: Graeme Hewson
214 | E: ghewson@wormhole.me.uk
215 |
216 | N: Steve Schulze
217 | E: thundergnat@gmail.com
218 |
219 | N: Anneli Cuss
220 | E: celtic@sairyx.org
221 |
222 | N: Eduardo Santiago
223 | E: esm@cpan.org
224 |
225 | N: Andy Lester
226 | E: andy@petdance.com
227 |
228 | N: Steve Dickinson
229 | E: dsdickinson@gmail.com
230 |
231 | N: Kurt Edmiston
232 | E: hurdlecrew@gmail.com
233 |
234 | N: Lewis Wall
235 | E: qufanat@gmail.com
236 |
237 | N: Gary H. Jones II
238 | E: gary@pointblanksecurity.com
239 |
240 | N: Kirk Kimmel
241 | E: kimmel.k.programmer@gmail.com
242 |
243 | N: Ruud H. G. van Tol
244 | E: rvtol@isolution.nl
245 |
246 | N: Jean-Pierre Rupp
247 | E: jpierre@xeno-genesis.com
248 |
249 | N: Tom Christiansen
250 | E: tchrist@perl.com
251 |
252 | N: Daniel Holz
253 | E: dgholz@gmail.com
254 |
255 | N: Kevin Granade
256 | E: kevingranade@linuxwrangling.com
257 |
258 | N: Ahmad M. Zawawi
259 | E: ahmad.zawawi@gmail.com
260 |
261 | N: Michael Hicks
262 | E: nooneofconsequence@gmail.com
263 |
264 | N: Paul Waring
265 | E: paul@xk7.net
266 |
267 | N: Grzegorz Rożniecki
268 | E: xaerxess@gmail.com
269 |
270 | N: Graham Knop
271 | E: haarg@haarg.org
272 |
273 | N: Nitesh Bezzala
274 | E: nbezzala@yahoo.com
275 |
276 | N: Nathan Glenn
277 | E: garfieldnate@gmail.com
278 |
279 | N: Matt Pettis
280 | E: matthew.pettis@gmail.com
281 |
282 | N: Géraud CONTINSOUZAS
283 | E: gcs@cpan.org
284 |
285 | N: Alex Schroeder
286 | E: alex@gnu.org
287 |
288 | N: David Farrell
289 | E: editor@perltricks.com
290 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | What is Modern Perl?
2 | --------------------
3 |
4 | Perl is a popular, powerful, and widely used programming language. Over its
5 | twenty year lifespan, it's powered millions of systems worldwide, moving
6 | trillions of dollars. More importantly, it's helped countless people get their
7 | work done effectively.
8 |
9 | The Perl community has a reputation for clever solutions -- and a reputation
10 | for institutional knowledge that isn't always clear to novices and neophytes.
11 | Modern Perl, written with this knowledge, can be very clean, very maintainable,
12 | and very effective.
13 |
14 | That knowledge should be available to everyone. This book will teach you how
15 | to program Perl well by teaching you how to understand Perl's design, its
16 | syntax, and its semantics.
17 |
18 | http://www.modernperlbooks.com/mt/2009/01/why-modern-perl.html
19 |
20 |
21 | Intended Audience
22 | -----------------
23 |
24 | I assume readers have some familiarity with Perl. They should have it
25 | installed and should know how to write, edit, save, and run Perl programs.
26 | They don't necessarily have to have finished reading a tutorial such as
27 | Learning Perl or Beginning Perl, but they should be sufficiently familiar with
28 | programming to be able to follow along with examples.
29 |
30 | I try not to assume complete knowledge of even basic constructs; I try to
31 | explain them in detail, as understanding subtleties of design and
32 | implementation are important to mastering the subject of Perl.
33 |
34 |
35 | Reviewer Guidelines
36 | -------------------
37 |
38 | I appreciate all suggestions and critiques, especially:
39 |
40 | * is the work accurate?
41 | * is the work complete?
42 | * is the work coherent?
43 | * are there missing sections and subjects?
44 | * are the examples effective?
45 | * is the flow of information appropriate?
46 |
47 |
48 | Building this Book
49 | ------------------
50 |
51 | You need a modern version of Perl installed. I recommend Perl 5.10.1, but
52 | anything newer than 5.8.6 should work.
53 |
54 | You should also have Pod::PseudoPod 0.16 or newer installed with its
55 | dependencies.
56 |
57 | From the top level directory of a checkout, build the individual chapters with:
58 |
59 | $ perl build/tools/build_chapters.pl
60 |
61 | The chapter sources are in the sections/ directory. Each chapter has a
62 | corresponding chapter_nn.pod file. Each file contains multiple POD links which
63 | refer to other files in the sections/ directory. Each of those files contains
64 | a PseudoPOD Z<> anchor.
65 |
66 | The build_chapters.pl program weaves these sections into chapters and writes
67 | them to POD files in build/chapters.
68 |
69 | (This process makes it easy to rearrange sections within and between chapters
70 | without generating huge diffs.)
71 |
72 | To build HTML from these woven chapters:
73 |
74 | $ perl build/tools/build_html.pl
75 |
76 | This will produce nicely-formatted HTML in the build/html/ directory. If
77 | anything looks wrong, it's a mistake on my part (or a CSS problem) and patches
78 | are very welcome.
79 |
80 | To build an ePub eBook from the woven chapters:
81 |
82 | $ perl build/tools/build_epub.pl
83 |
84 | This will produce an ePub eBook in the build/epub/ directory.
85 |
86 | To build PDFs from the chapters:
87 |
88 | $ perl build/tools/build_pdf.pl
89 |
90 | This will build PDFs in the build/pdf directory. You must have App::pod2pdf
91 | installed from the CPAN.
92 |
93 |
94 | Contributing to Modern Perl
95 | ---------------------------
96 |
97 | This work is licensed under a Creative Commons Attribution-Noncommercial-Share
98 | Alike 3.0 United States License. For more details, see:
99 |
100 | http://creativecommons.org/licenses/by-nc-sa/3.0/us/
101 |
102 | Please feel free to point people to this repository. Suggestions and
103 | contributions are welcome. You have the right to redistribute modified
104 | versions, but I ask (though do not require) you to file bugs or submit pull
105 | requests against this repository.
106 |
107 | This book is available in print and in formatted electronic formats
108 | from Onyx Neon Press:
109 |
110 | http://www.onyxneon.com/books/modern_perl/index.html
111 |
112 | The electronic versions are available for free, with no restrictions on free
113 | redistribution.
114 |
--------------------------------------------------------------------------------
/activestate.yaml:
--------------------------------------------------------------------------------
1 | project: https://platform.activestate.com/chromatic/ModernPerl4e-5.34-Linux?branch=main&commitID=aff573b8-824b-4844-a29e-7b0f0fc979e3
2 |
3 | scripts:
4 | - name: activationMessage
5 | language: perl
6 | value: |
7 | print <<~EOT;
8 | You are now in an activated state, which is like a virtual environment to work
9 | in that doesn't affect the rest of your system. To leave, run `exit`.
10 |
11 | What's next?
12 | - To learn more about what you can do, run → `state run modern-perl-book [chapter-number]`
13 | EOT
14 | exec( $^X, $ENV{ACTIVESTATE_ACTIVATED} . '/build/tools/build_html_book.pl' );
15 | - name: modern-perl-book
16 | description: Open the Modern Perl book in your web browser. With no arguments provided, opens the table of contents. Otherwise pass the chapter number (0, 1, ... 15) to read that chapter.
17 | language: perl
18 | value: |
19 | exec( $^X, $ENV{ACTIVESTATE_ACTIVATED} . '/build/tools/open_browser.pl', @ARGV );
20 | events:
21 | - name: ACTIVATE
22 | value: activationMessage
23 |
--------------------------------------------------------------------------------
/book.conf:
--------------------------------------------------------------------------------
1 | [book]
2 | author_name=chromatic
3 | copyright_year=2021
4 | cover_image=
5 | language=en
6 | title=Modern Perl
7 | subtitle=development edition
8 | filename_template=modern_perl
9 | build_index=1
10 | build_credits=1
11 | build_chapters=1
12 | ISBN10=
13 | ISBN13=
14 |
15 | [layout]
16 | chapter_name_prefix=chapter
17 | subchapter_directory=sections
18 | chapter_build_directory=chapters
19 |
--------------------------------------------------------------------------------
/build/epub/.gitignore:
--------------------------------------------------------------------------------
1 | !.gitignore
2 | *
3 |
--------------------------------------------------------------------------------
/build/html/style.css:
--------------------------------------------------------------------------------
1 |
179 |
--------------------------------------------------------------------------------
/build/latex/copyright.tex:
--------------------------------------------------------------------------------
1 | \thispagestyle{empty}
2 |
3 | \huge{\booktitle}
4 | \newline
5 | \large{\booksubtitle}
6 | \newline
7 | \newline
8 | \normalsize
9 |
10 | Copyright \copyright~2010-2014 \bookauthor
11 |
12 | \vfill
13 | \textbf{Editor:} Shane Warden\newline
14 | \textbf{Logo design:} Devin Muldoon\newline
15 | \textbf{Cover design:} Allison Randal, chromatic, and Jeffrey Martin
16 |
17 | \textbf{ISBN-10:} \bookisbnten\newline
18 | \textbf{ISBN-13:} \bookisbnthirteen
19 |
20 | Published by Onyx Neon Press, \url{http://www.onyxneon.com/}.
21 | The Onyx Neon logo is a trademark of Onyx Neon, Inc.
22 |
23 | Onyx Neon typesets books with free software, especially Ubuntu GNU/Linux, Perl,
24 | PseudoPod, and \LaTeX. Many thanks to the contributors who make these and other
25 | projects possible.
26 |
27 | 2010 - 2011 Edition October 2010\newline
28 | 2011 - 2012 Edition January 2012\newline
29 | 2014 - 2015 Edition January 2014
30 |
31 | Electronic versions of this book are available from
32 | \url{http://onyxneon.com/books/modern_perl/}, and the companion website is
33 | \url{http://modernperlbooks.com/}. Please share with your friends and
34 | colleagues.
35 |
36 | Thanks for reading!
37 |
--------------------------------------------------------------------------------
/build/latex/modern_perl_commands.sty:
--------------------------------------------------------------------------------
1 | \newcommand{\booktitle}{Modern Perl}
2 | \newcommand{\booksubtitle}{2014 edition}
3 | \newcommand{\bookauthor}{chromatic}
4 | \newcommand{\bookisbnten}{0-9779201-7-8}
5 | \newcommand{\bookisbnthirteen}{978-0-9779201-7-4}
6 |
--------------------------------------------------------------------------------
/build/pdf/.gitignore:
--------------------------------------------------------------------------------
1 | !.gitignore
2 | *
3 |
--------------------------------------------------------------------------------
/build/tools/build_chapters.pl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 |
3 | use strict;
4 | use warnings;
5 |
6 | use File::Path 'mkpath';
7 | use File::Spec::Functions qw( catfile catdir splitpath );
8 |
9 | my $sections_href = get_section_list();
10 |
11 | for my $chapter (get_chapter_list())
12 | {
13 | my $text = process_chapter( $chapter, $sections_href );
14 | write_chapter( $chapter, $text );
15 | }
16 |
17 | die( "Scenes missing from chapters:", join "\n\t", '', keys %$sections_href )
18 | if keys %$sections_href;
19 |
20 | exit;
21 |
22 | sub get_chapter_list
23 | {
24 | my $glob_path = catfile( 'sections', 'chapter_??.pod' );
25 | return glob( $glob_path );
26 | }
27 |
28 | sub get_section_list
29 | {
30 | my %sections;
31 | my $sections_path = catfile( 'sections', '*.pod' );
32 |
33 | for my $section (glob( $sections_path ))
34 | {
35 | next if $section =~ /\bchapter_??/;
36 | my $anchor = get_anchor( $section );
37 | $sections{ $anchor } = $section;
38 | }
39 |
40 | return \%sections;
41 | }
42 |
43 | sub get_anchor
44 | {
45 | my $path = shift;
46 |
47 | open my $fh, '<:utf8', $path or die "Can't read '$path': $!\n";
48 | while (<$fh>) {
49 | next unless /Z<(\w*)>/;
50 | return $1;
51 | }
52 |
53 | die "No anchor for file '$path'\n";
54 | }
55 |
56 | sub process_chapter
57 | {
58 | my ($path, $sections_href) = @_;
59 | my $text = read_file( $path );
60 |
61 | $text =~ s/^L<(\w+)>/insert_section( $sections_href, $1, $path )/emg;
62 |
63 | $text =~ s/(=head1 .*)\n\n=head2 \*{3}/$1/g;
64 | return $text;
65 | }
66 |
67 | sub read_file
68 | {
69 | my $path = shift;
70 | open my $fh, '<:utf8', $path or die "Can't read '$path': $!\n";
71 | return scalar do { local $/; <$fh>; };
72 | }
73 |
74 | sub insert_section
75 | {
76 | my ($sections_href, $name, $chapter) = @_;
77 |
78 | die "Unknown section '$name' in '$chapter'\n"
79 | unless exists $sections_href->{ $1 };
80 |
81 | my $text = read_file( $sections_href->{ $1 } );
82 | delete $sections_href->{ $1 };
83 | return $text;
84 | }
85 |
86 | sub write_chapter
87 | {
88 | my ($path, $text) = @_;
89 | my $name = ( splitpath $path )[-1];
90 | my $chapter_dir = catdir( 'build', 'chapters' );
91 | my $chapter_path = catfile( $chapter_dir, $name );
92 |
93 | mkpath( $chapter_dir ) unless -e $chapter_dir;
94 |
95 | open my $fh, '>:utf8', $chapter_path
96 | or die "Cannot write '$chapter_path': $!\n";
97 |
98 | print {$fh} $text;
99 |
100 | warn "Writing '$chapter_path'\n";
101 | }
102 |
--------------------------------------------------------------------------------
/build/tools/build_html.pl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 |
3 | use strict;
4 | use warnings;
5 |
6 | use Pod::PseudoPod::HTML;
7 | use File::Spec::Functions qw( catfile catdir splitpath );
8 |
9 | # P::PP::H uses Text::Wrap which breaks HTML tags
10 | local *Text::Wrap::wrap;
11 | *Text::Wrap::wrap = sub { $_[2] };
12 |
13 | my @chapters = get_chapter_list();
14 | my $anchors = get_anchors(@chapters);
15 |
16 | sub Pod::PseudoPod::HTML::end_L
17 | {
18 | my $self = shift;
19 | if ($self->{scratch} =~ s/\b(\w+)$//)
20 | {
21 | my $link = $1;
22 | die "Unknown link $link\n" unless exists $anchors->{$link};
23 | $self->{scratch} .= '"
24 | . $anchors->{$link}[1] . '';
25 | }
26 | }
27 |
28 | for my $chapter (@chapters)
29 | {
30 | my $out_fh = get_output_fh($chapter);
31 | my $parser = Pod::PseudoPod::HTML->new();
32 |
33 | $parser->output_fh($out_fh);
34 |
35 | # output a complete html document
36 | $parser->add_body_tags(1);
37 |
38 | # add css tags for cleaner display
39 | $parser->add_css_tags(1);
40 |
41 | $parser->no_errata_section(1);
42 | $parser->complain_stderr(1);
43 |
44 | $parser->parse_file($chapter);
45 | }
46 |
47 | exit;
48 |
49 | sub get_anchors
50 | {
51 | my %anchors;
52 |
53 | for my $chapter (@_)
54 | {
55 | my ($file) = $chapter =~ /(chapter_\d+)./;
56 | my $contents = slurp( $chapter );
57 |
58 | while ($contents =~ /^=head\d (.*?)\n\nZ<(.*?)>/mg)
59 | {
60 | $anchors{$2} = [ $file . '.html', $1 ];
61 | }
62 | }
63 |
64 | return \%anchors;
65 | }
66 |
67 | sub slurp
68 | {
69 | return do { local @ARGV = @_; local $/ = <>; };
70 | }
71 |
72 | sub get_chapter_list
73 | {
74 | my $glob_path = catfile( qw( build chapters chapter_??.pod ) );
75 | return glob $glob_path;
76 | }
77 |
78 | sub get_output_fh
79 | {
80 | my $chapter = shift;
81 | my $name = ( splitpath $chapter )[-1];
82 | my $htmldir = catdir( qw( build html ) );
83 |
84 | $name =~ s/\.pod/\.html/;
85 | $name = catfile( $htmldir, $name );
86 |
87 | open my $fh, '>:utf8', $name
88 | or die "Cannot write to '$name': $!\n";
89 |
90 | return $fh;
91 | }
92 |
--------------------------------------------------------------------------------
/build/tools/build_html_book.pl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env perl
2 |
3 | use Modern::Perl '2019';
4 | use Pod::PseudoPod::Book;
5 | use Path::Tiny;
6 |
7 | exit main( @ARGV );
8 |
9 | sub main {
10 | my $app = Pod::PseudoPod::Book->new;
11 |
12 | my ($cmd, $opt, @args) = $app->get_command( 'buildhtml' );
13 |
14 | for my $build_path ( 'build/chapters', 'build/html' ) {
15 | path($build_path)->mkpath;
16 | }
17 |
18 | for my $command (qw( buildcredits buildchapters ), $cmd ) {
19 | $app->execute_command( $app->plugin_for( $command ), $opt, @args );
20 | }
21 |
22 | fixup_html_chapters( 'build/html' );
23 |
24 | return 0;
25 | }
26 |
27 | sub fixup_html_chapters {
28 | my $output_dir = path(shift);
29 |
30 | for my $child_file ($output_dir->children( qr/\.html$/ ) ) {
31 | $child_file->edit( sub {
32 | s/
//;
33 | s/<\/body>/<\/div><\/body>/;
34 | });
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/build/tools/build_pdf.pl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 |
3 | use strict;
4 | use warnings;
5 |
6 | use File::Spec::Functions qw( catfile catdir splitpath );
7 |
8 | # getting chapter list
9 | my @chapters = get_chapter_list();
10 |
11 | # Check if pod2pdf is available
12 | require App::pod2pdf
13 | or die "pod2pdf is not present in your PATH; please install App::pod2pdf\n";
14 |
15 | my $outpath = catdir( qw( build pdf ) );
16 |
17 | for my $chapter ( @chapters ){
18 | my @filename = split( /\./ , $chapter );
19 | print "Converting $chapter to pdf\n";
20 | system( 'pod2pdf', '--noheader', $chapter, '--output-file',
21 | catfile(qw( build pdf ), (splitpath($filename[0]))[-1] . '.pdf' ) );
22 | }
23 |
24 | print "PDFs have been generated in build/pdf\n";
25 |
26 | sub get_chapter_list
27 | {
28 | my $glob_path = catfile( qw( build chapters chapter_??.pod ) );
29 | return glob $glob_path;
30 | }
31 |
--------------------------------------------------------------------------------
/build/tools/open_browser.pl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env perl
2 |
3 | use Modern::Perl '2019';
4 | use Browser::Open;
5 | use Path::Tiny;
6 | use feature 'signatures';
7 | no warnings 'experimental::signatures';
8 |
9 | exit main( @ARGV );
10 |
11 | sub main($chapter = undef) {
12 | return Browser::Open::open_browser('file://' . get_chapter($chapter), 1 );
13 | }
14 |
15 | sub get_chapter($chapter_number) {
16 | return get_file(shift)->absolute;
17 | }
18 |
19 | sub get_file($chapter_number) {
20 | my $index = path('build/html/index.html');
21 | return $index unless $chapter_number;
22 | return $index unless $chapter_number =~ /\A\d+\Z/;
23 |
24 | for my $num ($chapter_number, '0' . $chapter_number) {
25 | my $chapter_path = path('build/html/chapter_' . $num . '.html');
26 | return $chapter_path if $chapter_path->exists;
27 | }
28 |
29 | return $index;
30 | }
31 |
--------------------------------------------------------------------------------
/build/xhtml/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 |
--------------------------------------------------------------------------------
/images/mp_cover_full.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chromatic/modern_perl_book/bb03cb0404422853060b8493f7992cf39343e658/images/mp_cover_full.png
--------------------------------------------------------------------------------
/images/mp_cover_med.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chromatic/modern_perl_book/bb03cb0404422853060b8493f7992cf39343e658/images/mp_cover_med.png
--------------------------------------------------------------------------------
/images/mp_cover_thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chromatic/modern_perl_book/bb03cb0404422853060b8493f7992cf39343e658/images/mp_cover_thumb.png
--------------------------------------------------------------------------------
/sections/advanced_oo.pod:
--------------------------------------------------------------------------------
1 | =head1 Advanced OO Perl
2 |
3 | Z
4 |
5 | Creating and using objects in Perl with Moose (L) is easy. I
6 | good programs is not. It's as easy to overdesign a program as it is to
7 | underdesign it. Only practical experience can help you understand the most
8 | important design techniques, but several principles can guide you.
9 |
10 | =head2 Favor Composition Over Inheritance
11 |
12 | X
13 | X
14 |
15 | Novice OO designs often overuse inheritance to reuse code and to exploit
16 | polymorphism. The result is a deep class hierarchy with responsibilities
17 | scattered all over the place. Maintaining this code is difficult--who knows
18 | where to add or edit behavior? What happens when code in one place conflicts
19 | with code declared elsewhere?
20 |
21 | X
22 | X
23 |
24 | Inheritance is only one of many tools for OO programmers. It's not always the
25 | right tool. It's often the wrong tool. A C may extend C
26 | (an I), but C may better I several C
27 | objects as instance attributes (a I).
28 |
29 | Decomposing complex classes into smaller, focused entities improves
30 | encapsulation and reduces the possibility that any one class or role does too
31 | much. Smaller, simpler, and better encapsulated entities are easier to
32 | understand, test, and maintain.
33 |
34 | =head2 Single Responsibility Principle
35 |
36 | X
37 |
38 | When you design your object system, consider the responsibilities of each
39 | entity. For example, an C object may represent specific information
40 | about a person's name, contact information, and other personal data, while a
41 | C object may represent business responsibilities. Separating these
42 | entities in terms of their responsibilities allows the C class to
43 | consider only the problem of managing information specific to who the person is
44 | and the C class to represent what the person does. (Two Cs may
45 | have a C-sharing arrangement, for example, or one C may have the
46 | CFO and the COO Cs.)
47 |
48 | When each class has a single responsibility, you reduce coupling between
49 | classes and improve the encapsulation of class-specific data and behavior.
50 |
51 | =head2 Don't Repeat Yourself
52 |
53 | X
54 |
55 | Complexity and duplication complicate development and maintenance. The I
56 | principle (Don't Repeat Yourself) is a reminder to seek out and to eliminate
57 | duplication within the system. Duplication exists in data as well as in code.
58 | Instead of repeating configuration information, user data, and other important
59 | artifacts of your system, create a single, canonical representation of that
60 | information from which you can generate the other artifacts.
61 |
62 | This principle helps you to find the optimal representation of your system and
63 | its data and reduces the possibility that duplicate information will get out of
64 | sync.
65 |
66 | =head2 Liskov Substitution Principle
67 |
68 | X
69 |
70 | The Liskov substitution principle suggests that you should be able to
71 | substitute a specialization of a class or a role for the original without
72 | violating the original's API. In other words, an object should be as or more
73 | general with regard to what it expects and at least as specific about what it
74 | produces as the object it replaces.
75 |
76 | Imagine two classes, C and its child class C. If the classes
77 | follow the Liskov substitution principle, you can replace every use of
78 | C objects with C objects in the test suite, and everything
79 | should pass. See Reg Braithwaite's
80 | "IS-STRICTLY-EQUIVALENT-TO-A"N.>
81 | for more details.
82 |
83 | =head2 Subtypes and Coercions
84 |
85 | Z
86 |
87 | X
88 | X
89 | X
90 |
91 | Moose allows you to declare and use types and extend them through subtypes to
92 | form ever more specialized descriptions of what your data represents and how it
93 | behaves. These type annotations help verify that the function and method
94 | parameters are correct--or can be coerced into the proper data types.
95 |
96 | X>
97 | X>
98 |
99 | For example, you may wish to allow people to provide dates to a C entry
100 | as strings while representing them as C instances internally. You can
101 | do this by creating a Date type and adding a coercion from string types. See
102 | C and C for more information.
103 |
104 | =head2 Immutability
105 |
106 | Z
107 |
108 | X
109 |
110 | With a well-designed object, you tell it I, not I.
111 | If you find yourself accessing object instance data (even through accessor
112 | methods) outside of the object itself, you may have too much access to an
113 | object's internals.
114 |
115 | OO novices often treat objects as if they were bundles of records which use
116 | methods to get and set internal values. This simple technique leads to the
117 | unfortunate temptation to spread the object's responsibilities throughout the
118 | entire system.
119 |
120 | You can prevent inappropriate access by making your objects immutable. Provide
121 | the necessary data to their constructors, then disallow any modifications of
122 | this information from outside the class. Expose no methods to mutate instance
123 | data--make all of your public accessors read-only and use internal attribute
124 | writers sparingly. Once you've constructed such an object, you know it's always
125 | in a valid state. You can never modify its data to put it in an invalid state.
126 |
127 | This takes tremendous discipline, but the resulting systems are robust,
128 | testable, and maintainable. Some designs go as far as to prohibit the
129 | modification of instance data I the class itself.
130 |
--------------------------------------------------------------------------------
/sections/anonymous_functions.pod:
--------------------------------------------------------------------------------
1 | =head1 Anonymous Functions
2 |
3 | Z
4 |
5 | X
6 |
7 | An I is a function without a name. It behaves exactly like
8 | a named function--you can invoke it, pass it arguments, return values from it,
9 | and take references to it. Yet you can only access an anonymous function by
10 | reference (L), not by name.
11 |
12 | X
13 | X
14 | X
15 |
16 | A Perl idiom known as a I uses hashes to associate input with
17 | behavior:
18 |
19 | =begin programlisting
20 |
21 | my %dispatch = (
22 | plus => \&add_two_numbers,
23 | minus => \&subtract_two_numbers,
24 | times => \&multiply_two_numbers,
25 | );
26 |
27 | sub add_two_numbers { $_[0] + $_[1] }
28 | sub subtract_two_numbers { $_[0] - $_[1] }
29 | sub multiply_two_numbers { $_[0] * $_[1] }
30 |
31 | sub dispatch {
32 | my ($left, $op, $right) = @_;
33 |
34 | return unless exists $dispatch{ $op };
35 |
36 | return $dispatch{ $op }->( $left, $right );
37 | }
38 |
39 | =end programlisting
40 |
41 | The C function takes arguments of the form C<(2, 'times', 2)>,
42 | evaluates the operation, and returns the result. A trivial calculator
43 | application could use C to figure out which calculation to perform
44 | based on user input.
45 |
46 | =head2 Declaring Anonymous Functions
47 |
48 | X>
49 |
50 | The C builtin used without a name creates and returns an anonymous
51 | function. Use this function reference where you'd use a reference to a named
52 | function, such as to declare the dispatch table's functions in place:
53 |
54 | =begin programlisting
55 |
56 | my %dispatch = (
57 | plus => sub { $_[0] + $_[1] },
58 | minus => sub { $_[0] - $_[1] },
59 | times => sub { $_[0] * $_[1] },
60 | dividedby => sub { $_[0] / $_[1] },
61 | raisedto => sub { $_[0] ** $_[1] },
62 | );
63 |
64 | =end programlisting
65 |
66 | =begin tip Defensive Dispatch
67 |
68 | Only those functions within this dispatch table are available for users to
69 | call. If your dispatch function used a user-provided string as the literal name
70 | of functions, a malicious user could call any function anywhere by passing a
71 | fully-qualified name such as C<'Internal::Functions::malicious_function'>.
72 |
73 | =end tip
74 |
75 | You may also see anonymous functions passed as function arguments:
76 |
77 | =begin programlisting
78 |
79 | sub invoke_anon_function {
80 | my $func = shift;
81 | return $func->( @_ );
82 | }
83 |
84 | sub named_func {
85 | say 'I am a named function!';
86 | }
87 |
88 | invoke_anon_function( \&named_func );
89 | invoke_anon_function( B );
90 |
91 | =end programlisting
92 |
93 | =head2 Anonymous Function Names
94 |
95 | X
96 | X>
97 |
98 | Use introspection to determine whether a function is named or anonymous,
99 | whether through C or the CPAN module C's C
100 | function:
101 |
102 | =begin programlisting
103 |
104 | package ShowCaller;
105 |
106 | sub show_caller {
107 | my ($package, $file, $line, $sub) = caller(1);
108 | say "Called from $sub in $package:$file:$line";
109 | }
110 |
111 | sub main {
112 | my $anon_sub = sub { show_caller() };
113 | show_caller();
114 | $anon_sub->();
115 | }
116 |
117 | main();
118 |
119 | =end programlisting
120 |
121 | The result may be surprising:
122 |
123 | =begin screen
124 |
125 | Called from ShowCaller::B
126 | in ShowCaller:anoncaller.pl:20
127 | Called from ShowCaller::B<__ANON__>
128 | in ShowCaller:anoncaller.pl:17
129 |
130 | =end screen
131 |
132 | X>
133 |
134 | The C<__ANON__> in the second line of output demonstrates that the anonymous
135 | function has no name that Perl can identify. The CPAN module C's
136 | C function allows you to attach names to anonymous functions:
137 |
138 | =begin programlisting
139 |
140 | use Sub::Name;
141 | use Sub::Identify 'sub_name';
142 |
143 | my $anon = sub {};
144 | say sub_name( $anon );
145 |
146 | my $named = subname( 'pseudo-anonymous', $anon );
147 | say sub_name( $named );
148 | say sub_name( $anon );
149 |
150 | say sub_name( sub {} );
151 |
152 | =end programlisting
153 |
154 | This program produces:
155 |
156 | =begin screen
157 |
158 | __ANON__
159 | pseudo-anonymous
160 | pseudo-anonymous
161 | __ANON__
162 |
163 | =end screen
164 |
165 | Be aware that both references refer to the same underlying anonymous function.
166 | Using C on one reference will change that underlying function; all
167 | other references to that function will see the new name.
168 |
169 | =head2 Implicit Anonymous Functions
170 |
171 | X
172 |
173 | X>
174 |
175 | Perl allows you to declare anonymous functions as function arguments without
176 | using the C keyword. Though this feature exists nominally to enable
177 | programmers to write their own syntax such as that for C