####################################################### # # display-notes related to Intro to Perl, Class 2 # ####################################################### # last modified: 4-11-03 (post-class) #------------------------------------------------------------- INTERESTING TIDBIT #1 - back-quotes * you can assign the results of an operating system command to a variable by placing that command within back-quotes (` `) # class2_01_backquotes $datetime = `date`; print "Current date and time is: $datetime \n"; #------------------------------------------------------------- INTERESTING TIDBIT #2 - undef * remember that this is just another scalar value in Perl --- what a variable contains before it is filled, what many operators return when faced with "bad" arguments, etc. * not an automatic error to refer to, either! * in a number context -- it is treated like zero! * in a string context? treated like an empty string! * and so, for example, often (not *always*...) works fine in an accumulating context; # class2_02_undef $ct = 1; while ($ct <= 10) { $sum += $ct; # no error --- initially undef, but treated as zero $prod *= $ct; # OK, not so good --- initially undef, and treated # as 0, but that means it stays 0 (multiplying by 0 # and all...!) $ct++; } print("\$ct is: $ct\n"); print("\$sum is: $sum\n"); print("\$prod is: $prod\n"); #------------------------------------------------------------- INTERESTING TIDBIT #3 - defined() * you can use the function defined() to tell if something has that special undef value... * returns false for undef, true for everything else! # class2_03_defined $val1 = ""; # $val1 contains the empty string if (defined($val1)) { print "See? filling a \$val1 with the empty string IS defining it!\n"; } else { print "HUH? #1\n"; } # note that $val2 has NOT been defined yet... if (defined($val2)) { print "HUH?? #2\n"; } else { print "See? \$val2 is indeed undef\n"; } #------------------------------------------------------------- REALLY ON TO TODAY'S TOPIC - LISTS and ARRAYS * scalar variable -> has a SINGLE value * lists and arrays are MULTIPLE values... * BUT! there's a SLIGHT semantic difference in Perl: * (p. 40, "Learning Perl") * LIST: "an ordered collection of scalars" * ARRAY: "a variable that contains a list" * "the list is the data, and the array is the variable" * indexed like you expect: starts at 0, goes on from there * in Perl, the list within an array does NOT have to contain elements all of the same type --- but it often does; * no maximum size defined! #------------------------------------------------------------ WHOLE-ARRAY vs. ARRAY-ELEMENT NOTATION * if you want to refer to the entire array --- precede array name with @ * when you refer to a single scalar element within the array --- * use the usual [index] notation, BUT also, * precede the array name with $ (because the *result* of the expression is a scalar, get it? * (footnote claim: $ for scalar, @ for array...?) @my_array # refers to the entire array $my_array[3] # refers to the scalar element at index 3 of @my_array #------------------------------------------------------------- ACCESSING ELEMENTS OF AN ARRAY * do you think an array has to be declared first? This is Perl we are talking about! # class2_04_array1 # @myArray will have 7 elements after this, those with indices 0-5 # undefined: $myArray[6] = 27; $ct = 0; while ($ct < 7) { print "\$myArray[$ct]: "; if (defined($myArray[$ct])) { print "$myArray[$ct]\n"; } else { print "undef\n"; } $ct++; } * Perl will automatically extend the array's size, too, if you set an array element at some index "past" the current end; # now @myArray will have 14 items $myArray[13] = George; while ($ct < 14) { print "\$myArray[$ct]: "; if (defined($myArray[$ct])) { print "$myArray[$ct]\n"; } else { print "undef\n"; } $ct++; } #---------------------------------------------------------------- SPECIAL ARRAY INDICES * $#arrayName # index of last element in @arrayName! * class2_05_array2 rewrites class2_04_array1 taking advantage of this... * $arrayName[-1] # another way to just access the LAST array element * $arrayName[-2] # ... second to last array element * etc. * (WON'T like it if you use a negative index "bigger" than the array, though...) * class2_05_array2 demos above, too. #---------------------------------------------------------------- LIST LITERALS * simplest form: (p. 43, "Learning Perl"): "a list of comma-separated values enclosed in parentheses" (1, 2, 3) () # empty list * RANGE OPERATOR: .. * creates a list of the values from the scalar on the left up to the scalar on the right! (1..100) # the values 1, 2, 3, all the way to 100 (3, $a..$b, 16) # the values 3, current value of $a through current # value of $b, 16 * truncates to integer, only counts "up"! * and, a list can be made the value of an array... @myArray = (1..100); # using @ since referring to array as a whole * see class2_06_list1 #--------------------------------------------------------------------- THE qw SHORTCUT * a list can, of course, also contain strings: ("cis130", "cis230", "cis250", "cis260") * qw (quoted words, quoted by whitespace) lets you save some quote-typing; the below is equivalent to the previous list: qw/ cis130 cis230 cis250 cis260 / (but ANY punctuation mark can be used to delimit this --- not just / /!) qw! cis130 cis230 cis250 cis260 ! qw( cis130 cis230 cis250 cis260 ) etc.! * see class2_07_qw #-------------------------------------------------------------- MORE on list assignment * in addition to assigning an array to contain a list --- you can also assign values to a list of variable on the left hand side from a list of values on the right hand side...! ($a, $b, $c) = (1..3); * too many values on right? excess are ignored... * too few values on right? "leftover" variables get undef * you can even SWAP two variables' values this way, in Perl...! ($a, $b) = ($b, $a); * see class2_08_list2 #------------------------------------------------------------------- PUSH and POP, SHIFT and UNSHIFT * ...because "real Perl programmers don't use indices" (p. 46, "Learning Perl") * an array can be used as a stack, no additional set-up necessary... * pop - given an array, removes and returns the LAST element of the array * push - given an array and a value, adds that value to the END of the array * what --- you want to add, remove from BEGINNING of array?! * shift - given an array, removes and returns FIRST element * unshift - given an array and a value, adds that value to the BEGINNING of an array * pop, shift don't cause errors if array empty --- they just return undef... * see class2_09_pop_etc #---------------------------------------------------------------- INTERPOLATING ARRAYS INTO STRINGS * yep, can interpolate arrays in double-quoted strings, too --- elements are separated by spaces for you... * (that is: you can just put @array_name into a double-quoted string, and the effect is as if the list-turned-into-a-string-with spaces-between-the-elements had been typed there instead) * (there's a space between each pair of elements --- NOT a space at the beginning and end, though...) print "the values are: @my_values\n"; * see class2_09_pop_etc #--------------------------------------------------------------- FOREACH * know what? I think Perl programmers almost never REALLY say: while ($ct <= $#myArr) * why? Because that's such a common thing to do --- handle everything in an array variable or a list literal --- that of course Perl has a shortcut... foreach $var ( @array_or_list ) { # do action, with $var set to each element in # @array_or_list in turn } foreach $val ( @myArr ) { print "$val\n"; } foreach $val ( qw/ George Harold Jerome /) { print "$val\n"; } foreach $file ( `ls` ) { print "$file"; # guess what? ls results HAVE newlines already... } * see class2_10_foreach1 #--------------------------------------------------------------- PERL's FAVORITE DEFAULT: $_ * but that's not all, with regard to foreach... * ...you can leave out the control variable, too! * (you can just say: foreach ( @array_or_list ) { } * but --- how do you then "grab" the "current" list element? * Perl has a number of DEFAULT VARIABLES, set on your behalf --- and one of the most-used is $_ * $_ is automatically set to the "current" list element; foreach ( @array_or_list ) { # do something to $_ # ($_ contains the current element of @array_or_list) } * NOTE: $_ is not ONLY set in foreach loops --- it is also used in MANY other places when you do not TELL it to use some other variable... * see class2_11_foreach2 #------------------------------------------------------------------ REVERSE, SORT * reverse * returns a copy of the list/array passed to it with the elements in the opposite order * sort * returns a copy of the list/array passed to it with the elements ordered in ASCII order @backwards1 = reverse @myArr; @sorted1 = sort @myArr; @backwards2 = reverse qw/ Apple apple Berry berry /; @sorted2 = sort qw/ Apple apple Berry berry /; * see class2_12_reverse_sort #--------------------------------------------------------------------- REMEMBER - IMPORTANCE of CONTEXT! * in Perl (as in spoken languages!) the CONTEXT of an expression is important; * we've seen already with numbers and strings --- * it's true for scalars and lists, too. @values = (3..8); # the values 3 through 8 @myArr = @values; # also has the values 3 through 8 $myScalar = @values; # gets the NUMBER OF ELEMENTS in $values! @words = qw/ hello goodbye toodles /; @backwards = reverse @words; # the values toodles, goodbye, hello $backwards = reverse @words; # the reversed STRING "seldooteybdoogolleh" @myArr2 = 6 * 7; # gets the 1-element list (42) @myArr3 = undef; # OOPS! the 1-element array (undef) @myArr4 = (); # the PROPER way to initialize an EMPTY array # to "force" scalar context: print "There are ", scalar @myArr, " elements in \@myArr\n"; @lines = ; # reads MULTIPLE lines, until end-of-file # encountered, control-D typed, etc.; * see class2_13_context