Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
25515 lines (15198 sloc) 823 KB
# [[[ HEADER ]]]
use RPerl;
package RPerl::Learning;
use strict;
use warnings;
our $VERSION = 0.191_000;
# [[[ OO INHERITANCE ]]]
# NEED FIX: why does the following 'use parent' command cause $VERSION to become undefined???
#use parent qw(RPerl::CompileUnit::Module::Class);
#use RPerl::CompileUnit::Module::Class;
# [[[ CRITICS ]]]
## no critic qw(ProhibitUselessNoCritic ProhibitMagicNumbers RequireCheckedSyscalls) # USER DEFAULT 1: allow numeric values & print operator
## no critic qw(ProhibitUnreachableCode RequirePodSections RequirePodAtEnd) # DEVELOPER DEFAULT 1b: allow POD & unreachable or POD-commented code, must be after line 1
# [[[ OO PROPERTIES ]]]
our hashref $properties = {};
1; # end of class
__END__
=encoding utf8
=for comment DEV NOTE: BEGIN INLINE CSS DIV
=begin html
<div id="scoped-content"><style type="text/css" scoped>
table.rperl {
border-style: solid;
border-width: 2px;
}
table.rperl > tbody > tr > th {
background-color: #e0e0e0;
text-align: center;
}
table.rperl > tbody > tr:nth-child(odd) { background-color: #f5f5f5; }
table.rperl > tbody > tr:nth-child(even) { background-color: #ffffff; }
table.rperl > tbody > tr > th, td {
border-style: solid;
border-width: 1px;
border-color: #cccccc;
padding: 5px;
}
/* disable ".pod p" margins inside tables only */
table.rperl > tbody > tr > th > p { margin: 0px; }
table.rperl > tbody > tr > td > p { margin: 0px; }
/* right alignment for numeric precedence column of operators tables */
table.operators > tbody > tr > td:nth-child(5) { text-align: right; }
</style>
=end html
=head1 NAME
Learning RPerl
=head1 COPYRIGHT
Learning RPerl is Copyright © 2013, 2014, 2015, 2016, 2017 William N. Braswell, Jr.
All Rights Reserved.
Learning RPerl is part of the RPerl Family of software and documentation.
=head1 BOOK TITLE
=begin text
.;,..
.2prp02;'.
,0LRRRLLp1;.
.,20LRPEEPRL02'.
.'2rREEEEPRRLp1:,.
.1pLRPEEEPRRLLrl;.
.;2lpLREEEEEPRRLpl2,.
.':lrLPEEEPPPPPRRLLpl:,.
.'20LRPPPPPPPEEPRLLrpl:'.
.2rLRPPRRPPPEEPRRLLrp1;'.
.;lpLRRRRRPPPEEEPLLLrr0:'.
.,1LRRRLLRPPPRRRRLLLrr01,.
.,1pLRRRRLLRRRRRLLLLrrpl:'.
.:lrLRRLLRLLLLLLLrrrrp02,.
..:lpLRRRRLLLLLLLrppp002,.
.';1pLLRRLLLrpprpp0ppl2,.
.'1prLRRLLrpprLrrrLLL0:. ....
..;1pLLLLLLLLLLLLLLLLr0:. '0LLLLr01;..
.;20rrrLLLLLLLLrprLLLrl:'. 'rEEEEEEEEPRL1,.
.':10pLLLLLLLLLrp0pprp02;.. ;LPPEPPEEPPPRLLp2.
.';1rLLrrrrpppp0000pp0l1;'.. ...',;::2222222::;,'.. 2REEPPPPPPRRLLrrp2.
.,20rLLrrrrrpppppprrrrrrrpl2:221lppprLLRPPPPEEEEEEEEEEPERLL021LEEPPLrprrprrpppLL0.
.,1prprprrrLLLLRPPPEEEEPPPPPPRPPRRRRRLLRRPE333EEEE3EE33333EPRPERLpppprp000prLp1:,..
.,20rrppLRPPEEEEEEEEEEEEPPRRRRLLLLLLLRRPPPPPRRRPPEE33333PREEEEEPRLppp0pplll0p0001:'.
.';20LPEEEEEEEEE3EEEEEPPRRLLLLLLLLLLRRLLLLLLLRPPEPPEEERLLLLLLLrrrpl0l;'..'',;;::,.
'0LPEEEEEEEEEEPRRPPPRRRRLLLLrrLLrrLrprLLLrrLLLrLLL010prrLLrpp00:.
;rRPEE3EPPEERLLLLRPPLLLLLrrp0ll0p0l0p0l112:1lll2:1lll0l0pLLRp.
':lREPPEPPPRLRPEERLLLLrprLLLr0ll01:1l1::12::::2::2::::1120L0.
.:0prLPPPPRLLRPPRRLLLrrrLLLLRRPLpll2:;::;,:12::::,,,;;;::;:200,
.:0LLRRRPRPEPLLLLRRLrrLRRRRRLLLLrpp00l2:2222112211:,,,'',;:,,2l0,
...'',:1lpLRRLRLLLLLLLREEEEERrppppp0ppl11lp0pp0012:;;,,;;;,;2l1.
.,1rRPPPPPPRRPEEEEPLrLLrrpprLLLLrrrLrrp1:;;,;::;;20l;
.:LEEEPRrpppppppppprLLRPPPRRRRRLrrp0l2222::22101'
'rPPPLplll121llll0pprrrpppprLr0l12222221lll2'.
.;0PPRLLrpll11222:;;,,,,:10rrrrrrrp0ll1:;.
.1RLrRRLLr02:;,........,;:;;;;;,'..
2r22rLrpp1;.
.lL2;1l12'
.0L;.2L0.
,2:'. ,rp;,0L0. .,2;..
.:1l00pLLrprRPp2221ll,.
.',,;;;,,;:10Lr1'.
'0l'
.ll'
':::2pp1:,.....',.
..'';2ll1;,;::21l111;..
..,'... ...',;;...
=end text
=begin man
.;,..
.2prp02;'.
,0LRRRLLp1;.
.,20LRPEEPRL02'.
.'2rREEEEPRRLp1:,.
.1pLRPEEEPRRLLrl;.
.;2lpLREEEEEPRRLpl2,.
.':lrLPEEEPPPPPRRLLpl:,.
.'20LRPPPPPPPEEPRLLrpl:'.
.2rLRPPRRPPPEEPRRLLrp1;'.
.;lpLRRRRRPPPEEEPLLLrr0:'.
.,1LRRRLLRPPPRRRRLLLrr01,.
.,1pLRRRRLLRRRRRLLLLrrpl:'.
.:lrLRRLLRLLLLLLLrrrrp02,.
..:lpLRRRRLLLLLLLrppp002,.
.';1pLLRRLLLrpprpp0ppl2,.
.'1prLRRLLrpprLrrrLLL0:. ....
..;1pLLLLLLLLLLLLLLLLr0:. '0LLLLr01;..
.;20rrrLLLLLLLLrprLLLrl:'. 'rEEEEEEEEPRL1,.
.':10pLLLLLLLLLrp0pprp02;.. ;LPPEPPEEPPPRLLp2.
.';1rLLrrrrpppp0000pp0l1;'.. ...',;::2222222::;,'.. 2REEPPPPPPRRLLrrp2.
.,20rLLrrrrrpppppprrrrrrrpl2:221lppprLLRPPPPEEEEEEEEEEPERLL021LEEPPLrprrprrpppLL0.
.,1prprprrrLLLLRPPPEEEEPPPPPPRPPRRRRRLLRRPE333EEEE3EE33333EPRPERLpppprp000prLp1:,..
.,20rrppLRPPEEEEEEEEEEEEPPRRRRLLLLLLLRRPPPPPRRRPPEE33333PREEEEEPRLppp0pplll0p0001:'.
.';20LPEEEEEEEEE3EEEEEPPRRLLLLLLLLLLRRLLLLLLLRPPEPPEEERLLLLLLLrrrpl0l;'..'',;;::,.
'0LPEEEEEEEEEEPRRPPPRRRRLLLLrrLLrrLrprLLLrrLLLrLLL010prrLLrpp00:.
;rRPEE3EPPEERLLLLRPPLLLLLrrp0ll0p0l0p0l112:1lll2:1lll0l0pLLRp.
':lREPPEPPPRLRPEERLLLLrprLLLr0ll01:1l1::12::::2::2::::1120L0.
.:0prLPPPPRLLRPPRRLLLrrrLLLLRRPLpll2:;::;,:12::::,,,;;;::;:200,
.:0LLRRRPRPEPLLLLRRLrrLRRRRRLLLLrpp00l2:2222112211:,,,'',;:,,2l0,
...'',:1lpLRRLRLLLLLLLREEEEERrppppp0ppl11lp0pp0012:;;,,;;;,;2l1.
.,1rRPPPPPPRRPEEEEPLrLLrrpprLLLLrrrLrrp1:;;,;::;;20l;
.:LEEEPRrpppppppppprLLRPPPRRRRRLrrp0l2222::22101'
'rPPPLplll121llll0pprrrpppprLr0l12222221lll2'.
.;0PPRLLrpll11222:;;,,,,:10rrrrrrrp0ll1:;.
.1RLrRRLLr02:;,........,;:;;;;;,'..
2r22rLrpp1;.
.lL2;1l12'
.0L;.2L0.
,2:'. ,rp;,0L0. .,2;..
.:1l00pLLrprRPp2221ll,.
.',,;;;,,;:10Lr1'.
'0l'
.ll'
':::2pp1:,.....',.
..'';2ll1;,;::21l111;..
..,'... ...',;;...
=end man
=for man
=begin docbook
.;,..
.2prp02;'.
,0LRRRLLp1;.
.,20LRPEEPRL02'.
.'2rREEEEPRRLp1:,.
.1pLRPEEEPRRLLrl;.
.;2lpLREEEEEPRRLpl2,.
.':lrLPEEEPPPPPRRLLpl:,.
.'20LRPPPPPPPEEPRLLrpl:'.
.2rLRPPRRPPPEEPRRLLrp1;'.
.;lpLRRRRRPPPEEEPLLLrr0:'.
.,1LRRRLLRPPPRRRRLLLrr01,.
.,1pLRRRRLLRRRRRLLLLrrpl:'.
.:lrLRRLLRLLLLLLLrrrrp02,.
..:lpLRRRRLLLLLLLrppp002,.
.';1pLLRRLLLrpprpp0ppl2,.
.'1prLRRLLrpprLrrrLLL0:. ....
..;1pLLLLLLLLLLLLLLLLr0:. '0LLLLr01;..
.;20rrrLLLLLLLLrprLLLrl:'. 'rEEEEEEEEPRL1,.
.':10pLLLLLLLLLrp0pprp02;.. ;LPPEPPEEPPPRLLp2.
.';1rLLrrrrpppp0000pp0l1;'.. ...',;::2222222::;,'.. 2REEPPPPPPRRLLrrp2.
.,20rLLrrrrrpppppprrrrrrrpl2:221lppprLLRPPPPEEEEEEEEEEPERLL021LEEPPLrprrprrpppLL0.
.,1prprprrrLLLLRPPPEEEEPPPPPPRPPRRRRRLLRRPE333EEEE3EE33333EPRPERLpppprp000prLp1:,..
.,20rrppLRPPEEEEEEEEEEEEPPRRRRLLLLLLLRRPPPPPRRRPPEE33333PREEEEEPRLppp0pplll0p0001:'.
.';20LPEEEEEEEEE3EEEEEPPRRLLLLLLLLLLRRLLLLLLLRPPEPPEEERLLLLLLLrrrpl0l;'..'',;;::,.
'0LPEEEEEEEEEEPRRPPPRRRRLLLLrrLLrrLrprLLLrrLLLrLLL010prrLLrpp00:.
;rRPEE3EPPEERLLLLRPPLLLLLrrp0ll0p0l0p0l112:1lll2:1lll0l0pLLRp.
':lREPPEPPPRLRPEERLLLLrprLLLr0ll01:1l1::12::::2::2::::1120L0.
.:0prLPPPPRLLRPPRRLLLrrrLLLLRRPLpll2:;::;,:12::::,,,;;;::;:200,
.:0LLRRRPRPEPLLLLRRLrrLRRRRRLLLLrpp00l2:2222112211:,,,'',;:,,2l0,
...'',:1lpLRRLRLLLLLLLREEEEERrppppp0ppl11lp0pp0012:;;,,;;;,;2l1.
.,1rRPPPPPPRRPEEEEPLrLLrrpprLLLLrrrLrrp1:;;,;::;;20l;
.:LEEEPRrpppppppppprLLRPPPRRRRRLrrp0l2222::22101'
'rPPPLplll121llll0pprrrpppprLr0l12222221lll2'.
.;0PPRLLrpll11222:;;,,,,:10rrrrrrrp0ll1:;.
.1RLrRRLLr02:;,........,;:;;;;;,'..
2r22rLrpp1;.
.lL2;1l12'
.0L;.2L0.
,2:'. ,rp;,0L0. .,2;..
.:1l00pLLrprRPp2221ll,.
.',,;;;,,;:10Lr1'.
'0l'
.ll'
':::2pp1:,.....',.
..'';2ll1;,;::21l111;..
..,'... ...',;;...
=end docbook
=for html <img src="http://www.rperl.org/images/roadrunner_engraving.jpg" width="90%">
=for html <u>
B<Learning RPerl>
=for html </u>
~ or ~
=for html <u>
B<Let's Write Fast Perl!>
=for html </u>
~ affectionately known as ~
=for html <u>
B<The Roadrunner Book>
=for html </u>
.
X<br>
...
X<br>
.....
X<br>
.......
X<br>
being
X<br>
.......
X<br>
.....
X<br>
...
X<br>
.
B<The Official Introductory-Level Reference, User Manual, and Educational Documentation>
~ for ~
B<Restricted Perl, The Optimizing Perl 5 Compiler>
X<br>
=head1 DEDICATION
For Anna.
X<br>
=head1 EDITION
0th Edition, Pre-Release Copy
X<br>
=head1 TABLE OF CONTENTS: CHAPTERS AT-A-GLANCE
=over
=item * L</FOREWORD>
=item * L</PREFACE>
=item * L</CHAPTER 1: INTRODUCTION>
=item * L</CHAPTER 2: SCALAR VALUES & VARIABLES (NUMBERS & TEXT)>
=item * L</CHAPTER 3: ARRAY VALUES & VARIABLES>
=item * L</CHAPTER 4: ORGANIZING BY SUBROUTINES>
=item * L</CHAPTER 5: READING & WRITING FILES>
=item * L</CHAPTER 6: HASH VALUES & VARIABLES>
=item * L</CHAPTER 7: THE REGULAR EXPRESSION SUB-LANGUAGE>
=item * L</CHAPTER 8: MATCHING BY REGULAR EXPRESSIONS>
=item * L</CHAPTER 9: PROCESSING BY REGULAR EXPRESSIONS>
=item * L</CHAPTER 10: ADDITIONAL CONTROL STRUCTURES>
=item * L</CHAPTER 11: CLASSES, PACKAGES, MODULES, LIBRARIES>
=item * L</CHAPTER 12: TESTING FILES & DIRECTORIES>
=item * L</CHAPTER 13: MANIPULATING FILES & DIRECTORIES>
=item * L</CHAPTER 14: SORTING TEXT VALUES>
=item * L</CHAPTER 15: ADDITIONAL SPECIAL OPERATORS>
=item * L</CHAPTER 16: MANAGING OPERATING SYSTEM PROCESSES>
=item * L</CHAPTER 17: ADDITIONAL ADVANCED TECHNIQUES>
=item * L</APPENDIX A: EXERCISE ANSWERS>
=item * L</APPENDIX B: RPERL COMMAND-LINE ARGUMENTS>
=item * L</APPENDIX C: RPERL CRITICS>
=item * L</APPENDIX D: RPERL GRAMMAR>
=item * L</APPENDIX E: BEYOND THE ROADRUNNER>
=back
X<br>
=head1 FOREWORD
[ INSERT FOREWORD CONTENT HERE ]
X<br>
=head1 PREFACE
=head2 Section 0.1: Who I Am
My name is William N. Braswell, Jr.; I am also known by a number of other names including Will the Chill, The Voice In The Wilderness, Skipper Brassie ("braz-ee"), and just Will.
I have a degree in computer science and mathematics from Texas Tech University, I have worked as a Perl software developer for over 15 years, and I am the founder of the Auto-Parallel Technologies consulting company.
L<LinkedIn Profile|https://www.linkedin.com/in/williambraswell>
L<GitHub Profile|https://github.com/wbraswell>
I am 1 of 3 co-founders of the Perl 11 movement.
L<Perl11.org|http://perl11.org/>
I am also the President of the Austin Perl Mongers.
L<Austin.pm|http://austin.pm>
Most importantly, I am the creator of the RPerl optimizing compiler for Perl 5, about which you are currently reading!
L<RPerl.org|http://rperl.org>
=head2 Section 0.2: Why I Wrote This Book
Using RPerl is different enough from normal Perl 5 to necessitate the creation of in-depth user documentation.
Manual pages and cookbooks and example source code alone are not enough, only a full textbook can provide the level of detail necessary to truly learn RPerl.
This is that textbook.
=head2 Section 0.3: History Of This Book
RPerl v1.0 was released on US Independence Day, July 4th, 2015; 6 days later, work began on the source code solution to exercise 1 of chapter 1 of this book:
L<First Learning RPerl Commit on GitHub|https://github.com/wbraswell/rperl/commit/8c3dec4448fbed6bba04f92f9f23759c5512f2e9>
Significant GitHub commit dates may be viewed by forking the RPerl git repository and executing the following C<git> command:
=for rperl X<noncode>
$ git log --reverse --all --date=short --pretty='%cd: %s' | grep 'Learning RPerl'
2015-07-10: Learning RPerl, Chapter 1, Exercise 1, Hello World
...
=for rperl X</noncode>
=head2 Section 0.4: TPF Grants
This book was made possible in part by 2 generous grants from The Perl Foundation, as part of the September 2015 and January / February 2016 rounds of funding.
Special thanks to TPF Grants Committee Secretary, Makoto Nozaki; TPF Grant Manager, Mark Jensen; TPF Grants Committee's various supporting members; and everyone who gave positive feedback on the grant proposals.
A history of TPF grant #1 may be found at the following links:
=over 16
=item * L<Call For Grant Proposals|http://news.perlfoundation.org/2015/09/call-for-grant-proposals-sept.html>
=item * L<Grant Proposal|http://news.perlfoundation.org/2015/09/grant-proposal-rperl-user-docu.html>
=item * L<Grant Proposals|http://news.perlfoundation.org/2015/09/september-2015-grant-proposals-1.html>
=item * L<Grant Proposal Votes|http://news.perlfoundation.org/2015/10/september-2015-grant-votes.html>
=item * L<Grant Report 1|http://news.perlfoundation.org/2015/10/grant-report-rperl-user-docume.html>
=item * L<Grant Report 2|http://news.perlfoundation.org/2015/12/grant-report-rperl-user-docume-1.html>
=item * L<Grant Report 3|http://news.perlfoundation.org/2016/01/grant-report-rperl-user-docume-2.html>
=back
A history of TPF grant #2 may be found at the following links:
=over 16
=item * L<Grant Proposal: RPerl User Documentation, Part 2|http://news.perlfoundation.org/2016/02/grant-proposal-rperl-user-docu-1.html>
=item * L<Jan E<sol> Feb 2016 Grant Votes|http://news.perlfoundation.org/2016/02/janfeb-2016-grant-votes.html>
=back
=head2 Section 0.5: Acknowledgements & Thanks
Countless people have contributed to the development of RPerl; from source code to bug testing to financial donations to emotional support, it truly takes a village to build a compiler!
Below are the contents of the official RPerl thank-you file, listing the handles (online nicknames) and names of the most important RPerl contributors. If you don't already know who these people are, you will be pleasantly surprised by researching each of them.
L<Latest THANKS File|https://github.com/wbraswell/rperl/blob/master/THANKS>
=for rperl X<noncode>
Many Thanks To irc.perl.org:
#perl5 Founder timtoady
#perl6 Founder timtoady (again)
#perl11 Founders ingy & rurban & willthechill (yours truly)
#perl11 Members bulk88 & mst
#inline Founders ingy (again) & nwatkiss
#inline Members davido & mohawk & sisyphus
Additional Thanks To:
Eyapp Creator Casiano Rodriguez-Leon, PhD
Austin Perl Mongers
All RPerl Contributors & Users & Supporters
=for rperl X</noncode>
=head2 Section 0.6: Defense / Apology
I'm sure I will make errors while writing this book.
I may even upset some people, particularly those who have an emotional or financial investment in slow Perl software.
Despite my best efforts, I remain a fallible human being; thus, bad spelling and grammer and run-on sentences and parts that are hard to understand and parts that are not funny and formattiNg errors and bad spelling adn repetitions and other annoyances will doubtless plague this tome but we must not allow such trivialities as, improper punctuation to affect our willingness and ability to learn how to write super-fast RPerl software.
If you find a mistake in this book (other than in the immediately preceding paragraph), please utilize the following link to create a new GitHub issue (bug report) using a title starting with the words "Learning RPerl":
L<New GitHub Issue|https://github.com/wbraswell/rperl/issues/new>
I will try my best to create an engaging and educational experience for you, the reader; however, in anticipation of the inevitable disappointment you may experience, I can only humbly offer...
B<I'M SORRY!>
=head2 Section 0.7: POD
"The Pod format is not necessarily sufficient for writing a book."
L<http://perldoc.perl.org/perlpod.html>
~ Saint Larry Wall & Sean M. Burke
X<br>
"Challenge accepted."
L<https://github.com/wbraswell/rperl/blob/master/script/development/pod2rperlhtml.pl>
~ Will Braswell
X<br>
=head1 CHAPTER 1: INTRODUCTION
=head2 Section 1.1: Welcome To The Roadrunner Book!
You are about to learn the basic concepts of writing software using the RPerl optimizing compiler for the Perl computer programming language. With the skills gained by reading this book, you will be empowered to create new super-fast RPerl programs which can be intermixed with the enormous amount of existing Perl software available on the Internet.
This book is named and stylized for the animal mascot for RPerl, Roadie the Roadrunner. RPerl, like Roadie, I<"runs really fast">.
Throughout this text, the following 14 typography conventions are utilized:
=over
=item * "Literal Quotation"
=item * I<"First Occurrence Of Key Concept">
=item * I<Emphasis>
=item * B<Stronger Emphasis>
=item * F</path/to/program.pl>
=item * B<I<Program Name>>
=for html <u>
=item * B<Book Or Document Title>
=item * I<BEST PRACTICES>
=for html </u>
=item * L<Hyperlink|http://rperl.org>
=item * C<$code_snippet = 'unhighlighted';>
=item * C<`command_line_program.pl --with --arguments`> (Only Include Characters Between `Backquotes` When Running Command; Discard Backquote Characters Themselves)
=item * ...
my string $code_block = 'highlighted on RPerl.org & MetaCPAN.org'; # with comments
my integer $more_code = 17; # http://www.catb.org/jargon/html/R/random-numbers.html
return 'end of indented code block';
=item * ...
=for rperl X<noncode>
$ command_line_program.pl --with --arguments
Please provide input: foo bar
Your output is: howdy howdy howdy
=for rperl X</noncode>
=item * ...
=for rperl X<noncode>
Documentation referring to `command_line_program.pl --with --arguments` among other things.
When executed, the above command accepts as input the string 'foo bar',
and displays as output the string 'howdy howdy howdy'.
=for rperl X</noncode>
=back
=head2 Section 1.2: Learning Perl
=begin text
This book is purposefully patterned after the popular educational text B<Learning Perl>, affectionately known as the Llama Book. Both the Roadrunner Book and the Llama book are meant as introductory texts on Perl topics. The Llama Book is focused on normal Perl, and the Roadrunner Book is focused on optimized Perl.
This book copies the same chapter topics as B<Learning Perl>, but all content is re-written for RPerl. B<Learning RPerl> also copies the same exercise concepts as B<Learning Perl>, but all solutions are re-written in RPerl. Both books are canonical and may be used together in the classroom; the source code solutions are meant to be compared side-by-side as textbook examples of normal Perl versus optimized Perl.
Please support the Perl community by purchasing a copy of B<Learning Perl, 7th Edition> from our friends at O'Reilly:
=end text
=begin html
<p>This book is purposefully patterned after the popular educational text <u><b>Learning Perl</b></u>, affectionately known as the Llama Book. Both the Roadrunner Book and the Llama book are meant as introductory texts on Perl topics. The Llama Book is focused on normal Perl, and the Roadrunner Book is focused on optimized Perl.</p>
<p>This book copies the same chapter topics as <u><b>Learning Perl</b></u>, but all content is re-written for RPerl. <u><b>Learning RPerl</b></u> also copies the same exercise concepts as <u><b>Learning Perl</b></u>, but all solutions are re-written in RPerl. Both books are canonical and may be used together in the classroom; the source code solutions are meant to be compared side-by-side as textbook examples of normal Perl versus optimized Perl.</p>
<p>Please support the Perl community by purchasing a copy of <u><b>Learning Perl, 7th Edition</b></u> from our friends at O'Reilly:</p>
=end html
L<http://shop.oreilly.com/product/0636920049517.do>
=head2 Section 1.3: Is This Book A Good Choice For You?
=over
=item * Are you totally new to computer programming, and you want to learn how to write your first program?
=item * Do you already know Perl, and now you want to make your Perl code run faster?
=item * Do you already know some other computer language, and Perl has always intrigued you?
=item * Do you love learning about new languages and compilers?
=item * Do you miss your favorite old language Perl, and you're looking for a legitimate reason to go back?
=item * Are you a scientist and you just want your code to run really fast without the headaches of C or C++?
=back
If you answered "yes" to any of these questions, then the Roadrunner Book is definitely for you!
If you answered "no" to all of these questions, then this book may still be for you, give it a try!
If you hate Perl, or only love slow software, or wish all computers would explode, then we suggest some soul-searching and a L<few|https://www.youtube.com/watch?v=UScm9avQM1Y> L<Saint|https://www.youtube.com/watch?v=SKqBmAHwSkg> L<Larry|https://www.youtube.com/watch?v=G49RUPv5-NU> L<videos|https://www.youtube.com/watch?v=aNAtbYSxzuA>. You'll thank us in the morning.
=head2 Section 1.4: Why Aren't There More Footnotes?
This is a purposefully simple book, in the same way RPerl is a purposefully simple subset of the full Perl 5 programming language.
=head2 Section 1.5: What About Educational Programming Exercises?
There are one or more programming exercises at the end of every chapter, and full answers to each problem are given near the end of the book in Appendix A.
For maximum educational effect, we suggest you attempt to write each piece of code on your own before looking at our solutions.
If you are using this as an official textbook for certification or academic credit, such as at LAMPuniversity.org or a traditional school, you are obviously expected to write all your own code without referring to our or anyone else's solutions whatsoever. We suggest you enclose Appendix A with a paper clip or discard it altogether to avoid the potential for accidental academic dishonesty.
=head2 Section 1.6: How Long Should Each Exercise Take To Complete?
The numbers at the beginning of each exercise indicate the approximate number of minutes required for an average person to reach a full working solution. If it takes you less time, good for you! If it takes you more time, don't worry, it's no big deal; learning technical skills requires time and dedication. All experts were once novices.
=head2 Section 1.7: What If I Want To Teach RPerl?
Thank you for helping spread the love of Perl and the speed of RPerl!
As previously mentioned, this book may either be used solo or combined with the Llama Book. For students who are not already familiar with Perl, you may wish to use this text alone in order to simplify and ease the learning experience. For students who are already familiar with Perl or other dynamic programming languages like the snake or the red gemstone, you may wish to use both textbooks for a more in-depth compare-and-contrast approach.
=head2 Section 1.8: What Does The Name RPerl Actually Mean?
RPerl stands for I<"Restricted Perl">, in that we restrict our use of Perl to those parts which can be made to run fast. RPerl also stands for I<"Revolutionary Perl">, in that we hope RPerl's speed will revolutionize the software development industry, or at least the Perl community. RPerl might even stand for I<"Roadrunner Perl">, in that it I<runs really fast>.
=head2 Section 1.9: Why Did Will Invent RPerl?
Will loves Perl and the Perl community.
Will is a scientist and needs his code to run really fast.
Will doesn't like the hassle of writing code in C or C++ or XS or Inline::C or Inline::CPP.
Will waited a decade or two before realizing he had to do it himself.
=head2 Section 1.10: Why Didn't Will Just Use Normal Perl?
Dynamic languages like Perl are fast at running some kinds of computational actions, such as regular expressions (text data pattern matching) and reading from a database.
Unfortunately, dynamic languages are slow at running general-purpose computations, such as arithmetic and moving data around in memory. Sometimes very slow.
Dynamic languages like Perl are also flexible, powerful, and relatively easy to learn. Sometimes too flexible.
RPerl's goal is to keep all of Perl's power and ease-of-use, while removing the redundant parts of Perl's flexibility in order to gain a major runtime speed boost.
The most complex and flexible parts of Perl are called I<"high magic">, so RPerl is focused on supporting the I<"low magic"> parts of Perl which can be made to run fast.
=head2 Section 1.11: Is RPerl Simple Or Complicated?
RPerl is specifically designed to remove the confusing and overly-complicated parts of Perl.
RPerl also introduces a number of additional rules and templates which are not present in normal Perl, notably including the use of real data types.
The net effect of removing Perl complexity and adding RPerl rules falls in favor of RPerl, due primarily to the exceedingly complex nature of Perl.
In other words, RPerl is easier to learn and use than dynamic languages like normal Perl, and most any other language in general.
=head2 Section 1.12: How Is RPerl Being Promoted?
The RPerl team has been regularly promoting RPerl in a number of physical and digital venues, including but not limited to:
=over
=item * YAPC::NA L<http://www.yapcna.org>
=item * Austin Perl Mongers L<http://www.austin.pm>
=item * RPerl Website L<http://www.rperl.org>
=item * Github L<https://github.com/wbraswell/rperl>
=item * Facebook Page L<https://www.facebook.com/rperlcompiler>
=item * Facebook Groups L<https://www.facebook.com/groups/perlprogrammers> L<https://www.facebook.com/groups/perlmonger>
=item * Twitter L<https://twitter.com/rperlcompiler>
=item * PerlMonks L<http://perlmonks.org>
=item * Perl Blogs L<http://blogs.perl.org>
=item * IRC #perl11 L<http://irc.lc/magnet/perl11/rperl_newbie@@@>
=back
=head2 Section 1.13: What Is The RPerl Community Up To?
As of US Independence Day 2016, RPerl v2.0 (codename I<Pioneer>) has been publicly released and is in use by a number of early adopters around the world.
RPerl development is proceeding with financial support from both Kickstarter crowdfunding and official grant monies from The Perl Foundation.
The RPerl community is beginning to grow, and there are a number of exciting RPerl projects currently in the works.
If you would like to create software libraries and applications (AKA "programs" or "apps") to be utilized by end-users, then please join the RPerl application developers group, also known as the "RPerl App Devs":
L<RPerl App Devs Group On Facebook|https://www.facebook.com/groups/1551887621787018>
L<RPerl App Devs Intake Board On Trello|https://trello.com/b/XmmPJQJj/austin-pm-rperl-app-devs-intake>
=head2 Section 1.14: What Is RPerl Meant To Do?
RPerl is a general-purpose programming language, which means you can use RPerl to efficiently and effectively implement virtually any kind of software you can imagine.
RPerl is especially well-suited for building software which benefits from speed, such as scientific simulations and graphical video games.
RPerl is also good for building software which utilizes Perl's strong-suit of string manipulation; RPerl currently supports basic string operators, with full regular expression support to be added in an upcoming version.
=head2 Section 1.15: What Is RPerl Not Meant To Do?
RPerl has purposefully disabled the most complex features of Perl, such as runtime code evaluation, secret operators, and punctuation variables. If you have purposefully designed your Perl software to depend on these high-magic features, or you are unconditionally committed to continue using high-magic language features, then maybe RPerl isn't for you.
=head2 Section 1.16: How Can I Download & Install RPerl?
Installing RPerl ranges from easy to difficult, depending on how well your operating system supports Perl and C++.
On modern operating systems with good Perl support, such as Debian or Ubuntu GNU/Linux, you should be able to install RPerl system-wide by running the following command at your terminal command prompt:
=for rperl X<noncode>
$ sudo cpan RPerl
=for rperl X</noncode>
You may also choose to use the C<`cpanm`> command for simplicity, or the C<local::lib> tool for single-user (not system-wide) installation, both of which are included in the INSTALL notes document linked below.
If RPerl is properly installed, you should see a short text message displayed when you type the following command:
=for rperl X<noncode>
$ rperl -v
=for rperl X</noncode>
On operating systems with less Perl support, you may have to perform a number of steps to successfully install RPerl, with dry technical detail available in the INSTALL notes document:
L<https://github.com/wbraswell/rperl/blob/master/INSTALL>
Unless you are an experienced programmer or system administrator, it is B<strongly> recommended you use the Xubuntu operating system. You can download the Xubuntu ISO file at the link below, then use it to create a bootable DVD disc or USB flash drive, install Xubuntu onto any computer, and issue the C<`sudo cpan RPerl`> command as described above.
L<http://xubuntu.org/getxubuntu>
If you are interested in viewing the source code of RPerl itself, you may find the latest major release of RPerl (stable) on CPAN:
L<https://metacpan.org/author/WBRASWELL>
You may find the latest development release of RPerl (possibly unstable) on Github:
L<https://github.com/wbraswell/rperl>
=head2 Section 1.17: Where Is Perl Software Stored Online?
CPAN is the I<"Comprehensive Perl Archive Network">, the world's most successful and mature centralized software network.
CPAN servers are where most public Perl software is stored, including RPerl.
L<https://en.wikipedia.org/wiki/CPAN>
L<http://www.cpan.org>
Several other programming language communities have copied the success and implementation of CPAN, including JSAN for Javascript, CRAN for R, and CCAN for C.
=head2 Section 1.18: How Can I Obtain Technical Support For RPerl?
Official RPerl technical support is provided through Auto-Parallel Technologies, Inc.
To request more information, please send an e-mail to the following address:
william DOT braswell AT autoparallel DOT com
=head2 Section 1.19: Are There Any Free Technical Support Options?
Free technical support for non-commercial users is provided by the RPerl community through Internet Relay Chat.
Server: irc.perl.org
Channel: #perl11
Easy Web Chat: L<http://irc.lc/magnet/perl11/rperl_newbie@@@>
=head2 Section 1.20: Are There Any Bugs In RPerl?
All software has small (or large) problems called I<"bugs">, and depending on who is marketing the software, they may even tell you some of the bugs are actually "features"!
RPerl is a work in progress, and may contain a number of bugs, both known and unknown. If you find a bug in RPerl, we would love to hear about it!
The primary bug-tracking platform for RPerl is Github Issues, where you may file a new bug report ("new issue") if it is not already listed:
L<https://github.com/wbraswell/rperl/issues>
Please be sure to include all of the following information in your bug report:
=over
=item * Pertinent Problem Message Output, If Long Use L<https://gist.github.com/>
=item * Operating System Version C<`cat /etc/issue`>
=item * Perl Version C<`perl -v`>
=item * RPerl Version C<`rperl -v`>
=back
Although Github Issues is strongly preferred, the RPerl development team also supports the legacy CPAN ticket system:
L<https://rt.cpan.org/Public/Dist/Display.html?Name=RPerl>
=head2 Section 1.21: How Can I Write A Program Using RPerl?
Computer programs written using the RPerl language are plain text files, which means you can use any text editor to create and modify your RPerl source code. Examples of common text editors include Notepad, Pico, and Vi.
L<http://www.vim.org>
To avoid possible file format problems, do not edit your RPerl programs using a word processor such as Wordpad, Word, OpenOffice, or LibreOffice.
Experienced RPerl developers may choose to utilize an I<"integrated development environment"> (IDE), which is a special text editor made for writing software. Examples of common Perl IDE applications include Eclipse EPIC, Padre, and Komodo (non-free).
L<http://www.epic-ide.org>
L<http://padre.perlide.org>
L<http://komodoide.com/perl>
=head2 Section 1.22: A Sample RPerl Program
#!/usr/bin/perl
# Foo Bar Arithmetic Example
# [[[ HEADER ]]]
use RPerl;
use strict;
use warnings;
our $VERSION = 0.001_000;
# [[[ CRITICS ]]]
## no critic qw(ProhibitUselessNoCritic ProhibitMagicNumbers RequireCheckedSyscalls) # USER DEFAULT 1: allow numeric values & print operator
## no critic qw(RequireInterpolationOfMetachars) # USER DEFAULT 2: allow single-quoted control characters & sigils
# [[[ OPERATIONS ]]]
my integer $foo = 21 + 12;
my integer $bar = 23 * 42 * 2;
my number $baz = to_number($bar) / $foo;
print 'have $foo = ', to_string($foo), "\n";
print 'have $bar = ', to_string($bar), "\n";
print 'have $baz = ', to_string($baz), "\n";
=head2 Section 1.23: What Are The Parts Of That Sample RPerl Program?
This program is separated by blank lines into 4 sections: shebang, header, critics, and operations.
Other than the shebang and critics, all lines beginning with C<#> are comments and can be safely ignored or discarded without affecting the program.
The I<"shebang"> section is required, always contains exactly 1 line, and is short for I<"hash bang">; referring to the two leading characters C<#!> of this line. The I<"octothorpe"> character C<#> (tic-tac-toe symbol) is called a I<"pound-sign"> when used on a telephone, and is called a I<"hash"> (or more recently and less accurately I<"hash-tag">) when used on a computer. The exclamation-point character C<!> is called a I<"bang"> when used on a computer. When appearing together as the first two characters in a plain text file, the hash and bang characters tell the operating system to run the immediately-following command (in this case the Perl interpreter located at F</usr/bin/perl>) and pass the remaining contents of the text file as input to the command. In other words, if the first line of a plain text file is C<#!/usr/bin/perl>, then that file is a Perl program.
The I<"header"> section is required and always contains 4 lines for an RPerl I<"program"> file ending in F<.pl>, or 5 lines for an RPerl I<"module"> ending in F<.pm> (covered later in Chapter 11). C<use> is recognized by Perl as a special I<"keyword"> (which is also a Perl I<"function">) which has 2 primary purposes: to load additional RPerl modules, and to enable RPerl I<"pragma"> system configuration modes. The C<use RPerl;> line is dual-purpose, it both loads the F<RPerl.pm> module and enables the special RPerl low-magic pragma. The C<use strict;> and C<use warnings;> lines enable basic Perl pragmas which require decent programming practices by the human programmers. The C<our $VERSION = 0.001_000;> line sets the version number of this RPerl program.
The I<"critics"> section is included as necessary and may contain 1 or more lines beginning with C<## no critic>, which disable the errors caused by the over-restrictive nature of some Perl::Critic policies. There are currently 6 critics commands enabled for normal RPerl users, the first 2 of which are given in this example. The "USER DEFAULT 1" C<no critic> command allows the use of numeric values such as C<21> and C<12>, as well as the common C<print> command. The C<USER DEFAULT 2> critics command allows the printing of C<'have $foo = '>, where a single-quoted C<'> string literal value contains the the dollar-sign C<$> sigil (covered later in Chapter 2).
The I<"operations"> section is required and contains 1 or more lines of general-purpose RPerl source code. This is the main body of your program. The 6 lines of source code in our example are used to perform some simple arithmetic and display the results. The C<my integer $foo = 21 + 12;> line declares a new variable named C<$foo> which will only contain non-floating-point numeric data, and which is initialized to contain the arithmetic result of numeric literal values C<21> plus C<12>. The C<my integer $bar = 23 * 42 * 2;> line does much the same thing, creating a new numeric variable named C<$bar> and initialized with C<23> times C<42> times C<2>. The C<my number $baz = to_number($bar) / $foo;> line creates a new floating-point numeric variable C<$baz>, and initializes it to the quotient of the C<$bar> and C<$foo> variables. The C<to_number()> RPerl type conversion I<"subroutine"> converts a non-floating-point C<integer> value to a floating-point C<number> value. (A subroutine is a user-defined operation, in this case pre-defined by the RPerl development team for your convenience; please see L</CHAPTER 4: ORGANIZING BY SUBROUTINES> for more information.)
The C<print 'have $foo = ', $foo, "\n";> and following 2 lines will display on screen (not send to paper printer) the labeled values of C<$foo>, C<$bar>, and C<$baz> respectively. The C<,> comma is used to separate multiple arguments passed to the C<print> operator. The C<to_string()> RPerl type conversion subroutine converts the numeric values to underscore-formatted string values, suitable for use via the C<print> operator. If the C<to_string()> subroutine is not used, then the displayed numeric values will still be human-readable, but will not contain the proper underscores to be accepted back into RPerl as valid numeric data. The "n" in the C<"\n"> double-quoted string literal values stands for "newline", which inserts a carriage return to place the next piece of printed data down on the following line.
=head2 Section 1.24: How Do I Run The RPerl Compiler?
Normal Perl source code is executed using a software mechanism known as I<"interpretation">, which is to say that Perl is an I<"interpreted"> language and the F</usr/bin/perl> command is called the I<"Perl interpreter">. The primary alternative to interpretation is I<"compilation">, so RPerl is a I<"compiled"> subset of the Perl language and the F</usr/bin/rperl> command is called the I<"RPerl compiler">.
Like the Perl interpreter, the RPerl compiler accepts 2 different input file types: Perl programs which end in F<.pl> and Perl modules which end in F<.pm>. Perl program files actually run and execute actions, optionally receiving some functionality from 1 or more Perl module files if specified. Perl modules do not run or execute actions themselves, they only provide functionality which must in turn be called from a Perl program, or from another Perl module which eventually gets called by a Perl program.
A list of all valid RPerl compiler options may be seen by issuing the following command:
=for rperl X<noncode>
$ rperl -?
=for rperl X</noncode>
You may find the same information by viewing the following links:
L<rperl>
L<https://metacpan.org/pod/distribution/RPerl/script/rperl>
To compile-then-execute the preceding RPerl example program, you may copy and paste the entire program (from shebang to second C<print>) into a temporary file such as F</tmp/foobar.pl>, then execute the following command:
=for rperl X<noncode>
$ rperl /tmp/foobar.pl
=for rperl X</noncode>
The output of this example program should be:
=for rperl X<noncode>
have $foo = 33
have $bar = 1_932
have $baz = 58.545_454_545_454_5
=for rperl X</noncode>
If the compilation is successful, a new compiled executable file will be created in F</tmp/foobar>. You may then directly execute the compiled program as many times as you like, without needing to recompile it using the C<`rperl`> command, and you should receive the exact same output as the non-compiled code:
=for rperl X<noncode>
$ /tmp/foobar
have $foo = 33
have $bar = 1_932
have $baz = 58.545_454_545_454_5
=for rperl X</noncode>
Please see L</CHAPTER 11: CLASSES, PACKAGES, MODULES, LIBRARIES> for more information about compiling Perl modules.
=head2 Section 1.25: A Quick Overview of RPerl
=head3 Section 1.25.1: Creator Of RPerl, Will Braswell
Will Braswell does more than just create Perl compiler software, he is also very active in several other areas of life, including but not limited to:
=over
=item * Church & Spirituality
=item * Boy Scouts of America
=item * Cane Juggling & Circus Performance
=item * Linux Operating Systems
=item * Charitable & Fraternal Organizations
=item * Homeschooling & Higher Education
=item * Astrophysics & Mathematics
=item * Entrepreneurship & Business
=item * High-Performance Computing
=item * Professional Space Exploration
=item * Family Life
=back
These areas of interest are reflected in the tone and intention of RPerl.
=head3 Section 1.25.2: History Of RPerl
The RPerl project officially began as a New Year's Resolution on January 1st, 2013. Following the grand tradition of Perl creator I<"Saint" Larry Wall>, RPerl version releases are often timed to coincide with major holidays.
After 1 year of work, RPerl v1.0beta1 was released on New Year's Day 2014, eventually followed by RPerl v1.0beta2 on Christmas 2014.
The much-anticipated RPerl v1.0 full release was made on US Independence Day 2015, and RPerl v1.2 came on Halloween 2015.
RPerl v1.3 was released on Thanksgiving 2015, followed by RPerl v1.4 on Christmas 2015, and so forth.
RPerl v1.0 was funded through a Kickstarter campaign, then RPerl v1.2 and v1.3 were funded through a second Kickstarter campaign. Work on the first 6 chapters of this book was funded, in part, by grants from The Perl Foundation.
RPerl v2.0 was released on US Independence Day 2016, exactly 1 year after v1.0 was released, in order to establish a regular annual release cycle.
=head3 Section 1.25.3: Performance Of RPerl
The question of I<"How fast is RPerl?"> does not have one simple answer; instead there are several factors and configuration modes to be taken into consideration. A relatively detailed description of the performance and modes may be found at the following link:
L<http://rperl.org/performance_benchmarks.html>
The most condensed answer is that I<"RPerl is really fast."> Utilizing RPerl's fastest execution modes, we see performance very close to the highly-optimized I<C++> programming language, which means RPerl is now among the short list of "world's fastest languages" along with C, C++, and Fortran.
=head3 Section 1.25.4: The Low-Magic Perl Commandments
The high-magic features of Perl are primarily responsible for the slow speed at which Perl executes general-purpose computations. The I<"R"> in RPerl stands for I<"Restricted">, in that we restrict ourselves to only use the low-magic features of Perl which can run really fast.
The definitive list of do's and do-not's for high-magic vs low-magic Perl programming is called I<The Low Magic Perl Commandments> (LMPC). There are 64 total commandments split into 5 groups of Ideals, Magic, Data, Operations, and Object-Orientation. The "Thou Shalt" commandments appear in the left column, and the "Thou Shalt Nots" appear on the right.
L<http://rperl.org/the_low_magic_perl_commandments.html>
=for text The LMPC draw inspiration from, and (wherever possible) work together with Damian Conway's B<Perl Best Practices> and Jeffrey Thalhammer's Perl::Critic software.
=for html <p>The LMPC draw inspiration from, and (wherever possible) work together with Damian Conway's <u><b>Perl Best Practices</b></u> and Jeffrey Thalhammer's Perl::Critic software.</p>
L<http://shop.oreilly.com/product/9780596001735.do>
L<http://search.cpan.org/~thaljef/Perl-Critic/lib/Perl/Critic/PolicySummary.pod>
=head3 Section 1.25.5: Perlism & The Book Of RPerl
I<Perlism> is the computer religion dedicated to the use, promotion, and development of the Perl family of programming languages. (Not to be confused with a spiritual religion such as Christianity, a computer religion such as Perlism is an independent and complementary belief structure.)
=for text A I<Perlite> is an adherent to the Perlism religion. Perlism has a revered founder, Saint Larry (himself a devout Christian); a prophet, I<The Voice In The Wilderness> (Will); a monastery and shrine, I<Perl Monks>; commandments, The LMPC; proverbs from Saint Larry including I<TIMTOWTDI>, I<LMFB>, and I<HTAAOF>; and canonical scriptures, including Saint Larry's B<Apocalypses> and The Voice's B<The Book Of RPerl>.
=for html <p>A <i>Perlite</i> is an adherent to the Perlism religion. Perlism has a revered founder, Saint Larry (himself a devout Christian); a prophet, <i>The Voice In The Wilderness</i> (Will); a monastary and shrine, <i>Perl Monks</i>; commandments, The LMPC; proverbs from Saint Larry including <i>TIMTOWTDI</i>, <i>LMFB</i>, and <i>HTAAOF</i>; and canonical scriptures, including Saint Larry's <u><b>Apocalypses</b></u> and The Voice's <u><b>The Book Of RPerl</b></u>.</p>
=for comment START HERE: INSERT MAN & DOCBOOK FORMATS
=for comment START HERE: INSERT MAN & DOCBOOK FORMATS
=for comment START HERE: INSERT MAN & DOCBOOK FORMATS
The Book is a description of events surrounding the creation of RPerl and the future of the Internet. It is intended to both educate and entertain.
L<http://rperl.org/the_book_of_rperl.html>
=head3 Section 1.25.6: Fun With Proverbs & Catch Phrases & Acronyms
St. Larry has given us short and powerful proverbs, some of which are meant to have a purposefully tongue-in-cheek or sarcastic interpretation.
Will has provided a corollary to each of St. Larry's official proverbs.
=begin text
my $z = q{<<< BEGIN TEXT EVAL >>>};
use Text::ASCIITable;
my Text::ASCIITable $table = Text::ASCIITable->new({alignHeadRow => 'center', drawRowLine => 1});
$table->setCols(splice @{[split /\s*\n\s*/, q{
=end text
=begin man
.TS
allbox tab(@) ;
c c
l l .
=end man
=for html <table class="rperl operators">
=begin docbook
<table id="learning_rperl-section_1.25.6-table_1" label="" frame="all" colsep="1" rowsep="1">
<title>Proverbs & Acronyms</title>
<tgroup cols="2">
=end docbook
=for man T{
=for html <tr><th>
=for docbook <thead>
=for docbook <row><entry align="center">
B<St. Larry's Original Proverb>
=for man T}@T{
=for html </th><th>
=for docbook </entry><entry align="center">
B<Will's Corollary Proverb>
=for text }]}, 1);
=for man T}
=for html </td></tr>
=for docbook </entry></row>
=for text $table->addRow(splice @{[split /\s*\n\s*/, q{
=for man T{
=for html <tr><td>
=for docbook <row><entry align="left">
3 Great Virtues Of A Programmer:
LIH (Laziness, Impatience, Hubris)
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
3 Greater Virtues Of A Programmer:
DPH (Diligence, Patience, Humility)
=for text }]}, 1);
=for man T}
=for html </td></tr>
=for docbook </entry></row>
=for text $table->addRow(splice @{[split /\s*\n\s*/, q{
=for man T{
=for html <tr><td>
=for docbook <row><entry align="left">
TIMTOWTDI (There Is More Than One Way To Do It)
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
TDNNTBMTOWTDI (There Does Not Need To Be More Than One Way To Do It)
TIOFWTDI (There Is One Fastest Way To Do It)
=for text }]}, 1);
=for man T}
=for html </th></tr>
=for docbook </entry></row>
=for docbook </thead>
=for text $table->addRow(splice @{[split /\s*\n\s*/, q{
=for man T{
=for html <tr><td>
=for docbook <tbody>
=for docbook <row><entry align="left">
LMFB (Let Many Flowers Bloom)
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
PTBF (Pick The Best Flowers)
=for text }]}, 1);
=for man T}
=for html </th></tr>
=for docbook </entry></row>
=for docbook </thead>
=for text $table->addRow(splice @{[split /\s*\n\s*/, q{
=for man T{
=for html <tr><td>
=for docbook <tbody>
=for docbook <row><entry align="left">
HTAAOF (Have The Appropriate Amount Of Fun)
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
DTAAOW (Do The Appropriate Amount Of Work)
=for text }]}, 1);
=for man T}
=for html </td></tr>
=for docbook </entry></row>
=begin text
return $table->draw( ['.=','=.','=','='], # .=============.
['|','|','|'], # | info | info |
['|-','-|','=','='], # |-===========-|
['|','|','|'], # | info | info |
["'=","='",'=','='], # '============='
['|-','-|','-','+'] # rowseperator
);
$z = q{<<< END TEXT EVAL >>>};
=end text
=for man .TE
=for html </table>
=for docbook </tbody></tgroup></table>
In addition to St. Larry's official proverbs, there are a number of other commonly-used catch phrases and ideas in the Perl community.
=begin text
my $z = q{<<< BEGIN TEXT EVAL >>>};
use Text::ASCIITable;
my Text::ASCIITable $table = Text::ASCIITable->new({alignHeadRow => 'center', drawRowLine => 1});
$table->setCols(splice @{[split /\s*\n\s*/, q{
=end text
=begin man
.TS
allbox tab(@) ;
c c
l l .
=end man
=for html <table class="rperl operators">
=begin docbook
<table id="learning_rperl-section_1.25.6-table_2" label="" frame="all" colsep="1" rowsep="1">
<title>Catch Phrases & Acronyms</title>
<tgroup cols="2">
=end docbook
=for man T{
=for html <tr><th>
=for docbook <thead>
=for docbook <row><entry align="center">
B<Original Catch Phrase>
=for man T}@T{
=for html </th><th>
=for docbook </entry><entry align="center">
B<Will's Corollary Catch Phrase>
=for text }]}, 1);
=for man T}
=for html </td></tr>
=for docbook </entry></row>
=for text $table->addRow(splice @{[split /\s*\n\s*/, q{
=for man T{
=for html <tr><td>
=for docbook <row><entry align="left">
Perl 5 Is The Camel
Perl 5 Is The Raptor
Perl 6 Is The Butterfly
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
RPerl Is The Roadrunner
=for text }]}, 1);
=for man T}
=for html </td></tr>
=for docbook </entry></row>
=for text $table->addRow(splice @{[split /\s*\n\s*/, q{
=for man T{
=for html <tr><td>
=for docbook <row><entry align="left">
Perl Is The Onion
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
RPerl Is The Scallion
=for text }]}, 1);
=for man T}
=for html </th></tr>
=for docbook </entry></row>
=for docbook </thead>
=for text $table->addRow(splice @{[split /\s*\n\s*/, q{
=for man T{
=for html <tr><td>
=for docbook <tbody>
=for docbook <row><entry align="left">
Perl Is The Swiss Army Chainsaw
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
RPerl Is The Sword
=for text }]}, 1);
=for man T}
=for html </th></tr>
=for docbook </entry></row>
=for docbook </thead>
=for text $table->addRow(splice @{[split /\s*\n\s*/, q{
=for man T{
=for html <tr><td>
=for docbook <tbody>
=for docbook <row><entry align="left">
Perl Is Line-Noise
Perl Is A Write-Only Language
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
RPerl Is Best Practices
=for text }]}, 1);
=for man T}
=for html </td></tr>
=for docbook </entry></row>
=begin text
return $table->draw( ['.=','=.','=','='], # .=============.
['|','|','|'], # | info | info |
['|-','-|','=','='], # |-===========-|
['|','|','|'], # | info | info |
["'=","='",'=','='], # '============='
['|-','-|','-','+'] # rowseperator
);
$z = q{<<< END TEXT EVAL >>>};
=end text
=for man .TE
=for html </table>
=for docbook </tbody></tgroup></table>
=head2 Section 1.26: What's New In RPerl v2.0?
The single most significant new feature included in RPerl v2.0 is automatic parallelization. This long-awaited software feature was promised from the very beginning of RPerl's initial development, with RPerl v2.0 being the originally-designated target for release of auto-parallel capabilities. We stuck to the plan and delivered on time: the 4th of July, 2016.
Automatic parallelization is now enabled on 4 parallel CPU cores by default, because quad-core CPUs are common at this time. You may utilize the C<--num_cores=8> command-line argument to double the default number of parallel cores, for example. (Please see L</B.18: Modes, Parallelize> and L</B.19: Modes, Parallelize, Number Of Cores> for more information about auto-parallelization arguments.)
Currently, shared memory parallel hardware platforms are supported, such as multi-core CPUs and supercomputers, by utilizing the L<OpenMP|https://en.wikipedia.org/wiki/OpenMP> parallelization software. In the near future we will add support for distributed memory platforms, such as clusters and the cloud, by utilizing the L<MPI|https://en.wikipedia.org/wiki/Message_Passing_Interface> parallelization software, as well as GPUs and other specialty hardware by utilizing the L<OpenCL|https://en.wikipedia.org/wiki/OpenCL> parallelization software.
RPerl triggers auto-parallelization by simply including the word 'PARALLEL' in a loop label; everything inside that loop will be automatically parallelized, including multiply-nested loops. RPerl implements the L<polytope model|https://en.wikipedia.org/wiki/Polytope_model> (AKA L<polyhedral model|http://polyhedral.info>) for loop parallelization, by utilizing the L<Pluto PolyCC|http://pluto-compiler.sourceforge.net> polytope software.
In addition to auto-parallelization, a number of other new features were released after RPerl v1.0 and by-or-before v2.0, including but not limited to:
=over
=item * Generate Stand-Alone Binary Executable Files & Shared Object Files
=item * Control Native C++ Types Used For Integer & Number Values
=item * Support SSE Data Types & Operations
=item * Support GMP Data Types & Operations
=item * Monolithic Modules
=item * Uncompile (Delete) Unwanted Compiled Files
=item * Two-Dimensional Data Structures
=back
=head2 Section 1.27: Exercises
=head3 1. Hello World [ 15 mins ]
On a computer with RPerl already installed, create a directory named F<LearningRPerl> containing a sub-directory named F<Chapter1>. Using the B<I<Foo Bar>> example program as a template, manually type a new RPerl program into a file named F<exercise_1-hello_world.pl> inside the F<LearningRPerl/Chapter1> sub-directory. The sole purpose of your first program is to use the C<print> operator and simply display the following one line of text output, followed by one newline character:
=for rperl X<noncode>
Hello, World!
=for rperl X</noncode>
Run your new program by issuing the following command at your terminal command prompt:
=for rperl X<noncode>
$ rperl -t LearningRPerl/Chapter1/exercise_1-hello_world.pl
=for rperl X</noncode>
I<HINT: You only need the "USER DEFAULT 1" C<no critic> command, so your resulting program should be 7 lines long, not counting comments or blank lines.>
=head3 2. RPerl Commands [ 15 mins ]
First, run the following RPerl command, and observe the output for use in 2a and 2b below:
=for rperl X<noncode>
$ rperl -?
=for rperl X</noncode>
2a. What are some RPerl command-line options with which you are already familiar?
2b. With which options are you unfamiliar?
Next, run the following 3 RPerl commands, for 2c and 2d below:
=for rperl X<noncode>
$ rperl -t -V LearningRPerl/Chapter1/exercise_1-hello_world.pl
$ rperl -t -D LearningRPerl/Chapter1/exercise_1-hello_world.pl
$ rperl -t -V -D LearningRPerl/Chapter1/exercise_1-hello_world.pl
=for rperl X</noncode>
2c. How do the outputs of these 3 commands differ from the output of Exercise 1?
2d. How do the outputs differ from one another?
=head3 3. Foo Bar Arithmetic [ 15 mins ]
Manually type the entire B<I<Foo Bar Arithmetic>> example program into a file named F<exercise_3-foo_bar_arithmetic.pl> inside the F<LearningPerl/Chapter1> sub-directory. (Even if you have already used copy-and-paste on the B<I<Foo Bar Arithmetic>> example program, you should still use this as an opportunity to build some RPerl muscle memory and type it in by hand.)
Modify your program by adding a new floating-point numeric variable named C<$zab>, set its value to C<$foo> divided by C<$bar> (don't forget C<to_number()>), change the starting value of C<$bar>, and use C<print> to generate the following output:
=for rperl X<noncode>
have $foo = 33
have $bar = 966
have $baz = 29.272_727_272_727_3
have $zab = 0.034_161_490_683_229_8
=for rperl X</noncode>
Run your program thusly:
=for rperl X<noncode>
$ rperl -t LearningRPerl/Chapter1/exercise_3-foo_bar_arithmetic.pl
=for rperl X</noncode>
X<br>
=head1 CHAPTER 2: SCALAR VALUES & VARIABLES (NUMBERS & TEXT)
Most programming languages include the basic principles of using named I<"variables"> to store data values such as numbers, text strings, and lists of multiple numbers or strings. Multiple variables may be created, each with different names such as C<$foo> or C<$bar> or C<$quux>, and each potentially containing a different value.
A single piece of data, such as one number or one string, is called a I<"scalar">. Multiple pieces of data combined into a single aggregate structure may be either an I<"array"> or a I<"hash">, described in chapters 3 and 6, respectively. (Although sharing the same terminology, the I<hash> data structure is not related to the I<hash> C<#> tic-tac-toe character.) In normal Perl, only scalar variable names begin with the dollar-sign C<$> I<"sigil">, while aggregate data structures are stored in variables starting with different sigils like at-sign C<@> or percent-sign C<%>. A sigil is simply a special character prefixed to a word, in order to help us quickly identify different source code components. In RPerl, all variable names begin the C<$> sigil, both scalar types and aggregate structures alike.
=for comment DEV NOTE, CORRELATION #rp400: all POD changes must be made in both RPerl.pm & RPerl/Learning.pm
RPerl provides 7 scalar data types:
=over
=item * C<boolean>
=item * C<unsigned_integer>
=item * C<integer> (core)
=item * C<gmp_integer>
=item * C<number> (core)
=item * C<character>
=item * C<string> (core)
=back
Of the 7 RPerl scalar data types, 3 are directly (natively) supported by the Perl 5 core: C<integer>, C<number>, and C<string>. This means the Perl 5 core is capable of directly identifying and storing those 3 core types. The remaining 4 non-core types are indirectly supported by the Perl 5 interpreter: C<boolean> and C<unsigned_integer> can be stored within either an C<integer> or C<number>; C<character> can be stored within a C<string>; and C<gmp_integer> is supported by the C<use bigint;> wrapper around the C<Math::BigInt::GMP> module.
When RPerl application source code is compiled from RPerl into C++, all 7 data types are natively supported by C++ for high-speed execution.
A single group of actual numeric digit(s) or quoted string character(s) is called a I<"literal">, such as:
-21 # integer or gmp_integer or number
'howdy' # string
-23.421_12 # number
1_234_567 # unsigned_integer or integer or gmp_integer or number
1_234_567_890_123_456_789_012_345_678_901_234_567_890_123_456_789_012_345 # gmp_integer
'One million, two-hundred-thirty-four thousand, five-hundred-sixty-seven' # string
'1' # character or string
'a' # character or string
"\n" # newline character or string
q{} # empty character or string
0 # boolean or unsigned_integer or integer or gmp_integer or number
=head2 Section 2.1: Numeric Data & Operators
RPerl provides 5 numeric data types:
=over
=item * C<boolean>
S< >S< >S< >S< >a boolean logic value, either 0 or 1
=item * C<unsigned_integer>
S< >S< >S< >S< >a positive whole number value, greater-than or equal to 0
=item * C<integer>
S< >S< >S< >S< >a whole number value, either negative, 0, or positive
=item * C<gmp_integer>
S< >S< >S< >S< >a possibly-very-large whole number value, either negative, 0, or positive; may safely exceed your computer's data type limits
=item * C<number>
S< >S< >S< >S< >a floating-point decimal number value, either negative, 0, or positive
=back
Perl 5 provides several I<"built-in operators"> designed for use with numeric data, which can be organized into 6 general categories:
=over
=item * Arithmetic
=item * Trigonometry
=item * Comparison (Relational & Equality)
=item * Logic
=item * Bitwise
=item * Miscellaneous
=back
Most of the operators which have names consisting of normal letters (a - z) are classified as I<"functions"> in Perl 5 terminology. Notable exceptions are the logic operators, which are simply classified as "operators" in Perl, along with most of the operators which have names consisting of special characters. For the sake of simplicity, we will only use the term "operator" throughout this textbook.
L<http://perldoc.perl.org/perlop.html>
L<http://perldoc.perl.org/perlfunc.html>
Each operator in Perl 5 (and thus RPerl) is assigned 4 important characteristics: I<"arity"> (a number), I<"fixity"> (a placement location), I<"precedence"> (a number) and I<"associativity"> (a chirality or "handedness"). Operators of unary arity accept exactly 1 input operand, binary operators accept exactly 2 operands, etc. Prefix operators appear before their respective operands, postfix appear after, infix appear between, and closed operators appear both before and after their operands. Operators with a lower numeric precedence are executed before operators with a higher precedence; in the absence of parentheses, multiplication executes before addition because multiplication has a lower precedence number. Operators with equal precedence number are grouped by (and executed in order of) associativity; in the absence of parentheses, multiple subtraction operators will execute from left to right because subtraction is left-associative, whereas multiple exponent operators will execute from right to left because exponentiation is right-associative. For more information, see the Appendix:
L</D.3: Syntax Arity, Fixity, Precedence, Associativity>
Beyond the built-in math operators in Perl 5, more advanced operators and functions are available via the MathPerl software suite, which is (perhaps unsurprisingly) optimized using the RPerl compiler.
L<MathPerl on CPAN|https://metacpan.org/release/MathPerl>
=head3 Section 2.1.1: Boolean Literals
The most memory-efficient numeric literal is C<boolean>, which represents a single I<"bit"> (binary digit) of information. A C<boolean> literal may only give the values of exactly 0 or 1.
0 # boolean
1 # boolean
-1 # not a boolean
1.5 # not a boolean
-1.5 # not a boolean
=head3 Section 2.1.2: Unsigned Integer Literals
The second most efficient numeric literal is C<unsigned_integer>, which represents a single whole (non-decimal) number greater-than or equal to 0. An C<unsigned_integer> literal may describe any positive whole number, within the data size limits of the data types supported by your operating system software and computer hardware. An C<unsigned_integer> may not describe a negative number or a non-whole number.
23 # unsigned_integer
0 # unsigned_integer
42_230 # unsigned_integer
-23 # not an unsigned_integer
42.1 # not an unsigned_integer
999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999 # bad unsigned_integer, outside data type limits
=head3 Section 2.1.3: Integer Literals
The third most efficient numeric literal is C<integer>, which represents a single whole (non-decimal) number. An C<integer> literal may describe any positive or negative whole number, within your operating system and hardware data type limits.
-23 # integer
0 # integer
42_230 # integer
42.1 # not an integer
-999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999 # bad integer, outside data type limits
=head3 Section 2.1.4: GMP Integer Literals
The GNU Multi-Precision (GMP) software library is utilized to provide the C<gmp_integer> numeric literal, representing a single whole (non-decimal) number which may safely exceed the data type limits of your operating system and hardware. A C<gmp_integer> literal may describe any positive or negative whole number, within the limits of the memory (real or virtual) available to your RPerl code.
-23 # gmp_integer
0 # gmp_integer
42_230 # gmp_integer
42.1 # not a gmp_integer
-999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999 # gmp_integer
=head3 Section 2.1.5: Number Literals
The C<number> numeric literal represents a single floating-point (decimal) number, and may express any real number within your computer's data type limits.
-23.42 # number
0.000_001 # number
42.23 # number
42 # number
-4_123.456_789_123_456_789_123_456_789_123_456_789_123_456_789_123_456_789_123_456 # bad number, outside data type limits
=head3 Section 2.1.6: Underscore Digit Separators
For C<unsigned_integer>, C<integer>, C<gmp_integer>, and C<number> literals, an I<"underscore"> C<_> character must be inserted after every third digit away from the decimal point, where the underscore is used in a similar manner as a comma when writing long numbers by hand.
1_234_567 # integer, same as "1,234,567" in American notation
-32_123 # integer, same as "-32,123" in American notation
-32123 # bad integer, missing underscore
1.234_567 # number, same as "1.234567" in American notation
-32_123.456_789_01 # number, same as "-32,123.45678901" in American notation
-32_123.456_78901 # bad number, missing underscore
=head3 Section 2.1.7: Optional Positive Sign
For C<unsigned_integer>, C<integer>, C<gmp_integer>, and C<number> literals, an optional C<+> plus sign may be prepended to explicitly indicate a numeric literal is positive (greater-than zero).
1 # positive one
+1 # also positive one
=for html <u>
I<BEST PRACTICES>
=over
=item * I<When only positive numeric literals are used in one area of code, omit positive signs.>
=item * I<When both positive and negative literals are used in one code area, use signs for all applicable literals.>
=back
=for html </u>
+23 # NOT BEST PRACTICE: not aligned with other unsigned literal below
+55.6 # NOT BEST PRACTICE: not aligned with other unsigned literal below
42
23 # BEST PRACTICE: aligned with other unsigned literal below, best for all-positive literals
55.6 # BEST PRACTICE: aligned with other unsigned literal below, best for all-positive literals
42
X<break_code_blocks>
23 # NOT BEST PRACTICE: not aligned with other signed literals below
55.6 # NOT BEST PRACTICE: not aligned with other signed literals below
-21
-66.5
23 # NOT BEST PRACTICE: manually aligned with other signed literals below, but will not automatically align via Perl::Tidy
55.6 # NOT BEST PRACTICE: manually aligned with other signed literals below, but will not automatically align via Perl::Tidy
-21
-66.5
+23 # BEST PRACTICE: aligned with other signed literals below, best for mixed-sign literals
+55.6 # BEST PRACTICE: aligned with other signed literals below, best for mixed-sign literals
-21
-66.5
=head3 Section 2.1.8: Scientific Notation
For C<unsigned_integer>, C<integer>, and C<number> literals, very large or very small numbers may be approximated using I<"scientific notation">, where each number is normalized to have exactly one digit to the left of the decimal point, then a lower-case C<e> character and an appropriate integer power-of-ten is appended to the resulting normalized floating-point number. The C<e> character stands for "exponent", as in "exponent of ten", and the Perl style of scientific notation is sometimes more accurately referred to as I<"scientific e notation">.
As with normal integers, negative exponents must be prefixed with a C<-> minus sign and positive exponents may be optionally prefixed with a C<+> plus sign.
1_234_567_000 # good integer
1.234_567_000e09 # good number, same as "1_234_567_000" in scientific notation
0.001_234_567_000 # good number
1.234_567_000e-03 # good number, same as "0.001_234_567_000" in scientific notation
-0.000_000_000_000_000_000_000_001_234_567 # bad number, outside data type limits
-1.234_567e-24 # good number, same as "-0.000_000_000_000_000_000_000_001_234_567" in scientific notation
=for html <u>
I<BEST PRACTICES>
=over
=item * I<Use 2 digits to represent all exponents.>
=item * I<When only positive exponents are used, omit exponent signs.>
=item * I<When both positive and negative exponents are used, use signs for all exponents.>
=back
=for html </u>
1_234_567_000 # NOT BEST PRACTICE: no exponent
1.234_567_000e9 # NOT BEST PRACTICE: not aligned with two-digit exponents below
1.234_567_000e+09 # NOT BEST PRACTICE: not aligned with two-digit exponents below
1.234_567_000e09 # BEST PRACTICE: aligned with two-digit exponents below, best for all-positive exponents
1.234_567_000e19
2.111_000_333e04
1.234_567_000e09 # NOT BEST PRACTICE: not aligned with signed exponents below
1.234_567_000e+09 # BEST PRACTICE: aligned with signed exponents below, best for mixed-sign exponents
1.234_567_000e-09
2.111_000_333e-04
# accuracy of following numbers may be reduced on computers with lower precision data types
+1.537_969_711_485_091_65e+21 # BEST PRACTICE: best for mixed-sign exponents
-2.591_931_460_998_796_41e+01 # BEST PRACTICE: best for mixed-sign exponents
+1.792_587_729_503_711_81e-01 # BEST PRACTICE: best for mixed-sign exponents
+2.680_677_724_903_893_22e-03 # BEST PRACTICE: best for mixed-sign exponents
+1.628_241_700_382_422_95e-03 # BEST PRACTICE: best for mixed-sign exponents
-9.515_922_545_197_158_70e-15 # BEST PRACTICE: best for mixed-sign exponents
=head3 Section 2.1.9: Truth Values
In the most simple case, a I<"truth value"> may be represented by a boolean literal where the numeric value of C<0> represents the truth value of I<"false">, and numeric C<1> represents I<"true">. In general, a truth value is any data which may be recognized by Perl (and thus RPerl) as being either true or false; there is no third option.
Perl recognizes relatively few values as false, of which only 4 are accepted by RPerl:
0 # false, number zero
'0' # false, text zero
q{0} # false, text zero
q{} # false, text empty
All other values which RPerl accepts are recognized to hold a truth value of true.
All numeric operators in the comparison and logic sub-categories, as well as all string operators in the comparison sub-category, will generate truth values as output.
Perl attaches magic to the truth value of false, allowing it be utilized as either a normal truth value, or a numeric value of C<0>, or an empty string value of C<q{}>. This magic behavior is not supported by C++, and thus not supported by RPerl.
In C and C++, only numeric C<0> is universally recognized as false, while the text 0 and empty text are recognized as true, which is different than Perl. To achieve compatibility, RPerl automatically inserts additional C++ logic in all compiled output code to check for the 2 remaining RPerl false values of text character zero C<'0'> or C<q{0}>, and empty text C<q{}>. This ensures the compiled C++ output code will behave identically to the original RPerl input source code, with regard to truth values.
B<WARNING FOR ALL COMPARISON & LOGIC OPERATORS:>
B<Due to Perl's magic attached to truth values of false, as well as the difference between Perl and C++ recognized truth values, you may experience unexpected or undefined behavior if a truth value is utilized anywhere except true-or-false conditions in loops and conditional statements.>
B<Only utilize the truth values returned by comparison and logic operators within the condition enclosed by parentheses in C<if ()>, C<elsif ()>, C<for ()>, or C<while ()>.>
if (1 > 2) { print 'I think not', "\n"; } # good use of greater-than operator
elsif ($x and $y) { print 'Maybe', "\n"; } # good use of and operator
for (my integer $i = 0; $i < 23; $i++) { print 'finite loop', "\n"; } # good use of less-than operator
while ( 1 != 2 ) { print 'infinite loop', "\n"; } # good use of not-equal operator
my integer $foo = 3 + (1 >= 2); # UNEXPECTED BEHAVIOR: bad use of greater-than-or-equal operator
my integer $bar = 3 * (1 <= 2); # UNEXPECTED BEHAVIOR: bad use of less-than-or-equal operator
my integer $bat = sin (1 == 2); # UNEXPECTED BEHAVIOR: bad use of equal operator
=head3 Section 2.1.10: Floating-Point Error
A I<"floating-point number"> is any number which includes a decimal point C<.> as part of the numeric representation, as opposed to an integer which does not include a decimal point. In RPerl, all floating-point values are stored in variables of the data type C<number>.
0 # integer
1 # integer
-123 # integer
0.1 # floating-point
1.654 # floating-point
-123.4 # floating-point
my integer $some_int = 23; # integer variable
my number $some_float = 23.42; # floating-point variable
All computer languages which perform calculations on floating-point numbers are susceptible to I<"floating-point error">, which is any inaccuracy due to incorrect rounding or lack of available precision.
For example, suppose you have a floating-point number C<0.105>, which seems normal enough. Let us further suppose you want to divide C<0.105> by some other number, say C<1_000>, and by the simple rules of arithmetic you would expect to arrive at an answer of C<0.000_105>. Unfortunately, due to the way floating-point numbers are stored in computer memory, the actual result is closer to C<0.000_104_999>, so C<0.000_105> happens to be one of many possible floating-point errors.
(0.105 / 1_000) == 0.000_105 # UNEXPECTED BEHAVIOR: false
print ((0.105 / 1_000) - 0.000_105); # UNEXPECTED BEHAVIOR: -1.355_252_715_606_88e-20
It will usually not be possible to easily predict when and where floating-point error will occur. In general, you may experience the effects of floating-point error whenever your code relies upon one or more of the following:
=over
=item * A floating-point operator which must return a specific, exact result
=item * A floating-point variable which must contain a specific, exact value
=item * A floating-point value which must exactly equal another floating-point value
=back
To compensate for unpredictable floating-point error, you should use the I<"floating-point epsilon"> value stored in the constant C<RPerl::EPSILON()>, which is a very small number used to help detect inaccuracies. Whenever you want of directly compare two floating-point values, instead use the subtraction C<-> and absolute value C<abs> operators to take the positive difference, then use the less-than C<E<lt>> operator to compare the difference to the floating-point epsilon value. If the difference is less-than the floating-point epsilon, then the two input floating-point values can be considered to be numerically equal.
RPerl::EPSILON() # A VERY SMALL NUMBER: 0.000_000_000_000_000_2
(0.105 / 1_000) == 0.000_105 # UNEXPECTED BEHAVIOR: false
abs ((0.105 / 1_000) - 0.000_105) < RPerl::EPSILON() # EXPECTED BEHAVIOR: true
X<break_code_blocks>
my number $foo = 0.105 / 1_000;
my number $faa = 0.105 / 1_000;
my number $bar = 0.000_105;
my number $bat = 0.000_105;
if (0.000_105 == 0.000_105) { print 'true'; } else { print 'false'; } # EXPECTED BEHAVIOR: true
if ((0.105 / 1_000) == (0.105 / 1_000)) { print 'true'; } else { print 'false'; } # EXPECTED BEHAVIOR: true
if ($bar == $bat) { print 'true'; } else { print 'false'; } # EXPECTED BEHAVIOR: true
if ($foo == $faa) { print 'true'; } else { print 'false'; } # EXPECTED BEHAVIOR: true
if ($foo == $bar) { print 'true'; } else { print 'false'; } # UNEXPECTED BEHAVIOR: false
if (abs ($foo - $bar) < RPerl::EPSILON()) { print 'true'; } else { print 'false'; } # EXPECTED BEHAVIOR: true
B<WARNING FOR ALL FLOATING-POINT NUMERIC OPERATORS:>
B<Due to floating-point error, unexpected behavior may be experienced if a floating-point value is tested for exact equality with any other value.>
B<Always use the floating-point epsilon value C<RPerl::EPSILON()> to check for approximate equality instead of exact equality.>
=head3 Section 2.1.11: Arithmetic Operators
=begin text
my $z = q{<<< BEGIN TEXT EVAL >>>};
use Text::ASCIITable;
my Text::ASCIITable $table = Text::ASCIITable->new({alignHeadRow => 'center', drawRowLine => 1});
$table->setCols(splice @{[split /\s*\n\s*/, q{
=end text
=begin man
.TS
allbox tab(@) ;
c c c c c c c
l l l l r l l .
=end man
=for html <table class="rperl operators">
=begin docbook
<table id="learning_rperl-section_2.1.11-table_1" label="" frame="all" colsep="1" rowsep="1">
<title>Arithmetic Operators</title>
<tgroup cols="6">
=end docbook
=for man T{
=for html <tr><th>
=for docbook <thead>
=for docbook <row><entry align="center">
B<Name>
=for man T}@T{
=for html </th><th>
=for docbook </entry><entry align="center">
B<Symbol>
=for man T}@T{
=for html </th><th>
=for docbook </entry><entry align="center">
B<Arity>
=for man T}@T{
=for html </th><th>
=for docbook </entry><entry align="center">
B<Fixity>
=for man T}@T{
=for html </th><th>
=for docbook </entry><entry align="center">
B<Precedence>
=for man T}@T{
=for html </th><th>
=for docbook </entry><entry align="center">
B<Associativity>
=for man T}@T{
=for html </th><th>
=for docbook </entry><entry align="center">
B<Supported>
=for text }]}, 1);
=for man T}
=for html </th></tr>
=for docbook </entry></row>
=for docbook </thead>
=for text $table->addRow(splice @{[split /\s*\n\s*/, q{
=for man T{
=for html <tr><td>
=for docbook <tbody>
=for docbook <row><entry align="left">
Absolute Value
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
abs
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Unary
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Prefix
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="right">
01
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Left
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Coming Soon
=for text }]}, 1);
=for man T}
=for html </td></tr>
=for docbook </entry></row>
=for text $table->addRow(splice @{[split /\s*\n\s*/, q{
=for man T{
=for html <tr><td>
=for docbook <row><entry align="left">
Natural Exponential Function
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
exp
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Unary
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Prefix
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="right">
01
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Non
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Coming Soon
=for text }]}, 1);
=for man T}
=for html </td></tr>
=for docbook </entry></row>
=for text $table->addRow(splice @{[split /\s*\n\s*/, q{
=for man T{
=for html <tr><td>
=for docbook <row><entry align="left">
Exponent AKA Power
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
**
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Binary
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Infix
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="right">
04
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Right
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Yes
=for text }]}, 1);
=for man T}
=for html </td></tr>
=for docbook </entry></row>
=for text $table->addRow(splice @{[split /\s*\n\s*/, q{
=for man T{
=for html <tr><td>
=for docbook <row><entry align="left">
Negative with Parentheses
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
-( )
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Unary
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Closed
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="right">
05
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Right
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Yes
=for text }]}, 1);
=for man T}
=for html </td></tr>
=for docbook </entry></row>
=for text $table->addRow(splice @{[split /\s*\n\s*/, q{
=for man T{
=for html <tr><td>
=for docbook <row><entry align="left">
Multiply
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
*
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Binary
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Infix
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="right">
07
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Left
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Yes
=for text }]}, 1);
=for man T}
=for html </td></tr>
=for docbook </entry></row>
=for text $table->addRow(splice @{[split /\s*\n\s*/, q{
=for man T{
=for html <tr><td>
=for docbook <row><entry align="left">
Divide
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
/
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Binary
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Infix
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="right">
07
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Left
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Yes
=for text }]}, 1);
=for man T}
=for html </td></tr>
=for docbook </entry></row>
=for text $table->addRow(splice @{[split /\s*\n\s*/, q{
=for man T{
=for html <tr><td>
=for docbook <row><entry align="left">
Modulo AKA Modulus
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
%
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Binary
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Infix
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="right">
07
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Left
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Yes
=for text }]}, 1);
=for man T}
=for html </td></tr>
=for docbook </entry></row>
=for text $table->addRow(splice @{[split /\s*\n\s*/, q{
=for man T{
=for html <tr><td>
=for docbook <row><entry align="left">
Add
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
+
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Binary
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Infix
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="right">
08
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Left
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Yes
=for text }]}, 1);
=for man T}
=for html </td></tr>
=for docbook </entry></row>
=for text $table->addRow(splice @{[split /\s*\n\s*/, q{
=for man T{
=for html <tr><td>
=for docbook <row><entry align="left">
Subtract
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
-
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Binary
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Infix
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="right">
08
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Left
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Yes
=for text }]}, 1);
=for man T}
=for html </td></tr>
=for docbook </entry></row>
=for text $table->addRow(splice @{[split /\s*\n\s*/, q{
=for man T{
=for html <tr><td>
=for docbook <row><entry align="left">
Natural Logarithm
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
log
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Unary
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Prefix
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="right">
10
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Non
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Coming Soon
=for text }]}, 1);
=for man T}
=for html </td></tr>
=for docbook </entry></row>
=for text $table->addRow(splice @{[split /\s*\n\s*/, q{
=for man T{
=for html <tr><td>
=for docbook <row><entry align="left">
Square Root
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
sqrt
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Unary
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Prefix
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="right">
10
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Non
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Coming Soon
=for text }]}, 1);
=for man T}
=for html </td></tr>
=for docbook </entry></row>
=begin text
return $table->draw( ['.=','=.','=','='], # .=============.
['|','|','|'], # | info | info |
['|-','-|','=','='], # |-===========-|
['|','|','|'], # | info | info |
["'=","='",'=','='], # '============='
['|-','-|','-','+'] # rowseperator
);
$z = q{<<< END TEXT EVAL >>>};
=end text
=for man .TE
=for html </table>
=for docbook </tbody></tgroup></table>
=over
=item * B<Absolute Value>
abs VALUE
VALUE is numeric value;
If operand VALUE is 0 or positive (greater-than 0), return unchanged;
If VALUE is negative (less-than 0), return positive number with equal magnitude (distance from 0)
abs 0 # 0
abs 1 # 1
abs -1 # 1
abs 2_112.23 # 2_112.23
abs -2_112.23 # 2_112.23
=back
=over
=item * B<Natural Exponential Function>
exp VALUE
VALUE is numeric value;
Raise C<e> (base of natural logarithm) to the power of operand VALUE, return result
exp 0 # 1
exp 1 # 2.718_281_828_459_05
exp -1 # 0.367_879_441_171_442
=back
=over
=item * B<Exponent AKA Power>
VALUE1 ** VALUE2
VALUE1 and VALUE2 are numeric values;
Raise first operand VALUE1 to the power of second operand VALUE2, return result
0 ** 0 # 1
0 ** 1 # 0
0 ** 2 # 0
0 ** 3 # 0
1 ** 0 # 1
1 ** 1 # 1
1 ** 2 # 1
1 ** 3 # 1
2 ** 0 # 1
2 ** 1 # 2
2 ** 2 # 4
2 ** 3 # 8
(-1) ** 0 # 1
(-1) ** 1 # -1
(-1) ** 2 # 1
(-1) ** 3 # -1
(-2) ** 0 # 1
(-2) ** 1 # -2
(-2) ** 2 # 4
(-2) ** 3 # -8
0 ** -1 # inf
0 ** -2 # inf
0 ** -3 # inf
1 ** -1 # 1
1 ** -2 # 1
1 ** -3 # 1
2 ** -1 # 0.5
2 ** -2 # 0.25
2 ** -3 # 0.125
(-1) ** -1 # -1
(-1) ** -2 # 1
(-1) ** -3 # -1
(-2) ** -1 # -0.5
(-2) ** -2 # 0.25
(-2) ** -3 # -0.125
=back
=over
=item * B<Negative with Parentheses>
-( VALUE )
VALUE is numeric value;
Change sign of operand VALUE, return result;
Negative VALUE becomes positive, and positive VALUE becomes negative;
Parentheses must be used, due to ambiguity of hyphen C<-> character as negative operator, subtraction operator, or negative number literal
-( 0) # 0
-( 1) # -1
-(-1) # 1
-( 0.25) # -0.25
-(-0.25) # 0.25
-( 2_112.23) # -2_112.23
-(-2_112.23) # 2_112.23
=back
=over
=item * B<Multiply>
VALUE1 * VALUE2
VALUE1 and VALUE2 are numeric values;
Multiply first operand VALUE1 by second operand VALUE2, return product
0 * 0 # 0
0 * 1 # 0
0 * -1 # 0
1 * 0 # 0
1 * 1 # 1
1 * -1 # -1
-1 * 0 # 0
-1 * 1 # -1
-1 * -1 # 1
0.5 * 0 # 0
0.5 * 0.5 # 0.25
0.5 * -0.5 # -0.25
0.5 * 1 # 0.5
0.5 * -1 # -0.5
0.5 * 2 # 1.0
0.5 * -2 # -1.0
=back
=over
=item * B<Divide>
VALUE1 / VALUE2
VALUE1 and VALUE2 are numeric values;
Divide first operand VALUE1 by second operand VALUE2, return quotient;
Error if attempt to divide by 0
0 / 0 # ERROR
0 / 1 # 0
0 / -1 # 0
1 / 0 # ERROR
1 / 1 # 1
1 / -1 # -1
-1 / 0 # ERROR
-1 / 1 # -1
-1 / -1 # 1
0.5 / 0 # ERROR
0.5 / 0.5 # 1
0.5 / -0.5 # -1
0.5 / 1 # 0.5
0.5 / -1 # -0.5
0.5 / 2 # 0.25
0.5 / -2 # -0.25
=back
=over
=item * B<Modulo AKA Modulus>
VALUE1 % VALUE2
VALUE1 and VALUE2 are numeric values;
Divide integer part of first operand VALUE1 by integer part of second operand VALUE2, return remainder;
Error if attempt to modulus by VALUE2 with absolute value less-than 1
0 % 0 # ERROR
0 % 1 # 0
0 % -1 # 0
1 % 0 # ERROR
1 % 1 # 0
1 % -1 # 0
-1 % 0 # ERROR
-1 % 1 # 0
-1 % -1 # 0
0.5 % 0 # ERROR
0.5 % 0.5 # ERROR
0.5 % -0.5 # ERROR
0.5 % 1 # 0
0.5 % -1 # 0
0.5 % 2 # 0
0.5 % -2 # 0
=back
=over
=item * B<Add>
VALUE1 + VALUE2
VALUE1 and VALUE2 are numeric values;
Add first operand VALUE1 to second operand VALUE2, return sum
0 + 0 # 0
0 + 1 # 1
0 + -1 # -1
1 + 0 # 1
1 + 1 # 2
1 + -1 # 0
-1 + 0 # -1
-1 + 1 # 0
-1 + -1 # -2
0.5 + 0 # 0.5
0.5 + 0.5 # 1.0
0.5 + -0.5 # 0
0.5 + 1 # 1.5
0.5 + -1 # -0.5
0.5 + 2 # 2.5
0.5 + -2 # -1.5
=back
=over
=item * B<Subtract>
VALUE1 - VALUE2
VALUE1 and VALUE2 are numeric values;
Subtract second operand VALUE2 from first operand VALUE1, return difference
0 - 0 # 0
0 - 1 # -1
0 - -1 # 1
1 - 0 # 1
1 - 1 # 0
1 - -1 # 2
-1 - 0 # -1
-1 - 1 # -2
-1 - -1 # 0
0.5 - 0 # 0.5
0.5 - 0.5 # 0
0.5 - -0.5 # 1.0
0.5 - 1 # -0.5
0.5 - -1 # 1.5
0.5 - 2 # -1.5
0.5 - -2 # 2.5
=back
=over
=item * B<Natural Logarithm>
log VALUE
VALUE is numeric value;
Take logarithm base C<e> of operand VALUE, return result;
Constant C<e> is known as Euler's Number and is defined as the limit of C<(1 + 1/$n)**$n> as C<$n> grows to infinity;
To instead calculate logarithm using a base other than C<e>, utilize ratio C<(log $operand)/(log $base)>;
Error if attempt to take logarithm of VALUE less-than or equal to 0
log 0 # ERROR
log 1 # 0
log -1 # ERROR
log 2.718_281_828_459_05 # 1
=back
=over
=item * B<Square Root>
sqrt VALUE
VALUE is numeric value;
Take square root of operand VALUE, return result;
Error if attempt to take square root of VALUE less-than 0
sqrt 0 # 0
sqrt 1 # 1
sqrt -1 # ERROR
sqrt 2 # 1.414_213_562_373_1
=back
=head3 Section 2.1.12: Trigonometry Operators
=begin text
my $z = q{<<< BEGIN TEXT EVAL >>>};
use Text::ASCIITable;
my Text::ASCIITable $table = Text::ASCIITable->new({alignHeadRow => 'center', drawRowLine => 1});
$table->setCols(splice @{[split /\s*\n\s*/, q{
=end text
=begin man
.TS
allbox tab(@) ;
c c c c c c c
l l l l r l l .
=end man
=for html <table class="rperl operators">
=begin docbook
<table id="learning_rperl-section_2.1.12-table_1" label="" frame="all" colsep="1" rowsep="1">
<title>Trigonometry Operators</title>
<tgroup cols="6">
=end docbook
=for man T{
=for html <tr><th>
=for docbook <thead>
=for docbook <row><entry align="center">
B<Name>
=for man T}@T{
=for html </th><th>
=for docbook </entry><entry align="center">
B<Symbol>
=for man T}@T{
=for html </th><th>
=for docbook </entry><entry align="center">
B<Arity>
=for man T}@T{
=for html </th><th>
=for docbook </entry><entry align="center">
B<Fixity>
=for man T}@T{
=for html </th><th>
=for docbook </entry><entry align="center">
B<Precedence>
=for man T}@T{
=for html </th><th>
=for docbook </entry><entry align="center">
B<Associativity>
=for man T}@T{
=for html </th><th>
=for docbook </entry><entry align="center">
B<Supported>
=for text }]}, 1);
=for man T}
=for html </td></tr>
=for docbook </entry></row>
=for text $table->addRow(splice @{[split /\s*\n\s*/, q{
=for man T{
=for html <tr><td>
=for docbook <row><entry align="left">
Arctangent-Divide
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
atan2
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Binary
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Prefix
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="right">
01
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Left
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Coming Soon
=for text }]}, 1);
=for man T}
=for html </td></tr>
=for docbook </entry></row>
=for text $table->addRow(splice @{[split /\s*\n\s*/, q{
=for man T{
=for html <tr><td>
=for docbook <row><entry align="left">
Sine
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
sin
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Unary
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Prefix
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="right">
10
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Non
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Coming Soon
=for text }]}, 1);
=for man T}
=for html </th></tr>
=for docbook </entry></row>
=for docbook </thead>
=for text $table->addRow(splice @{[split /\s*\n\s*/, q{
=for man T{
=for html <tr><td>
=for docbook <tbody>
=for docbook <row><entry align="left">
Cosine
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
cos
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Unary
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Prefix
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="right">
10
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Non
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Coming Soon
=for text }]}, 1);
=for man T}
=for html </td></tr>
=for docbook </entry></row>
=begin text
return $table->draw( ['.=','=.','=','='], # .=============.
['|','|','|'], # | info | info |
['|-','-|','=','='], # |-===========-|
['|','|','|'], # | info | info |
["'=","='",'=','='], # '============='
['|-','-|','-','+'] # rowseperator
);
$z = q{<<< END TEXT EVAL >>>};
=end text
=for man .TE
=for html </table>
=for docbook </tbody></tgroup></table>
=over
=item * B<Arctangent-Divide>
atan2 VALUE1, VALUE2
VALUE1 and VALUE2 are numeric values;
Divide first operand VALUE1 by second operand VALUE2, take arctangent of quotient, return result;
Attempts to conform to Open Group / IEEE standards:
L<http://perldoc.perl.org/perlport.html#atan2>
L<http://pubs.opengroup.org/onlinepubs/9699919799/functions/atan2.html>
To instead calculate tangent of 1 operand (not arctangent of 2 operands), utilize trigonometry identity ratio C<(sin $operand)/(cos $operand)>
atan2 0, 0 # 0, MAY BE DIFFERENT ON YOUR SYSTEM
atan2 0, 1 # 0
atan2 0, -1 # 3.141_592_653_589_79, DEFINED AS PI
atan2 1, 0 # 1.570_796_326_794_9
atan2 1, 1 # 0.785_398_163_397_448
atan2 1, -1 # 2.356_194_490_192_34
atan2 -1, 0 # -1.570_796_326_794_9
atan2 -1, 1 # -0.785_398_163_397_448
atan2 -1, -1 # -2.356_194_490_192_34
=back
=over
=item * B<Sine>
sin VALUE
VALUE is numeric value;
Take sine of operand VALUE, return result
sin 0 # 0
sin 1 # 0.841_470_984_807_897
sin -1 # -0.841_470_984_807_897
sin 3.141_592_653_589_79 # 0, MAY BE SLIGHTLY OFF DUE TO FLOATING POINT ERROR
=back
=over
=item * B<Cosine>
cos VALUE
VALUE is numeric value;
Take cosine of operand VALUE, return result
cos 0 # 1
cos 1 # 0.540_302_305_868_14
cos -1 # 0.540_302_305_868_14
cos 3.141_592_653_589_79 # -1
=back
=head3 Section 2.1.13: Comparison (Relational & Equality) Operators
=begin text
my $z = q{<<< BEGIN TEXT EVAL >>>};
use Text::ASCIITable;
my Text::ASCIITable $table = Text::ASCIITable->new({alignHeadRow => 'center', drawRowLine => 1});
$table->setCols(splice @{[split /\s*\n\s*/, q{
=end text
=begin man
.TS
allbox tab(@) ;
c c c c c c c
l l l l r l l .
=end man
=for html <table class="rperl operators">
=begin docbook
<table id="learning_rperl-section_2.1.13-table_1" label="" frame="all" colsep="1" rowsep="1">
<title>Comparison (Relational & Equality) Operators</title>
<tgroup cols="6">
=end docbook
=for man T{
=for html <tr><th>
=for docbook <thead>
=for docbook <row><entry align="center">
B<Name>
=for man T}@T{
=for html </th><th>
=for docbook </entry><entry align="center">
B<Symbol>
=for man T}@T{
=for html </th><th>
=for docbook </entry><entry align="center">
B<Arity>
=for man T}@T{
=for html </th><th>
=for docbook </entry><entry align="center">
B<Fixity>
=for man T}@T{
=for html </th><th>
=for docbook </entry><entry align="center">
B<Precedence>
=for man T}@T{
=for html </th><th>
=for docbook </entry><entry align="center">
B<Associativity>
=for man T}@T{
=for html </th><th>
=for docbook </entry><entry align="center">
B<Supported>
=for text }]}, 1);
=for man T}
=for html </td></tr>
=for docbook </entry></row>
=for text $table->addRow(splice @{[split /\s*\n\s*/, q{
=for man T{
=for html <tr><td>
=for docbook <row><entry align="left">
Less-Than
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
<
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Binary
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Infix
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="right">
11
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Non
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Yes
=for text }]}, 1);
=for man T}
=for html </td></tr>
=for docbook </entry></row>
=for text $table->addRow(splice @{[split /\s*\n\s*/, q{
=for man T{
=for html <tr><td>
=for docbook <row><entry align="left">
Greater-Than
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
>
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Binary
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Infix
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="right">
11
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Non
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Yes
=for text }]}, 1);
=for man T}
=for html </th></tr>
=for docbook </entry></row>
=for docbook </thead>
=for text $table->addRow(splice @{[split /\s*\n\s*/, q{
=for man T{
=for html <tr><td>
=for docbook <tbody>
=for docbook <row><entry align="left">
Less-Than-Or-Equal
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
<=
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Binary
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Infix
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="right">
11
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Non
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Yes
=for text }]}, 1);
=for man T}
=for html </td></tr>
=for docbook </entry></row>
=for text $table->addRow(splice @{[split /\s*\n\s*/, q{
=for man T{
=for html <tr><td>
=for docbook <row><entry align="left">
Greater-Than-Or-Equal
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
>=
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Binary
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Infix
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="right">
11
=for man T}@T{
=for html </td><td>
=for docbook </entry><entry align="left">
Non
=for man T}@T{