Hashes, functions and references

Slides:



Advertisements
Similar presentations
Chapter 25 Perl and CGI (Common Gateway Interface)
Advertisements

Copyright © 2008 Pearson Education, Inc. Publishing as Pearson Addison-Wesley Chapter 14 Introduction to Ruby.
Chapter 2: Using Objects Part 1. To learn about variables To understand the concepts of classes and objects To be able to call methods To learn about.
Names and Bindings.
CS0007: Introduction to Computer Programming Console Output, Variables, Literals, and Introduction to Type.
Kernighan/Ritchie: Kelley/Pohl:
References and Data Structures. References Just as in C, you can create a variable that is a reference (or pointer) to another variable. That is, it contains.
Introduction to C Programming
CS 330 Programming Languages 10 / 14 / 2008 Instructor: Michael Eckmann.
ISBN Regular expressions Mastering Regular Expressions by Jeffrey E. F. Friedl –(on reserve.
COS 381 Day 21. Agenda Questions?? Resources Source Code Available for examples in Text Book in Blackboard
CS 898N – Advanced World Wide Web Technologies Lecture 8: PERL Chin-Chih Chang
CS 330 Programming Languages 10 / 16 / 2008 Instructor: Michael Eckmann.
COS 381 Day 18. Agenda  Assignment 4 Corrected 2 A’s, 3 C’s, 1 D and 1 F nment4/answer.htm
COS 381 Day 19. Agenda  Assignment 5 Posted Due April 7  Exam 3 which was originally scheduled for Apr 4 is going to on April 13 XML & Perl (Chap 8-10)
COS 381 Day 19. Agenda Questions?? Resources Source Code Available for examples in Text Book in Blackboard
1 Chapter 4 Language Fundamentals. 2 Identifiers Program parts such as packages, classes, and class members have names, which are formally known as identifiers.
CS 330 Programming Languages 10 / 11 / 2007 Instructor: Michael Eckmann.
Chapter 4 © 2002 by Addison Wesley Longman, Inc. 1 Chapter 4 Sebesta: Programming the World Wide Web.
 2007 Pearson Education, Inc. All rights reserved Introduction to C Programming.
Introduction to Perl. How to run perl Perl is an interpreted language. This means you run it through an interpreter, not a compiler. Your program/script.
CS 330 Programming Languages 09 / 30 / 2008 Instructor: Michael Eckmann.
More Regular Expressions. List/Scalar Context for m// Last week, we said that m// returns ‘true’ or ‘false’ in scalar context. (really, 1 or 0). In list.
Even More C Programming Pointers. Names and Addresses every variable has a location in memory. This memory location is uniquely determined by a memory.
Introduction to C Programming
Subroutines. aka: user-defined functions, methods, procdures, sub-procedures, etc etc etc We’ll just say Subroutines. –“Functions” generally means built-in.
Scripting Languages Chapter 8 More About Regular Expressions.
1 Chapter 5: Names, Bindings and Scopes Lionel Williams Jr. and Victoria Yan CSci 210, Advanced Software Paradigms September 26, 2010.
1 Variables, Constants, and Data Types Primitive Data Types Variables, Initialization, and Assignment Constants Characters Strings Reading for this class:
Operator Precedence First the contents of all parentheses are evaluated beginning with the innermost set of parenthesis. Second all multiplications, divisions,
Perl Tutorial Presented by Pradeepsunder. Why PERL ???  Practical extraction and report language  Similar to shell script but lot easier and more powerful.
Perl Refernces. Kinds of references: hard: a scalar variable that points to data symbolic: a variable that names another reference typeglob: a kind of.
Functional Programming in Scheme and Lisp. Overview In a functional programming language, functions are first class objects. You can create them, put.
Strings The Basics. Strings can refer to a string variable as one variable or as many different components (characters) string values are delimited by.
Control Structures. Important Semantic Difference In all of these loops we are going to discuss, the braces are ALWAYS REQUIRED. Even if your loop/block.
Functional Programming and Lisp. Overview In a functional programming language, functions are first class objects. In a functional programming language,
Hello.java Program Output 1 public class Hello { 2 public static void main( String [] args ) 3 { 4 System.out.println( “Hello!" ); 5 } // end method main.
Meet Perl, Part 2 Flow of Control and I/O. Perl Statements Lots of different ways to write similar statements –Can make your code look more like natural.
CPS120: Introduction to Computer Science Decision Making in Programs.
Fundamentals of C and C++ Programming. EEL 3801 – Lotzi Bölöni Sub-Topics  Basic Program Structure  Variables - Types and Declarations  Basic Program.
JavaScript Syntax and Semantics. Slide 2 Lecture Overview Core JavaScript Syntax (I will not review every nuance of the language)
Java™ How to Program, 10/e © Copyright by Pearson Education, Inc. All Rights Reserved.
Data TypestMyn1 Data Types The type of a variable is not set by the programmer; rather, it is decided at runtime by PHP depending on the context in which.
When you read a sentence, your mind breaks it into tokens—individual words and punctuation marks that convey meaning. Compilers also perform tokenization.
Prof. Alfred J Bird, Ph.D., NBCT Office – McCormick 3rd floor 607 Office Hours – Tuesday and.
Introducing Python CS 4320, SPRING Lexical Structure Two aspects of Python syntax may be challenging to Java programmers Indenting ◦Indenting is.
Introduction to Perl “Practical Extraction and Report Language” “Pathologically Eclectic Rubbish Lister”
May 2008CLINT-LIN Regular Expressions1 Introduction to Computational Linguistics Regular Expressions (Tutorial derived from NLTK)
Perl Tutorial. Why PERL ??? Practical extraction and report language Similar to shell script but lot easier and more powerful Easy availablity All details.
Perl Chapter 6 Functions. Subprograms In Perl, all subprograms are functions – returns 0 or 1 value – although may have “side-effects” optional function.
Copyright © Curt Hill Regular Expressions Providing a Search Pattern.
Scripting Languages Diana Trandab ă ț Master in Computational Linguistics - 1 st year
Programming Fundamentals. Overview of Previous Lecture Phases of C++ Environment Program statement Vs Preprocessor directive Whitespaces Comments.
Chapter 9 The Basics of Perl. © 2006 Pearson Addison-Wesley. All rights reserved Origins and Uses of Perl - Began in the late 1980s as a more.
 2008 Pearson Education, Inc. All rights reserved. 1 Arrays and Vectors.
Standard Types and Regular Expressions CS 480/680 – Comparative Languages.
1 PERL Functions. 2 Functions Functions also called subroutines are “free flowing”. The returned value from a function can be interpreted in many different.
Basic Scripting & Variables Yasar Hussain Malik - NISTE.
 2007 Pearson Education, Inc. All rights reserved. A Simple C Program 1 /* ************************************************* *** Program: hello_world.
Arrays and Lists. What is an Array? Arrays are linear data structures whose elements are referenced with subscripts. Just about all programming languages.
Gator Engineering Google Code Jam 2015 Copyright © 2008 W. W. Norton & Company. All rights reserved. 1.
1 Chapter 7 Pointers and C-Strings. 2 Objectives  To describe what a pointer is (§7.1).  To learn how to declare a pointer and assign a value to it.
OPERATORS IN C CHAPTER 3. Expressions can be built up from literals, variables and operators. The operators define how the variables and literals in the.
COMP234-Perl Variables, Literals Context, Operators Command Line Input Regex Program template.
9.1 Origins and Uses of Perl
Definition of the Programming Language CPRL
© 2016 Pearson Education, Ltd. All rights reserved.
Miscellaneous Items Loop control, block labels, unless/until, backwards syntax for “if” statements, split, join, substring, length, logical operators,
Overloading functions
Presentation transcript:

Hashes, functions and references

9.6 Hashes - Differ from arrays in two fundamental ways: 1. Arrays use integers as indices, hashes use strings 2. Array elements are ordered, hash elements are not - Hash names begin with percent signs (%) - List literals are used to initialize hashes - Can be comma-separated values, as in %hash1 = ("Monday", 10451, "Tuesday", 10580); - Or, implication symbols can be used between a key and its value, as in %hash2 = ("Monday" => 10451, "Tuesday" => 10580); - The left operand of => need not be quoted - Subscripts are keys (strings) placed in braces $salary = $salaries{"Joe Schmoe"}; $salaries{"Michel Angelo"} = 1000000;

9.6 Hashes (continued) - Elements can be deleted with delete delete $salaries{"Bill Clinton"}; - Use exists to determine whether a key is in a hash if (exists $salaries{"George Bush"}) … - Keys and values can be moved from a hash to an array with keys and values foreach $name (keys %salaries) { print "Salary of $name is: $salaries{$name} \n"; } - Perl has a predefined hash named %ENV, which stores operating system environment variables and their values (see Chapter 10)

A hash A hash is a key-value pair structure It is designated with a % symbol %coins = ( "Quarter" , '25',"Dime" , '10',"Nickel", '05', );

Hash “table” #!c:\perl\bin\perl.exe print "content-type: text/html \n\n"; #The header %coins = ( "Quarter" , '25',"Dime" , '10',"Nickel", '05', ); while (($key, $value) = each(%coins)){ print $key.", ".$value."<br />"; } $coins{Penny} = "01"; $coins{HalfDollar} = "50"; print "<br />"; while (($key, $value) = each(%coins)){

running

Hash example… days of the year C:\PERL\BIN>perl hashex1.pl Feb 28 The month May has 31 days The month Jan has 31 days The month Nov has 30 days The month June has 30 days The month July has 31 days The month Feb has 28 days The month March has 31 days The month Sept has 30 days The month Dec has 31 days The month Oct has 31 days The month April has 30 days The month August has 31 days total days in the year is 365 C:\PERL\BIN>

Assigning hash values You can assign them as in %months=(“Jan”, 31, …); Or %months=(“Jan”=>31,…); As with arrays, when you access an value at a key, it is referenced with a $ because it is (probably) a scalar. (see example code)

Hashex.pl %months=("Jan"=>31,"Feb"=>28,"March"=>31,"April"=>30, "May"=>31, "June"=>30, "July"=>31, "August"=>31, "Sept"=>30, "Oct"=>31, "Nov"=>30, "Dec"=>31); $feb_days=$months{"Feb"}; print "Feb $feb_days\n"; $days=0; foreach $month (keys %months)#won’t be in proper order { print "The month $month has $months{$month} days\n"; $days+=$months{$month}; } print "total days in the year is $days\n";

9.6 Hashes - Differ from arrays in two fundamental ways: 1. Arrays use integers as indices, hashes use strings 2. Array elements are ordered, hash elements are not - Hash names begin with percent signs (%) - List literals are used to initialize hashes - Can be comma-separated values, as in %hash1 = ("Monday", 10451, "Tuesday", 10580); - Or, implication symbols can be used between a key and its value, as in %hash2 = ("Monday" => 10451, "Tuesday" => 10580);

9.6 Hashes (continued) -- The left operand of => need not be quoted - Subscripts are keys (strings) placed in braces $salary = $salaries{"Joe Schmoe"}; $salaries{"Michel Angelo"} = 1000000; Elements can be deleted with delete delete $salaries{"Bill Clinton"}; - Use exists to determine whether a key is in a hash if (exists $salaries{"George Bush"}) …

To store a list as a hash value as if it were a scalar…use [] $wife{"Jacob"} = ["Leah", "Rachel", "Bilhah", "Zilpah"]; OR $wife{"Jacob"}[0] = "Leah"; $wife{"Jacob"}[1] = "Rachel"; $wife{"Jacob"}[2] = "Bilhah"; $wife{"Jacob"}[3] = "Zilpah";

- A reference is a scalar variable that references another variable or a literal - A reference to an existing variable is obtained with the backslash operator $ref_sum = \$sum; - A reference to a list literal is created by placing the literal in brackets $ref_list = [2, 4, 6, 8]; - A reference to a hash literal is created by placing the literal in braces $ref_hash = {Mom => 47, Dad => 48}; - All dereferencing in Perl is explicit - For scalars, add a $ to the beginning - For arrays and hashes, 1. Add a $ to the beginning of the name, or 2. Put the -> operator between the name and its subscript $ref_hash -> {"Mom"} = 48;

9.8 Functions - A function definition is the function header and a block of code that defines its actions - A function header is the reserved word sub and the function’s name - A function declaration is a message to the compiler that the given name is a function that will be defined somewhere in the program - Syntactically, a function declaration is just the function’s header - Function definitions can appear anywhere in a program - Function calls can be embedded in expressions (if they return something useful) or they can be standalone statements (if they don’t) - A function that has been previously declared can be treated as a list operator - A function can specify a return value in two ways: 1. As the operand of a return statement (a function can have zero or more returns) 2. As the value of the last evaluated expression in the function

9.8 Functions (continued) - Implicitly declared variables have global scope - Variables can be forced to be local to a function by naming them in a my declaration, which can include initial values my $sum = 0; my ($total, $pi) = (0, 3.14159265); - Parameters - Actual parameters vs. formal parameters - Pass-by-value is one-way, to the function - Pass-by-reference is two-way - Parameters are passed through the implicit array, @_ (implicitly copied in) - Elements of @_ are aliases for the actual parameters - Every function call has its own version of @_ - In the called function, parameters can be manipulated directly in @_, or in local variables initialized to elements of @_

9.8 Functions (continued) sub fun1 { my($first) = $_[0]; ++$first * ++$_[1]; } - Pass-by-reference parameters can be implemented by passing references sub sub1 { my($ref_len, $ref_list) = @_; my $count; for ($count = 0; $count < $$ref_len; $$ref_list[$count++]--){ - An example call to sub1: sub1(\$len, \@mylist);

9.8 Functions (continued) sub median { my $ref_list = $_[0]; # Compute the length of the passed array my $len = $#$ref_list + 1; # Sort the parameter array @list = sort {$a <=> $b} @$ref_list; # Compute the median if ($len % 2 == 1) { # length is odd return $list[$len / 2]; } else { # length is even return ($list[$len / 2] + $list[$len / 2 - 1]) / 2; } } # End of function median $med = median(\@my_list); print "The median of \@my_list is: $med \n";

9.9 Pattern Matching - The pattern-matching operator is m, but if slashes are used to delimit the pattern operand, the m can be omitted - The default string against which the pattern is matched is in $_ - Character and character-class patterns - Metacharacters: \ | ( ) [ ] { } ^ $ * + ? . - A non-meta, or normal character matches itself if (/gold/) { print "There's gold in that thar string!! \n"; } - Metacharacters can match themselves if they are backslashed - The period matches any character except newline /a.b/ matches "aab", "abb", "acb", ...

9.9 Pattern Matching (continued) - A character class is a string in brackets [abc] means a | b | c - A dash can be used to specify a range of characters [A-Za-z] - If a character class begins with a circumflex, it means the opposite [^A-Z] matches any character except an uppercase letter - Predefined character classes: Name Equivalent Pattern Matches \d [0-9] a digit \D [^0-9] not a digit \w [A-Za-z_0-9] a word character \W [^A-Za-z_0-9] not a word character \s [ \r\t\n\f] a whitespace character \S [^ \r\t\n\f] not a whitespace character

9.9 Pattern Matching (continued) - Pattern Quantifiers - pattern{n} means repeat the pattern n times /a{5}bc{5}/ - pattern* means repeat the pattern zero or more times /a*bc*/ - pattern+ means repeat the pattern 1 or more - pattern? means zero or one match /\d*b?c+/ - Two more useful predefined patterns: \b - matches the boundary position between a \w character and a \W character, in either order \B - matches a non-word boundary - These two do not match characters, they match positions between characters

9.9 Pattern Matching (continued) - Binding Operators - to match against a string other than the string in $_ $str =~ /\w/; $str !~ /\w/; - Anchors - match positions, not characters 1. ^ in front of a pattern (not in a character class) means the pattern must match at the beginning 2. $ at the end of a pattern means the pattern must match at the end - Pattern modifiers (after the pattern) 1. i makes letters in the pattern match either uppercase or lowercase 2. x allows whitespace in the pattern, including comments

9.9 Pattern Matching (continued) - Remembering matches - After the match, the implicit variables $1, $2, … have the parts of the string that matched the first, second, … parenthesized subpattern "John Fitzgerald Kennedy" =~ /(\w+) (\w+) (\w+)/; Now, $1 has "John", $2 has "Fitzgerald", and $3 has "Kennedy" - Inside the pattern, \1, \2, … can be used $` has the part of the string before the part that matched $& has the part of the string that matched $’ has the part of the string after the part that - Substitutions - Used to find and replace a substring s/Pattern/New_String/ $_ = "Darcy is her name, yes, it’s Darcy" s/Darcy/Darcie/;

9.9 Pattern Matching (continued) - Substitutions (continued) - Modifiers - The g modifier means find and replace all of them in the string - The e modifier means the New_String must be interpreted as Perl code - Example: Find a single hex character and replace it with its decimal value s/%([\dA-Fa-f])/pack("C", hex($1))/e; - The i modifier does what it does for pattern matching -

Transliterate Operator - Translates a character or character class into another character or character class tr/a-z/A-Z/; - Transliterates all lowercase letters to upper

references In Perl, the most common form of indirection is the reference. This is handled in C with -> operator. A referent doesn't really have a name of its own, apart from the references to it. To put it another way, every Perl variable name lives in some kind of symbol table, holding one hard reference to its underlying (otherwise nameless) referent. That referent might be simple, like a number or string, or complex, like an array or hash. Either way, there's still exactly one reference from the variable to its value.

references - A reference is a scalar variable that references another variable or a literal - A reference to an existing variable is obtained with the backslash operator $ref_sum = \$sum; - A reference to a list literal is created by placing the literal in brackets $ref_list = [2, 4, 6, 8];

- A reference to a hash literal is created by placing the literal in braces $ref_hash = {Mom => 47, Dad => 48}; - All dereferencing in Perl is explicit - For scalars, add a $ to the beginning - For arrays and hashes, 1. Add a $ to the beginning of the name, or 2. Put the -> operator between the name and its subscript $ref_hash -> {"Mom"} = 48;

The Backslash Operator $scalarref = \$foo; $constref = \186_282.42; $arrayref = \@ARGV; $hashref = \%ENV; $coderef = \&handler; $globref = \*STDOUT; The backslash operator will generate a whole list of references if applied to a list. Anonymous referents like #2 above are accessed only through references. This one happens to be a number, but you can create anonymous arrays, hashes, and subroutines as well.

a reference to an anonymous array You can create a reference to an anonymous array with square brackets: $arrayref = [1, 2, ['a', 'b', 'c', 'd']]; Here we've composed an anonymous array of three elements, whose final element is a reference to an anonymous array of four elements

a reference to an anonymous hash You can create a reference to an anonymous hash with braces: $hashref = { 'Adam' => 'Eve', 'Clyde' => $bonnie, 'Antony' => 'Cleo' . 'patra', };

a hash of arrays. $table = { "john" => [ 47, "brown", 186 ], "mary" => [ 23, "hazel", 128 ], "bill" => [ 35, "blue", 157 ], };

hash of hashes for the same table: { "john" => { age => 47, eyes => "brown", weight => 186, }, "mary" => { age => 23, eyes => "hazel", weight => 128, }, "bill" => { age => 35, eyes => "blue", weight => 157, }, }; As with square brackets, braces work like this only where the Perl parser is expecting a term in an expression. They should not be confused with the braces in an expression like $hash{key}

Disambiguating {} Since braces are also used for several other things (including blocks), you may occasionally have to disambiguate braces at the beginning of a statement by putting a + or a return in front, so that Perl realizes the opening brace isn't starting a block. For example, if you want a function to make a new hash and return a reference to it, you have these options: sub hashem { { @_ } } # WRONG -- returns @_. sub hashem { +{ @_ } } # Ok. sub hashem { return { @_ } } # Ok.

anonymous subroutine composer You can create a reference to an anonymous subroutine by using sub without a subroutine name: $coderef = sub { print “Huhn???!\n" }; # Now &$coderef prints “Huhn???!"

Constructors can be called in any of these ways: $objref = Doggie::->new(Tail => 'short', Ears => 'long'); #1 $objref = new Doggie:: Tail => 'short', Ears => 'long'; #2 $objref = Doggie->new(Tail => 'short', Ears => 'long'); #3 $objref = new Doggie Tail => 'short', Ears => 'long'; #4

Dereferencing simple scalars you can put an extra funny character on the front of any simple scalar variable to dereference it: $foo = "three humps"; $scalarref = \$foo; # $scalarref is now a reference to $foo $camel_model = $$scalarref; # $camel_model is now "three humps" Here are some other dereferences: $bar = $$scalarref; push(@$arrayref, $filename); $$arrayref[0] = "January"; # Set the first element of @$arrayref @$arrayref[4..6] = qw/May June July/; # Set several elements of @$arrayref %$hashref = (KEY => "RING", BIRD => "SING"); # Initialize whole hash $$hashref{KEY} = "VALUE"; # Set one key/value pair @$hashref{"KEY1","KEY2"} = ("VAL1","VAL2"); # Set two more pairs &$coderef(1,2,3); print $handleref "output\n";

more an expression like $$arrayref[0] is equivalent to ${$arrayref}[0] and means the first element of the array referred to by $arrayref. That is not at all the same as ${$arrayref[0]}, which is dereferencing the first element of the array named @arrayref. Likewise, $$hashref{KEY} is the same as ${$hashref}{KEY}, and has nothing to do with ${$hashref{KEY}}, which would be dereferencing an entry in the hash named %hashref. The following prints "howdy": $refrefref = \\\"howdy"; print $$$$refrefref;

Disambiguation using { } the earlier examples could all be disambiguated like this: $bar = ${$scalarref}; push(@{$arrayref}, $filename); ${$arrayref}[0] = "January"; @{$arrayref}[4..6] = qw/May June July/; ${$hashref}{"KEY"} = "VALUE"; @{$hashref}{"KEY1","KEY2"} = ("VAL1","VAL2"); &{$coderef}(1,2,3); not to mention: $refrefref = \\\"howdy"; print ${${${$refrefref}}};

More { } Suppose $dispatch{$index} contains a reference to a subroutine (sometimes called a "coderef"). This example invokes the subroutine with three arguments. &{ $dispatch{$index} }(1, 2, 3); Here, the BLOCK is necessary. Without that outer pair of braces, Perl would have treated $dispatch as the coderef instead of $dispatch{$index}.

a third method of dereferencing:use the -> infix operator Each of these trios is equivalent, corresponding to the three notations we've introduced. $ $arrayref [2] = "Dorian"; #1 ${ $arrayref }[2] = "Dorian"; #2 $arrayref->[2] = "Dorian"; #3 $ $hashref {KEY} = "F#major"; #1 ${ $hashref }{KEY} = "F#major"; #2 $hashref->{KEY} = "F#major"; #3 & $coderef (Presto => 192); #1 &{ $coderef }(Presto => 192); #2 $coderef->(Presto => 192); #3

As long as you stick with scalar values, though, you can use any expression to the left of the ->, including another dereference, because multiple arrow operators associate left to right: print $array[3]->{"English"}->[0]; fourth element of @array is intended to be a hash reference, and the value of the "English" entry in that hash is intended to be an array reference

lvalues and rvalues Suppose now that $array[3] is undefined. The following statement is still legal: $array[3]->{"English"}->[0] = "January"; This is one of those cases mentioned earlier in which references spring into existence (or "autovivify") when used as an lvalue (that is, when a value is being assigned to it). If $array[3] was undefined, it's automatically defined as a hash reference so that we can set a value for $array[3]->{"English"} in it. Once that's done, $array[3]->{"English"} is automatically defined as an array reference so that we can assign something to the first element in that array. Note that rvalues are a little different: print $array[3]->{"English"}->[0] only defines $array[3] and $array[3]->{"English"}, not $array[3]->{"English"}->[0], since the final element is not an lvalue.

Use of -> The arrow is optional between brackets or braces, or between a closing bracket or brace and a parenthesis for an indirect function call. So you can shrink the previous code down to: $dispatch{$index}(1, 2, 3); $array[3]{"English"}[0] = "January"; In the case of ordinary arrays, this gives you multidimensional arrays that are just like C's array: $answer[$x][$y][$z] += 42;

precedence In Perl, the following two statements do the same thing: $listref->[2][2] = "hello"; # Pretty clear $$listref[2][2] = "hello"; # A bit confusing This second of these statements may disconcert the C programmer, who is accustomed to using *a[i] to mean "what's pointed to by the ith element of a". But in Perl, the five characters ($ @ * % &) effectively bind more tightly than braces or brackets. Therefore, it is $$listref and not $listref[2] that is taken to be a reference to an array. If you want the C behavior, either you have to write ${$listref[2]} to force the $listref[2] to get evaluated before the leading $ dereferencer, or you have to use the -> notation: $listref[2]->[$greeting] = "hello";

An example Doing some counting, averaging and sorting with data Perl program from text (wages.pl) is in the slide notes # Wages.pl - An example program to illustrate some of the # features of Perl # Input: A file of lines of employee data, where each line has # name:age:department code:salary # Output: 1. The names of all employees whose names end with "son" # 2. Percentage of employees under 40 years old # 3. Average salary of employees under 40 years old # 4. An alphabetical list of employees who are under 40 # years old and who have salaries more than $40,000 # Open the data file and display a header for employees # whose names end in 'son' open(EMPLOYEES, "employees") || die "CanÕt open employees $!"; print "Names that end in 'son'\n\n"; # Loop to read and process the employee data while (<EMPLOYEES>) { # Increment the number of employees and chop off the newline $total_employees++; chomp; # Split the input line into its four parts ($name, $age, $dept, $salary) = split(/:/); # If the name ends in 'son', print the name if ($name =~ /son$/) { print "$name \n"; } # If the employee is under 40, count him or her and add his or her # salary to the sum of such salaries if ($age < 40) { $under_40++; $salary_sum += $salary; # If the salary was over 40,000, add the person and his or her # salary to the hash of such people if ($salary > 40000) { $sublist{$name} = $salary; # If there was at least one employee, continue if ($total_employees > 0) { # Process and display the results for those under 40 if ($under_40 > 0) { # Compute and display the % of employees under 40 and their # average salaries $percent = 100 * $under_40 / $total_employees; print "\nPercent of employees under 40 is: $percent \n"; $avg = $salary_sum / $under_40; print "Average salary of employees under 40 is: $avg \n"; # Sort and display the names of the employees under 40 print "Sorted list of employees under 40", " with salaries > \$40,000 \n"; @sorted_names = sort (keys(%sublist)); print "\nName \t\t Salary\n"; foreach $name (@sorted_names) { print "$name \t \$$sublist{$name} \n"; else { print "There are no employees under 40 \n"; print "There were no employees\n";

Datafile, colon delimited records Johanson:44:1234:40000 Williams:32:0011:65000 Smith:25:1010:62333 Abrahams:31:999:90000 Williamson:41:3322:34567 Cain:23:1111:15000 Abel:24:2222:45000 Zebra:19:3456:70000

Output from wages.pl c:\perl\bin>perl wages.pl employees.txt Names that end in 'son' Johanson Williamson Percent of employees under 40 is: 75 Average salary of employees under 40 is: 57888.8333333333 Sorted list of employees under 40 with salaries > $40,000 Name Salary Abel $45000 Abrahams $90000 Smith $62333 Williams $65000 Zebra $70000 c:\perl\bin>

Closures You can create anonymous subroutines with a nameless sub {}. You can think of those subroutines as defined at run time, which means that they have a time of generation as well as a location of definition. Some variables might be in scope when the subroutine is created, and different variables might be in scope when the subroutine is called. Forgetting about subroutines for a moment, consider a reference that refers to a lexical variable: { my $critter = "camel"; $critterref = \$critter; } The value of $$critterref will remain "camel" even though $critter disappears after the closing curly brace. But $critterref could just as well have referred to a subroutine that refers to $critter: { my $critter = "camel"; $critterref = sub { return $critter }; } This is a closure, which is a notion out of the functional programming world of LISP and Scheme. It means that when you define an anonymous function in a particular lexical scope at a particular moment, it pretends to run in that scope even when later called from outside that scope.

Closures and callbacks You can also think of closures as a way to write a subroutine template without using eval. The lexical variables act as parameters for filling in the template, which is useful for setting up little bits of code to run later. These are commonly called callbacks in event-based programming, where you associate a bit of code with a keypress, mouse click, window exposure, and so on. When used as callbacks, closures do exactly what you expect, even if you don't know the first thing about functional programming. (Note that this closure business only applies to my variables. Global variables work as they've always worked, since they're neither created nor destroyed the way lexical variables are.)

Functions (and ptrs to functions) sub make_saying { my $salute = shift; my $newfunc = sub { my $target = shift; print "$salute, $target!\n"; }; return $newfunc; # Return a closure } $f = make_saying("Howdy"); # Create a closure $g = make_saying("Greetings"); # Create another closure # Time passes... $f->("world"); $g->("earthlings");

c:\perl\bin>perl salutations.pl Howdy, world! Greetings, earthlings! c:\perl\bin>