NAME

Learning RPerl

BOOK TITLE

Learning RPerl

~ or ~

Let's Write Fast Perl!

.

...

.....

.......

being

.......

.....

...

.

The Official Introductory-Level Reference, User Manual, and Educational Documentation

~ for ~

Restricted Perl, The Optimizing Perl 5 Compiler

DEDICATION

For Anna.

TABLE OF CONTENTS: CHAPTERS AT-A-GLANCE

FOREWORD

[ INSERT FOREWORD CONTENT HERE ]

PREFACE

Section 0.1: Who I Am

[INSERT WHO]

Section 0.2: Why I Wrote This Book

[INSERT WHY]

Section 0.3: History Of This Book

[INSERT WHEN]

Section 0.4: TPF Grant

[INSERT MONEY]

Section 0.5: Acknowledgements & Thanks

[INSERT THEM]

Section 0.6: Defense / Apology

[INSERT SORRY]

Section 0.7: POD

"The Pod format is not necessarily sufficient for writing a book."

http://perldoc.perl.org/perlpod.html

~ Saint Larry Wall & Sean M. Burke

"Challenge accepted."

https://github.com/wbraswell/rperl/blob/master/script/development/pod2rperlhtml.pl

~ Will Braswell

CHAPTER 1: INTRODUCTION

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, "runs really fast".

Throughout this text, the following 12 typography conventions are utilized:

  • "Literal Quotation"

  • "First Occurrence Of Key Concept"

  • Emphasis

  • Stronger Emphasis

  • /path/to/program.pl

  • Program Name

  • Book Title

  • BEST PRACTICES

  • Hyperlink

  • $inline_code_snippet = 'unhighlighted';

    my string $indented_code_block = 'highlighted';  # with comments
    my integer $more_code = 17;  # http://www.catb.org/jargon/html/R/random-numbers.html
    return 'end of indented code block';

    $ terminal_command.pl with arguments
    Please provide input: foo bar
    Your output is:       howdy howdy howdy

Section 1.2: Learning Perl

This book is purposefully patterned after the popular educational text 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 Learning Perl, but all content is re-written for RPerl. Learning RPerl also copies the same exercise concepts as 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 Learning Perl from our friends at O'Reilly:

http://shop.oreilly.com/product/0636920018452.do

Section 1.3: Is This Book Right For You?

  • Are you totally new to computer programming, and you want to learn how to write your first program?

  • Do you already know Perl, and now you want to make your Perl code run faster?

  • Do you already know some other computer language, and Perl has always intrigued you?

  • Do you love learning about new languages and compilers?

  • Do you miss you favorite old language Perl, and you're looking for a legitimate reason to go back?

  • Are you a scientist and you just want your code to run really fast without the headaches of C or C++?

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 few Saint Larry videos. You'll thank us in the morning.

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.

Section 1.5: What About The Exercises & Their Answers?

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 refering to our or anyone else's solutions whatsoever. We suggest you enclose Appendix A with a paperclip or discard it altogether to avoid the potential for accidental academic dishonesty.

Section 1.6: What Do Those Numbers At The Start Of The Exercise Mean?

The original authors of Learning Perl meant the numbers at each exercise to 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.

Section 1.7: What If I'm An RPerl Course Instructor?

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 Learning Perl. 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.

Section 1.8: What Does RPerl Stand For?

RPerl stands for "Restricted Perl", in that we restrict our use of Perl to those parts which can be made to run fast. RPerl also stands for "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 "Roadrunner Perl", in that it runs really fast.

Section 1.9: Why Did Will Create 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.

Section 1.10: Why Didn't Will Just Use Normal Perl Or Some Other Language?

Dynamic languages like Perl are fast at running some kinds of computational actions, such as string manipulation (editing text data) 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 "high magic", so RPerl is focused on supporting the "low magic" parts of Perl which can be made to run fast.

Section 1.11: Is RPerl Easy Or Hard?

RPerl is specifically designed to remove the confusing and 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.

Section 1.12: How Did RPerl Get To Be So Popular?

The RPerl team has been regularly promoting RPerl in a number of physical and digital venues, including but not limited to:

Section 1.13: What Is Happening With RPerl Now?

As of Q4 2015, RPerl v1.2 (codename Andromeda) 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. More info coming soon!

Section 1.14: What Is RPerl Really Good For?

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.

Section 1.15: What Is RPerl Not Good For?

RPerl has purposefully disabled the most complex features of Perl, such as run-time 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.

Section 1.16: How Can I Get 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:

$ sudo cpan RPerl

If RPerl is properly installed, you should see a short text message displayed when you type the following command:

$ rperl -v

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:

https://github.com/wbraswell/rperl/blob/master/INSTALL

Unless you are an experienced programmer or system administrator, it is 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 $ sudo cpan RPerl command as described above.

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:

https://metacpan.org/author/WBRASWELL

You may find the latest development release of RPerl (possibly unstable) on Github:

https://github.com/wbraswell/rperl

Section 1.17: What Is CPAN?

CPAN is the "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.

https://en.wikipedia.org/wiki/CPAN

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.

Section 1.18: How Can I Get 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

Section 1.19: Are There Any Other Kinds Of Support?

Free technical support for non-commercial users is provided by the RPerl community through IRC.

IRC #perl11 http://irc.perl.org

Section 1.20: What If I Find A Bug In RPerl?

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:

https://github.com/wbraswell/rperl/issues

Although Github Issues is strongly preferred, the RPerl development team also supports the legacy CPAN ticket system:

https://rt.cpan.org/Public/Dist/Display.html?Name=RPerl

Section 1.21: How Do I Make An RPerl Program?

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.

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 "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).

http://www.epic-ide.org

http://padre.perlide.org

http://komodoide.com/perl

Section 1.22: A Simple RPerl Program

#!/usr/bin/perl

# Learning RPerl, Chapter 1, Exercise 3
# 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 = $bar / $foo;
print 'have $foo = ' . to_string($foo) . "\n";
print 'have $bar = ' . to_string($bar) . "\n";
print 'have $baz = ' . to_string($baz) . "\n";

Section 1.23: What Is Inside That 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 # are comments and can be safely ignored or discarded without affecting the program.

The "shebang" section is required, always contains exactly 1 line, and is short for "hash bang"; referring to the two leading characters #! of this line. The "octothorpe" character # (tic-tac-toe symbol) is called a "pound sign" when used on a telephone, and is called a "hash" (or more recently and less accurately "hash tag") when used on a computer. The exclamation point character ! is called a "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 /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 #!/usr/bin/perl, then that file is a Perl program.

The "header" section is required and always contains 4 lines for an RPerl "program" file ending in .pl, or 5 lines for an RPerl "module" ending in .pm (covered later in Chapter 11). use is recognized by Perl as a special "keyword" (AKA "builtin operator") which has 2 primary purposes: to load additional RPerl modules, and to enable RPerl "pragma" system configuration modes. The use RPerl; line is dual-purpose, it both loads the RPerl.pm module and enables the special RPerl low-magic pragma. The use strict; and use warnings; lines enable basic Perl pragmas which require decent programming practices by the human programmers. The our $VERSION = 0.001_000; line sets the version number of this RPerl program.

The "critics" section is included as necessary and may contain 1 or more lines beginning with ## 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 critics command allows the use of numeric values such as 21 and 12, as well as the common print command. The USER DEFAULT 2 critics command allows the printing of 'have $foo = ', where a single-quoted ' string literal value contains the the $ dollar sigil (covered later in Chapter 2).

The "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 my integer $foo = 21 + 12; line declares a new variable named $foo which will only contain non-floating-point numeric data, and which is initialized to contain the arithmetic result of numeric literal values 21 plus 12. The my integer $bar = 23 * 42 * 2; line does much the same thing, creating a new numeric variable named $bar and initialized with 23 times 42 times 2. The print 'have $foo = ' . to_string($foo) . "\n"; and following 2 lines will display on screen (not send to paper printer) the labeled values of $foo, $bar, and $baz respectively. The . dot operator is string concatenation, used in this example to create one string out of 3 parts so there is only 1 argument parameter passed to the print command. The to_string() RPerl operator converts a numeric value to an underscore-formatted string value, suitable for use via the print operator. The "n" in the "\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.

Section 1.24: How Do I Compile RPerl?

Normal Perl source code is executed using a software mechanism known as "interpretation", which is to say that Perl is an "interpreted" language and the /usr/bin/perl command is called the "Perl interpreter". The primary alternative to interpretation is "compilation", so RPerl is a "compiled" subset of the Perl language and the /usr/bin/rperl command is called the "RPerl compiler".

Like the Perl interpreter, the RPerl compiler accepts 2 different input file types: Perl programs which end in .pl and Perl modules which end in .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.

CURRENT RPERL LIMITATION: RPerl modules are supported in full compile mode, but RPerl programs are supported in test interpret mode only, to be updated in a forthcoming RPerl release.

A list of all valid RPerl compiler options may be seen by issuing the following command:

$ rperl -?

You may find the same information by viewing the following links:

rperl

https://metacpan.org/pod/distribution/RPerl/script/rperl

To partially-compile-then-execute the preceeding RPerl example program in test mode, you may copy and paste the entire program (from shebang to second print) into a temporary file such as /tmp/foobar.pl, then execute the following command:

$ rperl -t /tmp/foobar.pl

The output of this example program should be:

have $foo = 33
have $bar = 1_932
have $baz = 58.545_454_545_454_5

Please see "CHAPTER 11: CLASSES, PACKAGES, MODULES, LIBRARIES" for more information about compiling Perl modules.

Section 1.25: A Whirlwind Tour of RPerl

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:

  • Church & Spirituality

  • Boy Scouts of America

  • Cane Juggling & Circus Performance

  • Linux Operating Systems

  • Charitable & Fraternal Organizations

  • Homeschooling & Higher Education

  • Astrophysics & Mathematics

  • Entrepreneuriship & Business

  • High-Performance Computing

  • Professional Space Exploration

  • Family Life

These areas of interest are reflected in the tone and intention of RPerl.

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 "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 a grant from The Perl Foundation.

Section 1.25.3: Performance Of RPerl

The question of "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:

http://rperl.org/performance_benchmarks.html

The most condensed answer is that "RPerl is really fast." Utilizing RPerl's fastest execution modes, we see performance very close to the highly-optimized C++ programming language, which means RPerl is now among the short list of "world's fastest languages" along with C, C++, and Fortran.

Section 1.25.4: The Low-Magic Perl Commandments

The high-magic features of Perl are primarily responsible for how slow Perl runs for general-purpose computations. The "R" in RPerl stands for "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-nots for high-magic vs low-magic Perl programming is called 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.

http://rperl.org/the_low_magic_perl_commandments.html

The LMPC draw inspiration from, and (wherever possible) work together with Damian Conway's Perl Best Practices and Jeffrey Thalhammer's Perl::Critic software.

http://shop.oreilly.com/product/9780596001735.do

http://search.cpan.org/~thaljef/Perl-Critic/lib/Perl/Critic/PolicySummary.pod

Section 1.25.5: The Book Of RPerl

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.)

A Perlite is an adherent to the Perlism religion. Perlism has a revered founder, Saint Larry (himself a devout Christian); a prophet, The Voice In The Wilderness (Will); a monastary and shrine, Perl Monks; commandments, The LMPC; proverbs from Saint Larry including TIMTOWTDI, LMFB, and HTAAOF; and canonical scriptures, including Saint Larry's Apocalypses and The Voice's The Book Of RPerl.

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.

http://rperl.org/the_book_of_rperl.html

Section 1.26: Exercises

1. Hello World [ 15 mins ]

On a computer with RPerl already installed, create a directory named LearningRPerl containing a sub-directory named Chapter1. Using the Foo Bar example program as a template, manually type a new RPerl program into a file named exercise_1-hello_world.pl inside the LearningRPerl/Chapter1 sub-directory. The sole purpose of your first program is to use the print operator and simply display the following one line of text output, followed by one newline character:

Hello, World!

Run your new program by issuing the following command at your terminal command prompt:

$ rperl -t LearningRPerl/Chapter1/exercise_1-hello_world.pl

HINT: You only need the USER DEFAULT 1 critic line, so your resulting program should be 7 lines long, not counting comments or blank lines.

2. RPerl Commands [ 15 mins ]

First, run the following RPerl command, and observe the output for use in 2a and 2b below:

$ rperl -?

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:

$ 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

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?

3. Foo Bar Arithmetic [ 15 mins ]

Manually type the entire Foo Bar example program into a file named exercise_3-foo_bar_arithmetic.pl inside the LearningPerl/Chapter1 sub-directory. (Even if you have already used copy-and-paste on the Foo Bar 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 an extra numeric variable named $baz, set its value to $bar / $foo, and use print to generate the following output:

have $foo = 33
have $bar = 966
have $baz = 29.2727272727273

Run your program thusly:

$ rperl -t LearningRPerl/Chapter1/exercise_3-foo_bar_arithmetic.pl

CHAPTER 2: SCALAR DATA

Most programming languages include the basic principles of using named "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 $foo or $bar or $quux, and each potentially containing a different value.

A single piece of data, such as one number or one string, is called a "scalar". Multiple pieces of data combined into a single aggregate structure may be either an "array" or a "hash", described in chapters 3 and 6, respectively. (Although sharing the same terminology, the hash data structure is not related to the hash # tic-tac-toe character.) In normal Perl, only scalar variable names begin with the $ dollar sign "sigil", while aggregate data structures are stored in variables starting with different sigils like @ or %. In RPerl, all variable names begin the $ sigil, both scalar types and aggregate structures alike.

RPerl provides 7 scalar data types:

  • boolean

  • unsigned_integer

  • integer (core)

  • gmp_integer

  • number (core)

  • character

  • string (core)

START HERE: add blurb about core types, add unsigned_integer & gmp_integer examples & sections START HERE: add blurb about core types, add unsigned_integer & gmp_integer examples & sections START HERE: add blurb about core types, add unsigned_integer & gmp_integer examples & sections

A single group of actual numeric digit(s) or quoted string character(s) is called a "literal", such as:

-21         # integer or number

'howdy'     # string

-23.421_12  # number

1_234_567   # integer or number

'One million, two-hundred-thirty-four thousand, five-hundred-sixty-seven'  # string

"\n"        # newline character or string

'1'         # character or string

q{}         # empty character or string

0           # boolean or integer or number

Section 2.1: Numbers (Numeric Data)

RPerl provides 3 numeric data types:

  • boolean

    a boolean logic value, either 0 or 1

  • integer

    a whole number value, either negative, 0, or positive

  • number

    a floating-point decimal number value, either negative, 0, or positive

Section 2.1.1: Bool Literals

The most memory-efficient numeric literal is boolean, which represents a single "bit" (binary digit) of information. A 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

Section 2.1.2: Integer Literals

The next most efficient numeric literal is integer, which represents a single whole (non-decimal) number. An integer literal may describe any positive or negative whole number, within the data size limits of your operating system and computer hardware.

-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 limits

Section 2.1.3: Number Literals

The number numeric literal represents a single floating-point (decimal) number, and may express any real number within your computer's 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 limits

Section 2.1.4: Underscore Digit Separators

For integer and number literals, an "underscore" _ 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

Section 2.1.5: Optional Positive Sign

For integer and number literals, an optional + plus sign may be prepended to explicitly indicate a numeric literal is positive (greater than zero).

1   # positive one
+1  # also positive one

BEST PRACTICES

  • When only positive numeric literals are used in one area of code, omit positive signs.

  • When both positive and negative literals are used in one code area, use signs for all applicable literals.

+23    # good integer, but not aligned with other un-signed literal below
+55.6  # good number,  but not aligned with other un-signed literal below
42

23     # best integer for all positive literals, aligned
55.6   # best number  for all positive literals, aligned
42

23     # good integer, but not aligned with other signed literals below
55.6   # good number,  but not aligned with other signed literals below
-21
-66.5

+23    # best integer for mixed-sign literals, aligned
+55.6  # best number  for mixed-sign literals, aligned
-21
-66.5

Section 2.1.6: Scientific Notation

For integer and number literals, very large or very small numbers should be represented using "scientific notation", where each number is normalized to have exactly one digit to the left of the decimal point, then a lower-case e character and an appropriate integer power-of-ten is appended to the resulting normalized floating-point number. The e character stands for "exponent", as in "exponent of ten", and the Perl style of scientific notation is sometimes more accurately referred to as "scientific e notation".

As with normal integers, negative exponents must be prefixed with a - minus sign and positive exponents may be optionally prefixed with a + 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 limits
-1.234_567e-24  # good number, same as "-0.000_000_000_000_000_000_000_001_234_567" in scientific notation

BEST PRACTICES

  • Use 2 digits to represent all exponents.

  • When only positive exponents are used, omit exponent signs.

  • When both positive and negative exponents are used, use signs for all exponents.

   1_234_567_000      # good integer
   1.234_567_000e9    # good number, but does not align with two-digit exponents below
   1.234_567_000e09   # best number for all-positive exponents, aligned with two-digit exponent below
   1.234_567_000e19

   1.234_567_000e+09  # good number, but not aligned with positive exponents below
   1.234_567_000e09   # best number for all-positive exponents, aligned with positive exponent below
   1.234_567_000e19

   1.234_567_000e09   # good number, but not aligned with signed exponents below
   1.234_567_000e+09  # best number for mixed-sign exponents, aligned with signed exponent below
   1.234_567_000e-09

   +1.537_969_711_485_091_65e+21  # best number for mixed-sign exponents
   -2.591_931_460_998_796_41e+01  # best number for mixed-sign exponents
   +1.792_587_729_503_711_81e-01  # best number for mixed-sign exponents
   +2.680_677_724_903_893_22e-03  # best number for mixed-sign exponents
   +1.628_241_700_382_422_95e-03  # best number for mixed-sign exponents
   -9.515_922_545_197_158_70e-15  # best number for mixed-sign exponents

Section 2.1.7: Numeric Operators

[ INSERT OPS ]

Section 2.2: Strings (Text Data)

RPerl provides 2 text data types:

  • character

    a single text character; either a letter, number, or special character

  • string

    one or more text characters; any combination of letters, numbers, and special characters

RPerl provides 3 delimiters for enclosing text data:

  • 'single quotes'

  • "double quotes"

  • q{q quotes}

Section 2.2.1: Char Literals

The most memory-efficient text literal is character, which represents exactly zero or one character of information. A character may express the value of any single numeric digit (0, 1, 2, ..., 8, 9); letter (a, b, c, ..., y, z, A, B, C, ..., Y, Z ); or special ASCII character (!, #, *, +, etc). If the character literal has length zero, it is called the "empty character" and contains no data.

''          # not a character, use q{} for empty character
'0'         # character
'h'         # character
'+'         # character
'\n'        # not a character, too many characters, use "\n" for newline character
'-1'        # not a character, too many characters
'howdy23!'  # not a character, too many characters

""          # not a character, use q{} for empty character
"0"         # character
"h"         # character
"+"         # character
"\n"        # character, newline
"-1"        # not a character, too many characters & invalid use of double quotes
"howdy23!"  # not a character, too many characters & invalid use of double quotes

q{}          # character, empty
q{0}         # character
q{h}         # character
q{+}         # character
q{\n}        # not a character, too many characters, use "\n" for newline character
q{-1}        # not a character, too many characters
q{howdy23!}  # not a character, too many characters

Section 2.2.2: String Literals

Any text data more than 1 character in length must be represented by a string literal, which is comprised of any combination of valid character literal characters (numeric digits, letters, and special ASCII characters). Like the empty character, if a string literal has length zero then it is called the "empty string" and contains no data.

''          # not a string, use q{} for empty string
'0'         # string
'h'         # string
'+'         # string
'\n'        # string, not a newline, use "\n" for string containing newline
'-1'        # string
'howdy23!'  # string

""          # not a string, use q{} for empty string
"0"         # not a string, invalid use of double quotes, must contain newline or tab character(s)
"h"         # not a string, invalid use of double quotes, must contain newline or tab character(s)
"+"         # not a string, invalid use of double quotes, must contain newline or tab character(s)
"\n"        # string, contains only newline character
"-1"        # not a string, invalid use of double quotes, must contain newline or tab character(s)
"howdy23!"  # not a string, invalid use of double quotes, must contain newline or tab character(s)

q{}          # empty string
q{0}         # string
q{h}         # string
q{+}         # string
q{\n}        # string, not a newline, use "\n" for string containing newline
q{-1}        # string
q{howdy23!}  # string

Section 2.2.3: Single Quotes

Text literals enclosed in single quotes are the simplest and most common case in RPerl.

Single-quoted text literals are not "interpolated", which means the literal's data contents are not changed by Perl or RPerl in any way. Because single quotes do not activate string interpolation, the literal '\n' is not a newline character; instead, it is simply two normal characters, a backslash followed by a lowercase letter n. Do not use single quotes to represent a newline or tab character, use "\n" or "\t" instead.

Do not use single quotes to represent an empty character or empty string, use q{} instead.

A single-quoted text literal begins and ends with the single quote character, therefore it cannot logically contain a single quote character as part of the literal data itself. (RPerl does not support backslash-escaped single quote characters within a single-quoted string like normal Perl does, as this can be considered a simple form of string interpolation.)

Single-quoted text literals must not contain:

  • ' (single quote character)

  • \ (single backslash as final character)

  • \\\ (odd number of backslashes as final characters)

  • no characters

Single-quoted text literals may contain:

  • " (double quote character)

  • } (right curly brace character)

  • \ (single backslash as non-final character)

  • \\\ (odd number of backslashes as non-final characters)

  • any other characters

Section 2.2.4: Double Quotes

Text literals enclosed in double quotes are fully interpolated in normal Perl, and are only used for trivial interpolation of strings containing the special "\n" newline or "\t" tab characters in RPerl. All double-quoted strings must contain at least one newline or tab character.

String interpolation in normal Perl is triggered by finding either the $ dollar sign or @ "at sign" characters inside of a double-quoted string literal. Because RPerl does not support string interpolation, double-quoted string literals must not contain the $ or @ characters.

String interpolation is also triggered by finding a \ backslash character followed by one or more special "escape characters", which are mostly comprised of otherwise-normal characters such as numbers and lowercase letters. When a backslash is followed by valid escape characters, it is called an "escape sequence". Each valid escape sequence actually counts as only one character, even though it is represented by 2 or more typed characters, so a single escape sequence may be utilized as either a text literal or a string text literal. The special \n newline and \t tab characters are themselves escape sequences, and are the only allowed escape sequences in RPerl. (Thus, "\n" and "\t" may both be utilized as either a or string text literal in RPerl.) Double-quoted string literals must not contain any backslash characters, other than those used in newline and tab escape sequences.

Double-quoted text literals must not contain:

  • " (double quote character)

  • $ (dollar sign character)

  • @ (at sign character)

  • \ (extra backslash character, other than \n or \t)

  • no characters

Double-quoted text literals must contain 1 or more:

  • \n (newline character)

  • \t (tab character)

Double-quoted text literals may contain:

  • ' (single quote character)

  • } (right curly brace character)

  • any other characters

BEST PRACTICES

  • Use double-quoted string literals to contain newline and tab characters only, not other normal characters.

  • To represent a mixture of normal characters with newline and/or tab characters, enclose the normal characters in single quotes, enclose the newline and tab characters in double quotes, and use the . dot "string concatenation" operator to append one string literal to the other. (Please see "Section 2.2.6: String Operators" for more info about string concatenation.)

Section 2.2.5: q Quotes

Text literals enclosed in q{} "q quotes" begin with the lowercase q followed by { left curly brace characters, and end with the } right curly brace character. You must use q quotes to represent q{} empty text literals containing no characters.

[ INSERT BACKSLASHES, QUOTES ]

[ INSERT BACKSLASHES FOR SINGLE AND DOUBLE QUOTE SECTIONS ABOVE]

q-quoted text literals must not contain:

  • } (right curly brace character)

  • \ (single backslash as final character)

  • \\\ (odd number of backslashes as final characters)

q-quoted text literals may contain:

  • ' (single quote character)

  • " (double quote character)

  • \ (single backslash as non-final character)

  • \\\ (odd number of backslashes as non-final characters)

  • no characters

  • any other characters

[ INSERT BEST PRACTICES ]

Section 2.2.6: String Operators

[ INSERT OPS ]

Section 2.3: Perl’s Built-in Warnings

[INSERT WARNINGS]

Section 2.4: Scalar Variables

An RPerl "expression" is any general-purpose language component which either returns a value or is a literal value itself.

An RPerl "statement" is any general-purpose language component which performs some action(s).

An RPerl "named operator" is any of the 220+ Perl named operators, although RPerl only supports the low-magic forms of each operator.

An RPerl "operation" is the equivalent of a single sentence in human language, and may be either an expression followed by a ; semicolon punctuation character, or a named operator followed by a semicolon, or a statement.

The = equal sign is the assignment operator, used to set the variable on its left to store the value of the expression on its right.

Perl's my keyword is used to declare a new variable, and optionally initialize it to a starting value when combined with the = assignment operator.

Normal Perl does not support specific data types, so in Perl one variable named $foo may be initialized with a numeric value, then the same $foo variable may be changed to hold a string value without any warning or error.

my $foo = 23;
$foo = 'twenty-three';  # just fine in normal Perl

On the other hand, RPerl requires the use of data types for each and every variable.

my $foo = 23;  # error in RPerl, all modes

my number $foo = 23;
$foo = 'twenty-three';  # error in RPerl, compiled (non-test) modes, assigning string literal to number variable

my number $foo = 23;
$foo = 42;  # just fine in RPerl

Data types make your code much more readable and much, much faster. Learn to love data types. Now.

Section 2.4.x: Bool Data Type

The most efficient data type is boolean, which stores a single "bit" (binary digit) of information. A boolean may only hold the values of exactly 0 or 1.

my boolean $foo = 0;     # fine
my boolean $bar = 1;     # fine
my boolean $baz = -1.5;  # error in RPerl, compiled (non-test) modes

Section 2.4.x: Integer Data Type

The next most efficient data type is integer, which stores a single whole (non-decimal) number. An integer may hold any positive or negative whole number, within the data size limits of your operating system and computer hardware.

my integer $foo  = -23;     # fine
my integer $bar  = 0;       # fine
my integer $baz  = 42_230;  # fine
my integer $bax  = 42.1;    # error in RPerl, compiled (non-test) modes
my integer $quux = -999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999;  # likely error or data corruption, outside limits

Section 2.4.x: Number Data Type

The number data type stores a single floating-point (decimal) number, and may hold any real number within your computer's limits.

my number $foo  = -23.42;     # fine
my number $bar  = 0.000_001;  # fine
my number $baz  = 42.23;      # fine
my number $bax  = 42;         # fine
my number $quux = -4_123.456_789_123_456_789_123_456_789_123_456_789_123_456_789_123_456_789_123_456;  # likely error or data loss, outside limits

Section 2.4.x: Type Conversion

To convert from one data type to another, we use the RPerl type conversion subroutines, shown below for numeric types only:

  • boolean_to_integer()

  • boolean_to_number()

  • integer_to_boolean()

  • integer_to_number()

  • number_to_boolean()

  • number_to_integer()

my integer $foo = 23;
my number $bar  = $foo;  # error in RPerl, compiled (non-test) modes, type mismatch

my integer $foo = 23;
my number $bar  = integer_to_number($foo);  # fine, $bar is now 23.0

my number $foo  = 23.42;
my integer $bar = $foo;  # error in RPerl, compiled (non-test) modes, type mismatch

my number $foo  = 23.42;
my integer $bar = number_to_integer($foo);  # fine, $bar is now 23

Section 2.4.x Scope, Type, Name, Value

START HERE START HERE START HERE

The "scope" of a variable is either local using the my keyword, or global using the our keyword. Local variables are only usable within their own enclosing code block such as a conditional (section xxx), loop (xxx), or subroutine (chapter 4).

and global variables are usable within any code block accessible by the Perl interpreter or (RPerl compiler).

Except for certain special circumstances, all variables in RPerl are locally-scoped using my.

[ INSERT SCOPE TYPE NAME VALUE ]

Section 2.5: Constant Data

[INSERT CONSTANTS]

Section 2.6: Output With print

[INSERT PRINT]

Section 2.7: The if Control Structure

[INSERT IF]

Section 2.8: Getting User Input

[INSERT INPUT]

Section 2.9: The chomp Operator

[INSERT CHOMP]

Section 2.10: The while Control Structure

[INSERT WHILE]

Section 2.11: The undef Value

[INSERT UNDEF]

Section 2.12: The defined Function

[INSERT DEFINED]

Section 2.13: Exercises

1. XXXYYYZZZ [ XYZ mins ]

[INSERT EXERCISES]

CHAPTER 3: LISTS & ARRAYS

[INSERT CHAPTER]

CHAPTER 4: SUBROUTINES

[INSERT CHAPTER]

CHAPTER 5: INPUT & OUTPUT

[INSERT CHAPTER]

CHAPTER 6: HASHES

[INSERT CHAPTER]

CHAPTER 7: REGULAR EXPRESSIONS

[INSERT CHAPTER]

CHAPTER 8: REGULAR EXPRESSIONS MATCHING

[INSERT CHAPTER]

CHAPTER 9: REGULAR EXPRESSIONS PROCESSING

[INSERT CHAPTER]

CHAPTER 10: CONTROL STRUCTURES

[INSERT CHAPTER]

CHAPTER 11: CLASSES, PACKAGES, MODULES, LIBRARIES

[INSERT CHAPTER]

CHAPTER 12: FILE TESTS

[INSERT CHAPTER]

CHAPTER 13: DIRECTORY OPERATIONS

[INSERT CHAPTER]

CHAPTER 14: STRINGS & SORTING

[INSERT CHAPTER]

CHAPTER 15: SMART MATCHING & GIVEN-WHEN

[INSERT CHAPTER]

CHAPTER 16: PROCESS MANAGEMENT

[INSERT CHAPTER]

CHAPTER 17: SOME ADVANCED TECHNIQUES

[INSERT CHAPTER]

APPENDIX A: EXERCISE ANSWERS

Chapter 1, Exercise 1

This exercise is commonly used as the first task for new programmers, or for programmers who are learning a new language.

The goal of this exercise is to become familiar with the boilerplate (often-repeated template) RPerl HEADER and CRITICS code sections, as well as the basic print command.

The first line, starting with #! and called a "shebang", tells the operating system to run this program using Perl.

The 4 lines in the HEADER section tell Perl to run this program using RPerl, and the $VERSION number may be incremented for each update to this file.

The line in the CRITICS section, starting with ##, tells RPerl to allow hard-coded numeric values (not used in this program), as well as the print operator.

The last line, in the OPERATIONS section, calls the print operator to simply display the text "Hello, world!" followed by a newline character, combined into a single string value by the . (single dot) string concatenation operator.

All other lines beginning with # are comments and, along with blank lines, may be safely ignored or removed.

#!/usr/bin/perl

# Learning RPerl, Chapter 1, Exercise 1
# Print "Hello, world!"; the classic first program for new programmers

# [[[ 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

# [[[ OPERATIONS ]]]
print 'Hello, world!' . "\n";

Example execution and output:

$ rperl -t LearningRPerl/Chapter1/exercise_1-hello_world.pl
Hello, world!

Chapter 1, Exercise 2

The goal of this exercise is to become familiar with the rperl command.

Example execution and output for 2a and 2b:

$ rperl -?
Usage:
            rperl [OPTIONS] input_program_0.pl [input_program_1.pl input_program_2.pl ...]
            rperl [OPTIONS] MyClassFoo.pm [MyClassBar.pm MyClassBat.pm ...]
            rperl [OPTIONS] input_program_0.pl MyClassFoo.pm [input_program_1.pl ... MyClassBar.pm ...]

Options:
    --help _OR_ -h _OR_ -?
            Print a brief help message.

    --version _OR_ -v
            Print version number and copyright information.
            Lowercase 'v' not to be confused with uppercase 'V' in 'Verbose' option below.

    --dependencies _OR_ -d
    --nodependencies _OR_ -nod
            Follow and compile dependencies, or not.
            Enabled by default, equivalent to '--mode dependencies=ON' option.
            Lowercase 'd' not to be confused with uppercase 'D' in 'Debug' option below.
            WARNING: Disabling dependencies will likely cause errors or undefined behavior.

    --infile=MyFile.pm _OR_ -i=MyFile.pm
            Specify input file, may be repeated for multiple input files.
            Option prefix '--infile' may be entirely omitted.
            Option prefix MUST be omitted to specify wildcard for multiple input files.

    --outfile=MyFile _OR_ -o=MyFile
            Specify output file prefix, may be repeated for multiple output files.
            RPerl *.pm input file with PERL ops will create MyFile.pmc output file.
            RPerl *.pl input file with PERL ops will create my_file (or my_file.exe) & my_file.pmc output files.
            RPerl *.pm input file with CPP ops will create MyFile.pmc, MyFile.cpp, & MyFile.h output files.
            RPerl *.pl input file with CPP ops will create myfile (or myfile.exe on Windows), MyFile.pmc, MyFile.cpp, & MyFile.h output files.
            Option may be entirely omitted, 'MyFile.*' input file will default to 'MyFile.*' out.

    --mode ops=PERL _OR_ -m ops=PERL
    --mode ops=CPP _OR_ -m ops=CPP
            Specify operations mode, CPP by default.
            If set to PERL, forces types mode to PERL & compile mode to PARSE or GENERATE; test mode, does not actually compile.

    --mode types=PERL _OR_ -m types=PERL
    --mode types=CPP _OR_ -m types=CPP
    --mode types=DUAL _OR_ -m types=DUAL
            Specify data types mode, CPP by default.
            DUAL mode allows generate-once-compile-many types, selected by '#define __FOO__TYPES' in lib/rperltypes_mode.h file.

    --mode check=OFF _OR_ -m check=OFF
    --mode check=ON _OR_ -m check=ON
    --mode check=TRACE _OR_ -m check=TRACE
            Specify data type checking mode, TRACE by default.

    --mode dependencies=OFF _OR_ -m dependencies=OFF
    --mode dependencies=ON _OR_ -m dependencies=ON
            Specify dependencies mode, ON by default.

    --mode compile=PARSE _OR_ -m compile=PARSE
    --mode compile=GENERATE _OR_ -m compile=GENERATE
    --mode compile=SUBCOMPILE _OR_ -m compile=SUBCOMPILE
            Specify compile mode, SUBCOMPILE by default.

    --mode execute=OFF _OR_ -m execute=OFF
    --mode execute=ON _OR_ -m execute=ON
            Specify execute mode, ON by default.

    --mode label=OFF _OR_ -m label=OFF
    --mode label=ON _OR_ -m label=ON
            Specify source section label mode, ON by default.

    --compile _OR_ -c
    --nocompile _OR_ -noc
            Generate & subcompile C++ source code, or not.
            Enabled by default, equivalent to '--mode compile=SUBCOMPILE' option.

    --execute _OR_ -e
    --noexecute _OR_ -noe
            Run input code after optional compile, or not.
            Enabled by default for *.pl program input files, always disabled for *.pm module input files or multiple input files.
            Equivalent to '--mode execute=ON' option.

    --Verbose _OR_ -V
    --noVerbose _OR_ -noV
            Include additional user information in output, or not.
            Disabled by default, equivalent to `export RPERL_VERBOSE=1` shell command.
            Uppercase 'V' not to be confused with lowercase 'v' in 'version' option above.

    --Debug _OR_ -D
    --noDebug _OR_ -noD
            Include system diagnostic information in output, or not.
            Disabled by default, equivalent to `export RPERL_DEBUG=1` shell command.
            Uppercase 'D' not to be confused with lowercase 'd' in 'dependencies' option above.

    --Warnings _OR_ -W
    --noWarnings _OR_ -noW
            Include system warnings in output, or not.
            Enabled by default, equivalent to `export RPERL_WARNINGS=0` shell command.

    --test _OR_ -t
            Test mode: Perl ops, Perl types, Parse & Generate (no Save or Compile)
            Disabled by default, equivalent to '--mode ops=PERL --mode types=PERL --mode compile=GENERATE' options.

Example execution and output for 2c and 2d:

$ rperl -t -V LearningRPerl/Chapter1/exercise_1-hello_world.pl 
Verbose Flag:       1
Debug Flag:         0
Test Flag:          1
Input File:         LearningRPerl/Chapter1/exercise_1-hello_world.pl
Output File(s):     LearningRPerl/Chapter1/exercise_1-hello_world  
Modes:              ops => PERL, types => PERL, check => TRACE, compile => GENERATE, execute => ON, label => ON

DEPENDENCIES:       Follow & find all deps...    0 found.
PARSE PHASE 0:      Check     Perl syntax...        done.
PARSE PHASE 1:      Criticize Perl syntax...        done.
PARSE PHASE 2:      Parse    RPerl syntax...        done.
GENERATE:           Generate RPerl syntax...        done.
EXECUTE:            Run code...

Hello, world!


$ rperl -t -D LearningRPerl/Chapter1/exercise_1-hello_world.pl 
in rperl, have $RPerl::DEBUG = 1
in rperl, have $RPerl::VERBOSE = 0
Hello, world!


$ rperl -t -V -D LearningRPerl/Chapter1/exercise_1-hello_world.pl 
Verbose Flag:       1
Debug Flag:         1
Test Flag:          1

in rperl, have $RPerl::DEBUG = 1
in rperl, have $RPerl::VERBOSE = 1
Input File:         LearningRPerl/Chapter1/exercise_1-hello_world.pl
Output File(s):     LearningRPerl/Chapter1/exercise_1-hello_world  
Modes:              ops => PERL, types => PERL, check => TRACE, compile => GENERATE, execute => ON, label => ON

DEPENDENCIES:       Follow & find all deps...    0 found.
PARSE PHASE 0:      Check     Perl syntax...        done.
PARSE PHASE 1:      Criticize Perl syntax...        done.
PARSE PHASE 2:      Parse    RPerl syntax...        done.
GENERATE:           Generate RPerl syntax...        done.
EXECUTE:            Run code...

Hello, world!

Of the above 3 commands executed for 2c and 2d, the first includes normal output plus additional verbose output; the second includes normal output plus additional debugging output (minimal in this simple case); and the third includes normal output plus both verbose and debugging output.

Chapter 1, Exercise 3

The goal of this exercise is to become familiar with basic variables and arithmetic.

The shebang line, HEADER section, and first line in the CRITICS section are the same boilerplate as the previous exercise.

The second line in the CRITICS section tells RPerl to allow the $ (dollar) character, among others, to be displayed using the print operator.

The first 3 lines in the OPERATIONS section each declare a new variable; $foo and $bar each hold an integer (non-floating-point) numeric value, while $baz holds a number (floating-point) value.

The $foo and $bar variables receive their values from hard-coded numeric values being operated upon by the + (plus sign) addition and * (asterisk) multiplication operators, respectively; the $baz variable receives its value from the the $foo and $bar variables being operated upon by the / (forward slash) division operator.

The last 3 lines call the print operator to display the names of each variable, followed by each variable's respective value converted from number to underscore-formatted string, followed by a newline character.

#!/usr/bin/perl

# Learning RPerl, Chapter 1, Exercise 3
# 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 = $bar / $foo;
print 'have $foo = ' . to_string($foo) . "\n";
print 'have $bar = ' . to_string($bar) . "\n";
print 'have $baz = ' . to_string($baz) . "\n";

Example execution and output:

$ rperl -t LearningRPerl/Chapter1/exercise_3-foo_bar_arithmetic.pl 
have $foo = 33
have $bar = 1_932
have $baz = 58.545_454_545_454_5

Chapter 2, Exercise 1

The goal of this exercise is to become familiar with constant values.

The first line in the CRITICS section tells RPerl to allow hard-coded numeric values as well as the print operator, both of which are utilized in this program.

The second line in the CRITICS section tells RPerl to allow the use constant operation.

The line in the CONSTANTS section declares a number (floating-point) constant value named PI, automatically accessible via a subroutine named PI().

The inner type variable $TYPED_PI is only used for RPerl parsing purposes; for example, if your constant is named FOO then you should declare it using the inner type variable $TYPED_FOO and you should access it by calling the subroutine FOO(), but you should never directly utilize the variable $TYPED_FOO anywhere else in your code.

The first 2 lines in the OPERATIONS section each create a new number variable, with $radius set to the hard-coded value of 12.5 and $circumference set to the well-known basic geometry formula "circumference equals 2 pi times radius".

The last 3 lines call the print operator to display the values of PI(), $radius, and $circumference, each followed by a newline character.

#!/usr/bin/perl

# Learning RPerl, Chapter 2, Exercise 1
# Find the circumference of a circle with hard-coded radius of 12.5 units

# [[[ 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(ProhibitConstantPragma ProhibitMagicNumbers)  # USER DEFAULT 3: allow constants

# [[[ CONSTANTS ]]]
use constant PI => my number $TYPED_PI = 3.141_592_654;

# [[[ OPERATIONS ]]]
my number $radius = 12.5;
my number $circumference = 2 * PI() * $radius;

print 'Pi = ' . to_string(PI()) . "\n";
print 'Radius = ' . to_string($radius) . "\n";
print 'Circumference = 2 * Pi * Radius = 2 * ' . to_string(PI()) . ' * ' . to_string($radius) . ' = ' . to_string($circumference) . "\n";

Example execution and output:

$ rperl -t LearningRPerl/Chapter2/exercise_1-circumference_of_specific_radius.pl 
Pi = 3._141_592_654
Radius = 12.5
Circumference = 2 * Pi * Radius = 2 * 3._141_592_654 * 12.5 = 78.539_816_35

Chapter 2, Exercise 2

The goal of this exercise is to become familiar with accepting user keyboard input.

The third line in the CRITICS section tells RPerl to allow user input via the STDIN standard stream, a software input connection which is attached to the keyboard by default.

The second line in the OPERATIONS section creates a string variable $radius_string, and assigns to it the text value typed by the user on their keyboard.

The third line in the OPERATIONS section creates a number variable $radius, and assigns to it the numeric value returned by calling the RPerl type conversion operator string_to_number() on the string variable $radius_string.

This exercise is otherwise identical to the previous exercise.

#!/usr/bin/perl

# Learning RPerl, Chapter 2, Exercise 2
# Find the circumference of a circle with any radius entered by the user

# [[[ 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(ProhibitConstantPragma ProhibitMagicNumbers)  # USER DEFAULT 3: allow constants
## no critic qw(ProhibitExplicitStdin)  # USER DEFAULT 4: allow <STDIN> prompt

# [[[ CONSTANTS ]]]
use constant PI => my number $TYPED_PI = 3.141_592_654;

# [[[ OPERATIONS ]]]
print 'Please input radius: ';
my string $radius_string = <STDIN>;
my number $radius = string_to_number($radius_string);
my number $circumference = 2 * PI() * $radius;

print "\n";
print 'Pi = ' . to_string(PI()) . "\n";
print 'Radius = ' . to_string($radius) . "\n";
print 'Circumference = 2 * Pi * Radius = 2 * ' . to_string(PI()) . ' * ' . to_string($radius) . ' = ' . to_string($circumference) . "\n";

Example execution, input, and output:

$ rperl -t LearningRPerl/Chapter2/exercise_2-circumference_of_any_radius.pl 
Please input radius: 2

Pi = 3.141_592_654
Radius = 2
Circumference = 2 * Pi * Radius = 2 * 3.141_592_654 * 2 = 12.566_370_616

Chapter 2, Exercise 3

The goal of this exercise is to become familiar with conditional statements and comparison operators.

In the OPERATIONS section, the line starting with if ($radius >= 0) denotes the beginning of a conditional statement: if the numeric value of the variable $radius is greater-than-or-equal-to 0, then the normal calculation for $circumference is used; if $radius is less than 0 (physically impossible), then a warning message is printed and $circumference is set to 0.

This exercise is otherwise identical to the previous exercise.

#!/usr/bin/perl

# Learning RPerl, Chapter 2, Exercise 3
# Find the circumference of a circle with any positive radius entered by the user

# [[[ 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(ProhibitConstantPragma ProhibitMagicNumbers)  # USER DEFAULT 3: allow constants
## no critic qw(ProhibitExplicitStdin)  # USER DEFAULT 4: allow <STDIN> prompt

# [[[ CONSTANTS ]]]
use constant PI => my number $TYPED_PI = 3.141_592_654;

# [[[ OPERATIONS ]]]
print 'Please input radius: ';
my string $radius_string = <STDIN>;
my number $radius = string_to_number($radius_string);
my number $circumference;

if ($radius >= 0) {
    $circumference = 2 * PI() * $radius;
}
else {
    print 'Negative radius detected, defaulting to zero circumference!' . "\n";
    $circumference = 0;
}

print "\n";
print 'Pi = ' . to_string(PI()) . "\n";
print 'Radius = ' . to_string($radius) . "\n";
print 'Circumference = 2 * Pi * Radius = 2 * ' . to_string(PI()) . ' * ' . to_string($radius) . ' = ' . to_string($circumference) . "\n";

Example execution, input, and output:

$ rperl -t LearningRPerl/Chapter2/exercise_3-circumference_of_any_positive_radius.pl 
Please input radius: -2
Negative radius detected, defaulting to zero circumference!

Pi = 3._141_592_654
Radius = -2
Circumference = 2 * Pi * Radius = 2 * 3._141_592_654 * -2 = 0

Chapter 2, Exercise 4

The goal of this exercise is to gain further exposure to the STDIN standard stream and variable multiplication.

In the OPERATIONS section, STDIN is accessed to collect user input for both $multiplicator_string and $multiplicand_string variables.

These 2 string variables are converted from text values to numeric values by calling string_to_number(), then multiplied via the * multiplication operator, and the results displayed by calling print.

#!/usr/bin/perl

# Learning RPerl, Chapter 2, Exercise 4
# Find the product of any two numbers entered by the user

# [[[ 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(ProhibitExplicitStdin)  # USER DEFAULT 4: allow <STDIN> prompt

# [[[ OPERATIONS ]]]
print 'Please input multiplicator: ';
my string $multiplicator_string = <STDIN>;
my number $multiplicator = string_to_number($multiplicator_string);

print 'Please input multiplicand: ';
my string $multiplicand_string = <STDIN>;
my number $multiplicand = string_to_number($multiplicand_string);

my number $product = $multiplicator * $multiplicand;

print "\n";
print 'Product = Multiplicator * Multiplicand = ' . to_string($multiplicator) . ' * ' . to_string($multiplicand) . ' = ' . to_string($product) . "\n";

Example execution, input, and output:

$ rperl -t LearningRPerl/Chapter2/exercise_4-product_of_any_two_numbers.pl 
Please input multiplicator: 2112
Please input multiplicand: 23.42

Product = Multiplicator * Multiplicand = 2_112 * 23.42 = 49_463.04

Chapter 2, Exercise 5

The goal of this exercise is to become familiar with the x string repeat operator.

In the OPERATIONS section, STDIN is accessed twice to collect user input for a string variable $repeat_string to be repeated, and an integer variable $repeat_integer to specify the number of repetitions.

The last line contains 2 operators, print and the x string repeat operator.

Like the . (single dot) string concatenation operator, the x operator has a higher precedence than print and is thus executed first, generating a single string value comprised of the original string repeated 0 or more times, then the resulting string is displayed by calling print.

#!/usr/bin/perl

# Learning RPerl, Chapter 2, Exercise 5
# Repeat any string any number of times, both values entered by the user

# [[[ 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(ProhibitExplicitStdin)  # USER DEFAULT 4: allow <STDIN> prompt

# [[[ OPERATIONS ]]]
print 'Please input string to be repeated: ';
my string $repeat_string = <STDIN>;

print 'Please input integer (whole number) times to repeat string: ';
my string $repeat_integer_string = <STDIN>;
my integer $repeat_integer = string_to_integer($repeat_integer_string);

print "\n";
print $repeat_string x $repeat_integer;

Example execution, input, and output:

$ rperl -t LearningRPerl/Chapter2/exercise_5-string_repeat.pl 
Please input string to be repeated: howdy
Please input integer (whole number) times to repeat string: 3

howdy
howdy
howdy

Chapter 3, Exercise 1

The goal of this exercise is to become familiar with while and foreach loops, arrays, and array operators.

The first line in the OPERATIONS section declares a new variable $input_strings of type string_arrayref, which is capable of storing 0 or more individual string values, and $input_strings is then initialized to contain the empty set [].

The line starting with while (my string $input_string = <STDIN>) denotes the beginning of an iterative (repeating) loop statement, which continues to accept and store user input until CTRL-D is pressed to indicate the EOF (end-of-file) condition, also known as EOT (end-of-transmission).

A new copy of the variable $input_string is created and assigned the value of collected user input by calling STDIN at the start of each loop iteration; the my operator is evaluated as a true condition and the loop repeats, until CTRL-D is received and the my operator returns a false condition.

Inside the body of the while loop is 1 line calling the push operator, which appends the current iteration's value of $input_string onto the list of strings contained in $input_strings.

The @{...} (at-sign-curly-braces) is the array dereference operator, which exists because in Perl it is still sometimes necessary to directly access an array by value, instead of the RPerl method of indirectly accessing the array by reference, such as is required by the push operator.

The line starting with my string_arrayref $input_strings_reversed declares another array of string values input_strings_reversed, and then assigns it the strings contained within the first array $input_strings in reversed order, as returned by calling the reverse operator.

As with the push operator, the reverse operator requires its argument to be dereferenced using @{...}; another dereferenced array value is returned by reverse, and an array reference is returned by enclosing reverse and its argument inside the [...] (square brackets) array reference operator.

Finally, the line starting with foreach my string $input_strings_reversed_element denotes the beginning of another loop statement, which iterates the value of $input_strings_reversed_element once for each string value contained in the $input_strings_reversed array; print is called inside the loop body to display the original input strings in reverse order.

#!/usr/bin/perl

# Learning RPerl, Chapter 3, Exercise 1
# Print user-supplied list of strings in reverse order

# [[[ 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(ProhibitExplicitStdin)  # USER DEFAULT 4: allow <STDIN> prompt

# [[[ OPERATIONS ]]]
my string_arrayref $input_strings = [];

print 'Please input zero or more strings, separated by <ENTER>, ended by <CTRL-D>:' . "\n";

while (my string $input_string = <STDIN>) {
    push @{$input_strings}, $input_string;
}

print "\n";
print 'Strings in reverse order:' . "\n";

my string_arrayref $input_strings_reversed = [reverse @{$input_strings}];

foreach my string $input_strings_reversed_element (@{$input_strings_reversed}) {
    print $input_strings_reversed_element;
}

Example execution, input, and output:

$ rperl -t LearningRPerl/Chapter3/exercise_1-stdin_strings_reverse.pl 
Please input zero or more strings, separated by <ENTER>, ended by <CTRL-D>:
Howdy
Doody
Buffalo
Bob
Clarabell
Clown

Strings in reverse order:
Clown
Clarabell
Bob
Buffalo
Doody
Howdy

Chapter 3, Exercise 2

The goal of this exercise is FOO.

#!/usr/bin/perl

# Learning RPerl, Chapter 3, Exercise 2
# Print string array elements indexed by user-supplied integers

# [[[ 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(ProhibitExplicitStdin)  # USER DEFAULT 4: allow <STDIN> prompt

# [[[ OPERATIONS ]]]
my string_arrayref $flintstones_and_rubbles = [qw(fred betty barney dino wilma pebbles bamm-bamm)];
my integer_arrayref $input_indices          = [];

print 'Please input zero or more integers with values ranging from 0 to 6, separated by <ENTER>, ended by <CTRL-D>:' . "\n";

while ( my string $input_string = <STDIN> ) {
    push @{$input_indices}, string_to_integer($input_string);
}

print "\n";
print 'Flintstones & Rubbles:' . "\n";

foreach my integer $input_index ( @{$input_indices} ) {
    print $flintstones_and_rubbles->[ ( $input_index - 1 ) ] . "\n";
}

Example execution, input, and output:

$ rperl -t LearningRPerl/Chapter3/exercise_2-stdin_array_indices.pl 
Please input zero or more integers with values ranging from 0 to 6, separated by <ENTER>, ended by <CTRL-D>:
3
5
2
6
0
4
1
2

Flintstones & Rubbles:
barney
wilma
betty
pebbles
bamm-bamm
dino
fred
betty

Chapter 3, Exercise 3

The goal of this exercise is FOO.

#!/usr/bin/perl FOO

Example execution, input, and output:

$ rperl -t while $foo reverse LearningRPerl/Chapter FOO

Chapter 4, Exercise 1

The goal of this exercise is FOO.

#!/usr/bin/perl FOO

Example execution, input, and output:

$ rperl -t LearningRPerl/Chapter FOO

Chapter 4, Exercise 2

The goal of this exercise is FOO.

#!/usr/bin/perl FOO

Example execution, input, and output:

$ rperl -t LearningRPerl/Chapter FOO

Chapter 4, Exercise 3

The goal of this exercise is FOO.

#!/usr/bin/perl FOO

Example execution, input, and output:

$ rperl -t LearningRPerl/Chapter FOO

Chapter 4, Exercise 4

The goal of this exercise is FOO.

#!/usr/bin/perl FOO

Example execution, input, and output:

$ rperl -t LearningRPerl/Chapter FOO

Chapter 4, Exercise 5

The goal of this exercise is FOO.

#!/usr/bin/perl FOO

Example execution, input, and output:

$ rperl -t LearningRPerl/Chapter FOO

Chapter 5, Exercise 1

The goal of this exercise is FOO.

#!/usr/bin/perl FOO

Example execution, input, and output:

$ rperl -t LearningRPerl/Chapter FOO

Chapter 5, Exercise 2

The goal of this exercise is FOO.

#!/usr/bin/perl FOO

Example execution, input, and output:

$ rperl -t LearningRPerl/Chapter FOO

Chapter 5, Exercise 3

The goal of this exercise is FOO.

#!/usr/bin/perl FOO

Example execution, input, and output:

$ rperl -t LearningRPerl/Chapter FOO

Chapter 6, Exercise 1

The goal of this exercise is FOO.

#!/usr/bin/perl FOO

Example execution, input, and output:

$ rperl -t LearningRPerl/Chapter FOO

Chapter 6, Exercise 2

The goal of this exercise is FOO.

#!/usr/bin/perl FOO

Example execution, input, and output:

$ rperl -t LearningRPerl/Chapter FOO

Chapter 6, Exercise 3

The goal of this exercise is FOO.

#!/usr/bin/perl FOO

Example execution, input, and output:

$ rperl -t LearningRPerl/Chapter FOO

APPENDIX B: BEYOND THE ROADRUNNER

The Scallion The Sword

APPENDIX C: RPERL GRAMMAR

1a. Describe Eyapp EBNF grammar format and Grammar.eyp file sections 1b. Describe lexical token types 1c. Describe operator precedence and associativity 1d. Describe all grammar rules and productions 1e. Provide examples of valid code

SEE ALSO

RPerl

rperl

AUTHOR

William N. Braswell, Jr.

mailto:wbraswell@NOSPAM.cpan.org