#!/usr/bin/perl
#########################################################################
#
# An executive summary of Perl for folks with some programming experience.
#
# This doesn't try to be the whole story, 
# but it's enough to get you going.
#
# ------------------------------------
#
# Also note that I've put a link to a book that may be worth getting,
#  "Web, Graphics, and Perl/Tk : Best of the Perl Journal, vol 2"
# 
# Other reasonable choices are "Learning Perl/Tk", 
# "Mastering Perl/Tk", or any of a variety of books on Perl.
# 
# I have samples of some of these in my office.
#
# ------------------------------------------
#
# For those starting out with Perl, 
# the choices for Windows installation is either
#
#  Cygwin www.cygwin.com 
#  (which gives you a unix environment within Windows, including X11), or 
# 
#  ActiveState.com 
# which supports commercial and free versions of perl on Windows  
# (ActivePerl is the free one.  There are also fancier GUI tools for 
# perl development, though I typically use a good editor.)
# 
#
#########################################################################

#     The specifics of several of these recipes apply to 
#     a unix system, like the linux on cs.marlboro.edu.
#     But things aren't that different on a Microsoft box
#     (see activestate.com's website for perl on Windows, 
#     or cygwin.com for a unix-like system within Windows.)
#     or an Apple box (under OS X is a unix anyway).

# --- Running a perl program ----
# 
# Typically the perl compiler is installed in /usr/bin/perl
# (on unix systems, anyway), and a perl text source file will
# have a .pl or .pm (perl module) extension, or no extension at all.
#
# If the file is "hello.pl", then typically typing "perl hello.pl"
# will compile and run it.
#  (Caveat: Assuming /usr/bin is in your PATH.
#   The environment variable that says where to look for commands.
#   In a typical unix shell like bash, your .bashrc or .bash_profile 
#   file in your home directory sets your PATH variable.)
#
# Or, the file itself may be marked executable ("chmod +x hello.pl")
# and then invoked from the command line ("./hello.pl") as long as
# the veryfirst line of the file looks like the one in the file, namely
# "#!/usr/bin/perl" which tells the OS how to execute the file.

#
# --- Comments ------------------
#
# Comments run from a "#" character to the end of a line.
# (But you'd already figured that out, eh?)

# --- Warnings ------------------
use strict;
use warnings;

# The "use" keyword imports functionality into
# a Perl program, either from Perl itself or 
# from other files / modules / packages.
#
# These two should almost always start any Perl program;
# they tell the compiler that all variables should be declared,
# and to print out warnings if it looks like something funny
# is going on.

# --- Variables -----------------
#
# Most variables start with a funny character that designates
# what kind of thing they are.  This is one of Perl's quirks.
# Perl also has many special variables with various bizarre
# names and properties, things like $_ and $\ .
#
# Scalars

my $foo      = 12.3;                                 # a number
my $name     = "Jim Mahoney";                        # a string
my $function = sub { print("Hi there.\n"); };        # a subroutine reference

# A scalar is a variable that has one "thing" in it, 
# whatever that may be.  Perl converts between
# integer, floating point, and strings as it needs to,
# so we don't declare memory storage types as we do in C or Java.
#
# All scalar variable names are prefixed with "$"
# which is supposed to remind you of "S" for Scalar.
#
# The "my" declares these variables to exist.
# Without it (or something like it) you'll get an error
# if you're running under "use strict".  
# The scope of the variable (where it exists and the name is visible)
# is through the enclosing conditional or subroutine block's { } 
# or the end of the file.

# --- Built-in functions --------
#
# Perl has hundreds of built-in functions like print, sin,
# map, push, pop, open, ...   See the documentation at 
# for example perldoc.com (the perlfunc pages in the manual).
#
# Typical statements end in a semi-colon.

print("This is ");            # The \n within " " signifies the newline char
print("printing.\n");         # for the operating system Perl's running on.

print "So is this\n";         # Unlike most languages, the ( ) are optional.

print "
 And even
 this.
 ";                           # Even this works.

# --- Arrays ----------------------
#
# Perl has a built-in array type.  The slots in an array 
# may be filled with any data type, and the array grows as needed.

my @stuff = ( "wagon", 3, sin(2.3), 16.2, $foo );

# All array names are prefixed with "@"
# which is supposed to remind you of "a" for Array.

$stuff[1] = 4;             # Change the 3 to a 4.

# To access one part of an array, we use the [] to mark subscript indeces.
# But since one part is a scalar, the syntax expects $ rather than @.
# (Surprise!)  This confuses nearly all beginners.
# Expectations are that Perl6 will reverse this convention,
# confusing all the rest of us who've been brainwashed already.
#
# The leftmost (first) array element has index 0.
#
print " stuff[0] is ", $stuff[0], "\n";

# --- Conditionals ------------------

# The basic "if" looks just like C.

if ( 3 < 5 ) {
  print("Yup, 3 is less than 5.\n");
}

# The { } are required, however, unlike C.

if ( "George" lt "Fred" ) {
  print(" 'George' comes before 'Fred'.\n");
}
else {
  print(" 'Fred' does not come before 'George'.\n");
}

# "else if" is spellled "elsif" in Perl.  Go figure.

# Booleans are just scalars.
# 0, "", and an empty array in scalar context are false.
# Everything else is true.
# 
# The binary comparison operators are things like
#
#   ==   numerical equality
#   <    numerical less-than
#
#   eq   string equality
#   lt   string (alphabetic) less-than
#
# There are many boolean operators, including "and", "&&", "or", "||".
# The only difference between "and" and "&&" is how tightly it grabs
# the stuff around it; use parens and it won't matter.

my $running = 1;                            # typical value used for "true".
my $count   = 101;
my $done = ($running and ( $count < 10));   # boolean operator example.
if ($done) {
  print "Hey - looks like we're done.\n";
}

# -- Loops --------------------------------
#
# You can use C's looping explicit loop
for (my $i=0; i<3; $i++){
  print " i is $i \n";              # Note that $i expands to value in " ".
}

# Or the typical while construct
my $j = 0;
while ($j<3){
  print " j is $j \n";
  $j++;                            # add one to $j.
}

# But more typically Perl folks loop over arrays.
my @numbers = (0,1,2,3);
for my $number (@numbers){
  print " n is $number. \n";
}

# This may not seem much simpler, but there are
# a few nice parts of this syntax.  First, Perl
# lets you create monotomic arrays with a 1..n notation,
# so this loop could be

for my $n (0..3){
  print " n is $number. \n";
}

# which is kind-of fun (though the 0,1,2,3 are created and stored
# before the loop is run - problematic for big loops).
#
# But often you don't care about the array index or how
# many there are - you just want to hit each piece.

my @folks;
push @folks, "Cathy";              # Stick "Cathy" on the end of the array.
push @folks, "Jim";
push @folks, "Fred";
for my $person (@folks){
  print " name is $person \n";
}

# --- Subroutines --------------------------

# The syntax for defining subroutines is another Perl quirk.
# Arguments are not declared explicitly; instead, all passed variables
# are put into a magic array named @_.  The convention is then
# to copy what you want out of that array to local variables.
# (Or you can change the orginals directly if need be. )
#
# So nearly all your subroutines will look something like this.

# Takes two arguments as inputs.
# Returns double the smallest,
# and as a side effect prints what's going on if debuggin is on.
sub this_and_that {
  my ($first, $second) = @_;                 # declare inputs
  my $DEBUG = 1;
  print " tat: (first, second) = ($first, $second)\n"      if $DEBUG;
  my $smallest;
  if ($first < $second){
    $smallest = $first;
    print " tat: first smaller"                            if $DEBUG;
  }
  else {
    $smallest = $second;
    print " tat: second smaller"                           if $DEBUG:
  }
  return 2*$smallest;
}

# Invoking the subroutine looks like it usually does :

my $answer = this_and_that(10.2, 12);
print " answer is $answer \n";

# I'll note in passing that Perl allows you to put "if", "for"
# and a few constructs like that at the end of a statement, 
# as I did above with the debug print statements.

# --- Fat Arrow and Hashes -------------------------------------

# Perl allows you to use the two symbols "=>" rather than
# a comma.  It also has the side effect of effectivly quoting
# the thing on the left.  Thus

my @foo = ( "color", "red" );

# is essentially the same as 

my @bar = ( color => "red" );

# This syntax is commonly used to give key,value pairs in a list.

# Perl has another data structure called a hash
# which is like an array, but with strings
# as indeces rather than numbers.  These hashes are big collections
# of key,value pairs.  They start with "%".

my %scores = (
	      Mary => 98,
	      Joe  => 95,
	      Fred => 82,
	     );

# Note that the carriage returns I used to line that
# previous stuff up have nothing to do with the syntax.
# The stuff inside the () is just a list, which is converted
# to a hash by pulling off values one at a time.
# In other words (key1, value1, key2, value2, key3, value3).
#
# To access a hash, we subscript it with {}.

$scores{Alfred} = 23;
print "Joe's score is ", $scores{Joe}, "\n";

# To loop over the elements of a hash, there's a special
# keys() function that pulls out the Mary,Joe,Fred,Alfred 
# stuff as a list.

for my $name (keys %scores){
  print " " , $name, "'s score is ", $scores{$name}, "\n";
}

# --- Thin arrow and Objects ---------------------------------

# While I'm not going to discuss defining objects here,
# using nearly any perl module from the CPAN (like Perl/Tk) 
# will involve creating and invoking objects.
#
# See http://cs.marlboro.edu/docs/Tk/ for some Perl/Tk documentation.

use Tk;                # import subroutines and definitions for Perl/Tk
my $window = MainWindow->new;

# This syntax is similar to that in C++ in that the 
# thin arrow -> "derereferences" something. So once we 
# have an object $obj , a method invocation is $obj->method($arg);
#
# Here "MainWindow" is like a Java Class or a C++ structure.
# In java this would translate as "MainWindow window = MainWindow.new"
# or "MainWindow window = new MainWindow()".
#
# Perl actually allows several syntax constructions to accomplish this
# same effect.  In this case, new() is a subroutine in package (or class)
# MainWindow which returns an object, which is a scalar.  
# We could have also said

my $window = new MainWindow;

# or

my $window = MainWindow->new();

# Once we have one of these objects, invoking methods on it 
# looks like this.

my $label = $window->Label( -text => 'Quit' );

# Don't let the "-text" and fat-arrow confuse you; 
# this is just sending two arguments, namely "-text" and "Quit" 
# to a subroutine called "Label" which is a method of the object $window
# which belongs to package MainWindow.
#
# This method modifies the $window object by creating another Label 
# object within it, and giving the property "text" the value "Quit" 
# within that Label.  It also returns the object, acting like another
# "new" method for creating an object.

$label->pack();

# That last call tells the label to arrange itself appropriately
# within the enclosing window 
#
# Those last two commands could be nested into one call,

$window->Label( -text => "another label")->pack;

# You should read this from left to right.
# Essentially its  [ $window->Label() ] -> pack
# which is         [ $label           ] -> pack
# without giving a name to the $label after creating it.

# That's about all you need know to start using Perl/Tk.

# Different perl module authors adapt different conventions for
# what the arguments to their functions should look like, or
# how the module should be used.  Here the "-" in front of "text"
# is just such a convention; it isn't part of Perl or even typical.
#
# The stacked invocations are likewise more of a convention of
# this module than how all such object programming is done.



