| Profil de yeapyeap's spaceBlogLivre d'orRéseau | Aide |
|
|
29 juin Different between casex and casez from http://www.asic-world.com/verilog/vbehave2.html
The if - else statement controls the execution of other statements. In programming language like c, if - else controls the flow of program. When more than one statement needs to be executed for an if condition, then we need to use begin and end as seen in earlier examples.
Syntax : if if (condition) statements;
Syntax : if-else if (condition) statements; else statements;
Syntax : nested if-else-if if (condition) statements; else if (condition) statements; ................ ................ else statements;
1 module simple_if(); 2 3 reg latch; 4 wire enable,din; 5 6 always @ (enable or din) 7 if (enable) begin 8 latch <= din; 9 end 10 11 endmoduleYou could download file simple_if.v here
1 module if_else(); 2 3 reg dff; 4 wire clk,din,reset; 5 6 always @ (posedge clk) 7 if (reset) begin 8 dff <= 0; 9 end else begin 10 dff <= din; 11 end 12 13 endmoduleYou could download file if_else.v here
1 module nested_if();
2
3 reg [3:0] counter;
4 reg clk,reset,enable, up_en, down_en;
5
6 always @ (posedge clk)
7 // If reset is asserted
8 if (reset == 1'b0) begin
9 counter <= 4'b0000;
10 // If counter is enable and up count is asserted
11 end else if (enable == 1'b1 && up_en == 1'b1) begin
12 counter <= counter + 1'b1;
13 // If counter is enable and down count is asserted
14 end else if (enable == 1'b1 && down_en == 1'b1) begin
15 counter <= counter - 1'b1;
16 // If counting is disabled
17 end else begin
18 counter <= counter; // Redundant code
19 end
20
21 // Testbench code
22 initial begin
23 $monitor ("@‰0dns reset=‰b enable=‰b up=‰b down=‰b count=‰b",
24 $time, reset, enable, up_en, down_en,counter);
25 $display("@‰0dns Driving all inputs to know state",$time);
26 clk = 0;
27 reset = 0;
28 enable = 0;
29 up_en = 0;
30 down_en = 0;
31 #3 reset = 1;
32 $display("@‰0dns De-Asserting reset",$time);
33 #4 enable = 1;
34 $display("@‰0dns De-Asserting reset",$time);
35 #4 up_en = 1;
36 $display("@‰0dns Putting counter in up count mode",$time);
37 #10 up_en = 0;
38 down_en = 1;
39 $display("@‰0dns Putting counter in down count mode",$time);
40 #8 $finish;
41 end
42
43 always #1 clk = ~clk;
44
45 endmodule
You could download file nested_if.v here
@0ns Driving all inputs to know state @0ns reset=0 enable=0 up=0 down=0 count=xxxx @1ns reset=0 enable=0 up=0 down=0 count=0000 @3ns De-Asserting reset @3ns reset=1 enable=0 up=0 down=0 count=0000 @7ns De-Asserting reset @7ns reset=1 enable=1 up=0 down=0 count=0000 @11ns Putting counter in up count mode @11ns reset=1 enable=1 up=1 down=0 count=0001 @13ns reset=1 enable=1 up=1 down=0 count=0010 @15ns reset=1 enable=1 up=1 down=0 count=0011 @17ns reset=1 enable=1 up=1 down=0 count=0100 @19ns reset=1 enable=1 up=1 down=0 count=0101 @21ns Putting counter in down count mode @21ns reset=1 enable=1 up=0 down=1 count=0100 @23ns reset=1 enable=1 up=0 down=1 count=0011 @25ns reset=1 enable=1 up=0 down=1 count=0010 @27ns reset=1 enable=1 up=0 down=1 count=0001
In the above example, the (enable == 1'b1 && up_en == 1'b1) is given highest priority and condition (enable == 1'b1 && down_en == 1'b1) is given lowest priority. We normally don't include reset checking in priority as this does not fall in the combo logic input to the flip-flop as shown in the figure below.
So when we need priority logic, we use nested if-else statements. On the other hand if we don't want to implement priority logic, knowing that only one input is active at a time (i.e. all inputs are mutually exclusive), then we can write the code as shown below.
It's known fact that priority implementation takes more logic to implement than parallel implementation. So if you know the inputs are mutually exclusive, then you can code the logic in parallel if.
1 module parallel_if(); 2 3 reg [3:0] counter; 4 wire clk,reset,enable, up_en, down_en; 5 6 always @ (posedge clk) 7 // If reset is asserted 8 if (reset == 1'b0) begin 9 counter <= 4'b0000; 10 end else begin 11 // If counter is enable and up count is mode 12 if (enable == 1'b1 && up_en == 1'b1) begin 13 counter <= counter + 1'b1; 14 end 15 // If counter is enable and down count is mode 16 if (enable == 1'b1 && down_en == 1'b1) begin 17 counter <= counter - 1'b1; 18 end 19 end 20 21 endmoduleYou could download file parallel_if.v here
The case statement compares an expression to a series of cases and executes the statement or statement group associated with the first matching case:
Syntax of a case statement look as shown below. case () < case1 > : < statement > < case2 > : < statement > ..... default : < statement > endcase
1 module mux (a,b,c,d,sel,y);
2 input a, b, c, d;
3 input [1:0] sel;
4 output y;
5
6 reg y;
7
8 always @ (a or b or c or d or sel)
9 case (sel)
10 0 : y = a;
11 1 : y = b;
12 2 : y = c;
13 3 : y = d;
14 default : $display("Error in SEL");
15 endcase
16
17 endmodule
You could download file mux.v here
1 module mux_without_default (a,b,c,d,sel,y);
2 input a, b, c, d;
3 input [1:0] sel;
4 output y;
5
6 reg y;
7
8 always @ (a or b or c or d or sel)
9 case (sel)
10 0 : y = a;
11 1 : y = b;
12 2 : y = c;
13 3 : y = d;
14 2'bxx,2'bx0,2'bx1,2'b0x,2'b1x,
15 2'bzz,2'bz0,2'bz1,2'b0z,2'b1z : $display("Error in SEL");
16 endcase
17
18 endmodule
You could download file mux_without_default.v here
The example above shows how to specify multiple case items as a single case item.
The Verilog case statement does an identity comparison (like the === operator); one can use the case statement to check for logic x and z values as shown in the example below.
1 module case_xz(enable);
2 input enable;
3
4 always @ (enable)
5 case(enable)
6 1'bz : $display ("enable is floating");
7 1'bx : $display ("enable is unknown");
8 default : $display ("enable is ‰b",enable);
9 endcase
10
11 endmodule
You could download file case_xz.v here
Special versions of the case statement allow the x ad z logic values to be used as "don't care":
1 module casez_example();
2 reg [3:0] opcode;
3 reg [1:0] a,b,c;
4 reg [1:0] out;
5
6 always @ (opcode or a or b or c)
7 casez(opcode)
8 4'b1zzx : begin // Don't care about lower 2:1 bit, bit 0 match with x
9 out = a;
10 $display("@‰0dns 4'b1zzx is selected, opcode ‰b",$time,opcode);
11 end
12 4'b01?? : begin
13 out = b; // bit 1:0 is don't care
14 $display("@‰0dns 4'b01?? is selected, opcode ‰b",$time,opcode);
15 end
16 4'b001? : begin // bit 0 is don't care
17 out = c;
18 $display("@‰0dns 4'b001? is selected, opcode ‰b",$time,opcode);
19 end
20 default : begin
21 $display("@‰0dns default is selected, opcode ‰b",$time,opcode);
22 end
23 endcase
24
25 // Testbench code goes here
26 always #2 a = $random;
27 always #2 b = $random;
28 always #2 c = $random;
29
30 initial begin
31 opcode = 0;
32 #2 opcode = 4'b101x;
33 #2 opcode = 4'b0101;
34 #2 opcode = 4'b0010;
35 #2 opcode = 4'b0000;
36 #2 $finish;
37 end
38
39 endmodule
You could download file casez_example.v here
@0ns default is selected, opcode 0000 @2ns 4'b1zzx is selected, opcode 101x @4ns 4'b01?? is selected, opcode 0101 @6ns 4'b001? is selected, opcode 0010 @8ns default is selected, opcode 0000
1 module casex_example();
2 reg [3:0] opcode;
3 reg [1:0] a,b,c;
4 reg [1:0] out;
5
6 always @ (opcode or a or b or c)
7 casex(opcode)
8 4'b1zzx : begin // Don't care 2:0 bits
9 out = a;
10 $display("@‰0dns 4'b1zzx is selected, opcode ‰b",$time,opcode);
11 end
12 4'b01?? : begin // bit 1:0 is don't care
13 out = b;
14 $display("@‰0dns 4'b01?? is selected, opcode ‰b",$time,opcode);
15 end
16 4'b001? : begin // bit 0 is don't care
17 out = c;
18 $display("@‰0dns 4'b001? is selected, opcode ‰b",$time,opcode);
19 end
20 default : begin
21 $display("@‰0dns default is selected, opcode ‰b",$time,opcode);
22 end
23 endcase
24
25 // Testbench code goes here
26 always #2 a = $random;
27 always #2 b = $random;
28 always #2 c = $random;
29
30 initial begin
31 opcode = 0;
32 #2 opcode = 4'b101x;
33 #2 opcode = 4'b0101;
34 #2 opcode = 4'b0010;
35 #2 opcode = 4'b0000;
36 #2 $finish;
37 end
38
39 endmodule
You could download file casex_example.v here
@0ns default is selected, opcode 0000 @2ns 4'b1zzx is selected, opcode 101x @4ns 4'b01?? is selected, opcode 0101 @6ns 4'b001? is selected, opcode 0010 @8ns default is selected, opcode 0000
1 module case_compare;
2
3 reg sel;
4
5 initial begin
6 #1 $display ("\n Driving 0");
7 sel = 0;
8 #1 $display ("\n Driving 1");
9 sel = 1;
10 #1 $display ("\n Driving x");
11 sel = 1'bx;
12 #1 $display ("\n Driving z");
13 sel = 1'bz;
14 #1 $finish;
15 end
16
17 always @ (sel)
18 case (sel)
19 1'b0 : $display("Normal : Logic 0 on sel");
20 1'b1 : $display("Normal : Logic 1 on sel");
21 1'bx : $display("Normal : Logic x on sel");
22 1'bz : $display("Normal : Logic z on sel");
23 endcase
24
25 always @ (sel)
26 casex (sel)
27 1'b0 : $display("CASEX : Logic 0 on sel");
28 1'b1 : $display("CASEX : Logic 1 on sel");
29 1'bx : $display("CASEX : Logic x on sel");
30 1'bz : $display("CASEX : Logic z on sel");
31 endcase
32
33 always @ (sel)
34 casez (sel)
35 1'b0 : $display("CASEZ : Logic 0 on sel");
36 1'b1 : $display("CASEZ : Logic 1 on sel");
37 1'bx : $display("CASEZ : Logic x on sel");
38 1'bz : $display("CASEZ : Logic z on sel");
39 endcase
40
41 endmodule
You could download file case_compare.v here
Simulation Output
Driving 0
Normal : Logic 0 on sel
CASEX : Logic 0 on sel
CASEZ : Logic 0 on sel
Driving 1
Normal : Logic 1 on sel
CASEX : Logic 1 on sel
CASEZ : Logic 1 on sel
Driving x
Normal : Logic x on sel
CASEX : Logic 0 on sel
CASEZ : Logic x on sel
Driving z
Normal : Logic z on sel
CASEX : Logic 0 on sel
CASEZ : Logic 0 on sel
X, Z In IF Conditions And CaseX, CaseZ from http://www.see.ed.ac.uk/~gerard/Teach/Verilog/me5cds/me95cdr.htmlLogic Levels Within Verilog0 - logic zero, false condition 1 - logic one, true condition x - unknown logic value z - high impedance An x can be any one of a 1, 0, z or change of state. If a one and a zero are both present at a node with comparable strength, the resultant is unknown (x). A z represents a high impedance or floating gate condition. It is the weakest level of logic, being very susceptible to change, and primarily occurs when a node is no longer driven. X, Z in IF and CASE statementsWithin an IF statement a zero corresponds to a false condition and any other value to true. However, if an unknown (x) or high impedance (z) are compared the result may evaluate to an x or z, being interpreted as a false condition. Case expressions may include x's and z's, with the comparison only being successful if there is an exact match between each individual bit (whether it be a 0, 1, x ot z). X, Z In CASEX, CASEZCasex and casez are the two variations of the case statement within Verilog. The syntax is almost identical to the case statement, with the only difference being that case is substituted by either casex or casez. The syntax is as follows: case_statement :: = | case (expression) case_item {case_item} endcase | casez (expression) case_item {case_item} endcase | case (expression) case_item {case_item} endcase case_item :: = expression {,expression} : statement_or_null | default [:] statement_or_null The use of casex and casez allows don't care values to be considered in the comparison. Casez allows for z values to be treated as don't cares, whereas casex allows for both z and x to be treated as don't cares. Only bit values other than the don't care bits are used in the comparison. An example of the use of x within a casex statement is given below: reg [7:0] value_read, value_held; always begin value_held = 8'bx1xx01x1 casex (value_read ^ value_held) 8'bxx1010x0 : statement1; 8'b00xx01x0 : statement2; 8'bx001x0x1 : statement3; 8'bxx1010x0 : statement4; endcase end Where the ^ character represents the Exclusive-OR function. Assuming value_read is given as 11001001 the statement executed is calculated as follows: value_held ^ value_read = x1xx01x1 ^ 01100110 = x0xx00x1 Note: when an x is Exclusive-ORed with any value the result is an x. It can be seen that the only statement the match and therefore the one which is executed is statement3. rand and srand (Perl)Using the Perl rand() functionIntroductionThe Example 1. Between 0 and 1To generate a random decimal number between 0 and 1, use #!/usr/bin/perl use strict; use warnings; my $random_number = rand(); print $random_number . "\n"; This will give you a random number, like: 0.521563085335405 Example 2. A bigger range of numbersQuite often you don't want a number between 0 and 1, but you want a bigger range of numbers. If you pass #!/usr/bin/perl use strict; use warnings; my $range = 100; my $random_number = rand($range); print $random_number . "\n"; The program will produce something like: 34.0500569277541 Example 3. A random integerTo generate a random integer, convert the output from rand to an integer, as follows: #!/usr/bin/perl use strict; use warnings; my $range = 100; my $random_number = int(rand($range)); print $random_number . "\n"; This program gives you an integer from 0 to 99 inclusive: 68 Example 4. With an offsetTo generate a random number between, for example, 100 and 150, simply work out the range and add the minimum value to your random number. #!/usr/bin/perl use strict; use warnings; my $range = 50; my $minimum = 100; my $random_number = int(rand($range)) + $minimum; print $random_number . "\n"; This program gives you: 129 For srand:
26 juin How to manupulate data of the array (Perl) from http://perldoc.perl.org
Does the opposite of a unshift(@ARGV, '-e') unless $ARGV[0] =~ /^-/; Note the LIST is prepended whole, not one element at a time, so the prepended elements stay in the same order. Use
Treats ARRAY as a stack, and pushes the values of LIST onto the end of ARRAY. The length of ARRAY increases by the length of LIST. Has the same effect as for $value (LIST) { $ARRAY[++$#ARRAY] = $value; } but is more efficient. Returns the number of elements in the array following the completed
reverse LIST In list context, returns a list value consisting of the elements of LIST in the opposite order. In scalar context, concatenates the elements of LIST and returns a string value with all characters in the opposite order. print reverse <>; # line tac, last line first undef $/; # for efficiency of <> print scalar reverse <>; # character tac, last line tsrif Used without arguments in scalar context, reverse() reverses This operator is also handy for inverting a hash, although there are some caveats. If a value is duplicated in the original hash, only one of those can be represented as a key in the inverted hash. Also, this has to unwind one hash and build a whole new one, which may take some time on a large hash, such as from a DBM file. %by_name = reverse %by_address; # Invert the hash
effective perl programming from http://www.usenix.org/publications/login/2000-7/features/effective.htmleffective perl programming
by Joseph N. Hall Joseph N. Hall is the author of Effective Perl Programming (Addison-Wesley, 1998). He teaches Perl classes, consults, and plays a lot of golf in his spare time. Manual SQL (It Rhymes) You Too Can Write an SQL Client Lately I've found myself spending an increasing amount of time working with Perl and SQL databases, and sometimes with more than one type of server at a time. One minor aggravation in dealing with different kinds of servers at the same time is that their command-line clients work differently. For example, MySQL's command-line client, mysql, has the GNU readline library built into it, which means that you can use the up and down arrows (or Control-N, Control-P) to access the command-line history, and various emacs-like commands to edit the current line. Oracle's SQL*PLUS client, on the other hand, has a lot of nifty features, but no readline library. Ugh. Well, I guess if my SQL client(s) don't suit me, I should consider writing my own. And that's exactly what I've done for this article. In years past I probably wouldn't have considered writing my own SQL client, and certainly not as an afternoon "quickie," but as you'll see below, nowadays with Perl it's just a matter of slapping together some modules. Starting Up First, make sure you have the DBI, Term::ReadLine, and Term::ReadLine::Gnu modules installed, as well as the DBD module(s) for your favorite server(s). Our shiny new server-independent SQL client will be called perlsql. Let's start it off like this: #!/usr/local/bin/perl -w The use DBI directive gives me the DBI module, and use Term::ReadLine gives me an interface to GNU readline-like functionality. File::MkTemp will also come in handy in a bit. From the UNIX command line, we'll invoke perlsql something like this: persql 'DBI:Oracle:host=localhost;sid=main' scott/tiger The first argument is a DBI DSN string. It will, of course, vary (considerably) depending on what server you're connecting to, how it's set up, and what environment you are executing in. The second argument is an Oracle-style username/password identifier. Here's how we process the command line: my $dsn = shift; The shift operator works on @ARGV by default if you don't specify an argument. The username and password default to empty string if none are specified. Now we're ready to connect to the database: $dbh = DBI->connect($dsn, $user, $passwd, This connects us to the database and sets some connect attributes. We turn the PrintError attribute off so that error messages aren't automatically printed. Turning RaiseError on causes DBI to generate an exception when an error is encountered. Turning AutoCommit on automatically commits every statement executed by DBI. Next, let's initialize Term::ReadLine: my $term = new Term::ReadLine 'PerlSQ'; We're now ready to write some command-processing code. The Readline Loop I'll go ahead and show you the entire command-processing loop, and then explain it a piece at a time. while (defined($_ = $term->readline("$line> ")) ) { The command-processing line is, overall, a while loop that reads a line at a time from our ReadLine terminal. If the user types the end-of-file character, $term->readline returns undef and drops us out of the loop. Inside the loop we first strip leading/trailing white space from the command line and make sure it's not blank. If it's not, we process the line in one of several possible ways. First, we check to see if the line is an SQL command. The hash %is_sql_cmd contains a list of SQL commands. This is obviously server-dependent, but simple enough to come up with. I define it like this: my %is_sql_cmd = map { $_ => 1 } qw( If it is an SQL command, I pass it to my do_sql subroutine, which I'll explain below. The next possibility is that the user has typed quit. In that case, I delete the current line (containing quit) from the readline history, and exit the loop. Another possibility is a line beginning with an exclamation mark. Those lines get sent to a shell with Perl's system operator. If the line doesn't fit one of those descriptions, it's treated as a Perl command. If you supply the eval operator a string, Perl takes the string and executes it as Perl code in the current context. Note that I'm using the generalized qq form of double quote — it just looks better to me than ordinary double quotes if I'm quoting several lines. I don't want the Perl code executed in my current package (otherwise, commands typed in by the user might inadvertently mess up the running perlsql program!), so I change to a different package in the eval — perlsql in this case. I turn off strict and make sure the default filehandle is set to STDOUT, then execute the command line in a do block. Then I restore the default filehandle and return the result of executing the command. (Note that this code doesn't actually do anything with the result, $res, but that's a feature that could be added.) If the eval produced an error, the message will be in the $@ variable, so I check that and print it if necessary. At the bottom of the loop, I increment the line number counter. Processing SQL The do_sql subroutine takes a single SQL command as its argument, double-quote interpolates it, executes it, and then displays the result. sub do_sql { Double-quote interpolating SQL command lines is useful because it lets us use Perl variables inside our commands — something like: select count(*) from club where state = '$state' To double-quote interpolate $sql, I eval it in the perlsql package. Note that the argument to eval is a double-quoted string, and that within that I have another double-quoted string. I use a NUL (\0) as the delimiter for the embedded double-quoted string. After that, I echo the interpolated command to the terminal and then prepare and execute the command. I display the results of select statements with the display_result subroutine: sub display_result { The arguments to display_result are array references containing the "precision" of the result columns (how many characters are required to print the contents), the names of the result columns, and the results themselves. The results are a two-dimensional "array of arrays." I use the precision to create a suitable printf format (just printing the data as strings) and then print each row of the result. The whole thing winds up looking like this: 112> select distinct postal_code from club where name like 'Augusta%' For non-select statements, I print the number of rows affected by the command (if available). More Powerful Command-line Editing One of the annoying things about using SQL command-line clients is that you often need to enter rather long commands. Perhaps you'd like to be able to edit them using a separate editor? No problem! We'll just bind the Control-V key to a subroutine that lets you edit the current line in your favorite editor: $term->add_defun('visual', sub { The Term::ReadLine::Gnu method add_defun registers a subroutine with the readline library. In this case, I've defined it as an anonymous subroutine (with the sub {} operator). I use the mktemp subroutine from File::MkTemp to create a temporary filename, then create a temporary file with that name, write the contents of the current command line into it (from copy_text), and fire up an editor on that file with system. If the editor leaves a readable file, I read the contents back in as a single blob of text (clearing the $/ special variable makes Perl ignore line endings when reading from the file) and use that to set the current command. I found that it was necessary to manipulate the insertion point with Attribs->{point} manually to avoid some weird problems. A call to forced_update_display after everything's done forces the readline library to update the display. The bind_key method binds the subroutine that I've registered with the name visual to the Control-V key. Cleaning Up An END block handles disconnect from the database and cleanup of any temporary files that might have been left behind: END { Features Gone Begging I've written a slightly longer version of this program that has a few more frills. It saves the history to a file and restores it on startup, and also reads in a This short program (the version on my Web site above is only 140 lines long as of this writing) is, I think, an excellent demonstration of how you can quickly create surprisingly powerful and useful things in Perl. It took me only a few hours to write perlsql. Yet, even after that small amount of work, it's a useful database-independent SQL client, and one that knows Perl in addition to everything else! The idea behind perlsql isn't a new one — there have been previous attempts at writing DBI/ReadLine clients. The notion hit me all on my own but it was of course not original. The first such well-known DBI-based client was Andreas Koenig's pmsql. A later program was dbimon. dbimon is apparently out of date, but I have also seen a few other more recent Perl-based SQL clients. 24 juin Predefined Names (perl) from http://www.cs.cmu.edu/afs/cs/user/rgs/mosaic/pl-predef.html#$|Predefined NamesThe following names have special meaning to perl. I could have used alphabetic symbols for some of these, but I didn't want to take the chance that someone would say reset "a-zA-Z" and wipe them all out. You'll just have to suffer along with these silly symbols. Most of them have reasonable mnemonics, or analogues in one of the shells.
system vs exec perl from perldoc.perl.org
Both Perl's exec() function and system() function execute a system shell command. The big difference is that system() creates a fork process and waits to see if the command succeeds or fails - returning a value. exec() does not return anything, it simply executes the command. Neither of these commands should be used to capture the output of a system call. If your goal is to capture output, you should use the backtick operator: $result = `PROGRAM`; Pattern matching inside the array#! usr/bin/perl @a = 'adad'; output: dadadadda but if the code is like below #! usr/bin/perl $a = 'adad'; if (/adad/){ it don’t have the output. the first one is like pattern matching,as long as the element of a array can match the adad, it will print out the dadadadda umask -Perl
0 = absolutely nothing 1 = x other 2 = w other 4 = r other 8 = x group 16 = w group 32 = r group 64 = x user 128 = w user 256 = r user 512 = sticky other 1024 = sticky group 2048 = sticky user add 'em together to get what you want! :) e.g. umask 384 = rw------- umask 448 = rwx------ umask 457 = rwx--x—x umask 420 = rw-r--r-- umask 4095 = rwsrwsrwt –everything umask 4096 = --------- --flips all the bits over 19 juin perltoot - Tom's object-oriented tutorial for perl(2) from http://perl.about.com/gi/dynamic/offsite.htm?zi=1/XJ/Ya&sdn=perl&cdn=compute&tm=20&gps=247_142_1020_541&f=22&tt=14&bt=0&bts=0&st=31&zu=http%3A//www.xav.com/perl/lib/Pod/perltoot.htmlAlternate Object RepresentationsNothing requires objects to be implemented as hash references. An object can be any sort of reference so long as its referent has been suitably blessed. That means scalar, array, and code references are also fair game. A scalar would work if the object has only one datum to hold. An array would work for most cases, but makes inheritance a bit dodgy because you have to invent new indices for the derived classes.
Arrays as ObjectsIf the user of your class honors the contract and sticks to the advertised interface, then you can change its underlying interface if you feel like it. Here's another implementation that conforms to the same interface specification. This time we'll use an array reference instead of a hash reference to represent the object. package Person;
use strict;my($NAME, $AGE, $PEERS) = ( 0 .. 2 ); ############################################
## the object constructor (array version) ##
############################################
sub new {
my $self = [];
$self->[$NAME] = undef; # this is unnecessary
$self->[$AGE] = undef; # as is this
$self->[$PEERS] = []; # but this isn't, really
bless($self);
return $self;
} sub name {
my $self = shift;
if (@_) { $self->[$NAME] = shift }
return $self->[$NAME];
} sub age {
my $self = shift;
if (@_) { $self->[$AGE] = shift }
return $self->[$AGE];
} sub peers {
my $self = shift;
if (@_) { @{ $self->[$PEERS] } = @_ }
return @{ $self->[$PEERS] };
}1; # so the require or use succeeds You might guess that the array access would be a lot faster than the hash access, but they're actually comparable. The array is a little bit faster, but not more than ten or fifteen percent, even when you replace the variables above like $AGE with literal numbers, like 1. A bigger difference between the two approaches can be found in memory use. A hash representation takes up more memory than an array representation because you have to allocate memory for the keys as well as for the values. However, it really isn't that bad, especially since as of version 5.004, memory is only allocated once for a given hash key, no matter how many hashes have that key. It's expected that sometime in the future, even these differences will fade into obscurity as more efficient underlying representations are devised. Still, the tiny edge in speed (and somewhat larger one in memory) is enough to make some programmers choose an array representation for simple classes. There's still a little problem with scalability, though, because later in life when you feel like creating subclasses, you'll find that hashes just work out better.
Closures as ObjectsUsing a code reference to represent an object offers some fascinating possibilities. We can create a new anonymous function (closure) who alone in all the world can see the object's data. This is because we put the data into an anonymous hash that's lexically visible only to the closure we create, bless, and return as the object. This object's methods turn around and call the closure as a regular subroutine call, passing it the field we want to affect. (Yes, the double-function call is slow, but if you wanted fast, you wouldn't be using objects at all, eh? :-) Use would be similar to before: use Person;
$him = Person->new();
$him->name("Jason");
$him->age(23);
$him->peers( [ "Norbert", "Rhys", "Phineas" ] );
printf "%s is %d years old.\n", $him->name, $him->age;
print "His peers are: ", join(", ", @{$him->peers}), "\n";
but the implementation would be radically, perhaps even sublimely different: package Person; sub new {
my $that = shift;
my $class = ref($that) || $that;
my $self = {
NAME => undef,
AGE => undef,
PEERS => [],
};
my $closure = sub {
my $field = shift;
if (@_) { $self->{$field} = shift }
return $self->{$field};
};
bless($closure, $class);
return $closure;
} sub name { &{ $_[0] }("NAME", @_[ 1 .. $#_ ] ) }
sub age { &{ $_[0] }("AGE", @_[ 1 .. $#_ ] ) }
sub peers { &{ $_[0] }("PEERS", @_[ 1 .. $#_ ] ) }1; Because this object is hidden behind a code reference, it's probably a bit mysterious to those whose background is more firmly rooted in standard procedural or object-based programming languages than in functional programming languages whence closures derive. The object created and returned by the When a method like Once we're executing inside the closure that had been created in new(), the $self hash reference suddenly becomes visible. The closure grabs its first argument (``NAME'' in this case because that's what the Nothing under the sun will allow anyone outside the executing method to be able to get at this hidden data. Well, nearly nothing. You could single step through the program using the debugger and find out the pieces while you're in the method, but everyone else is out of luck. There, if that doesn't excite the Scheme folks, then I just don't know what will. Translation of this technique into C++, Java, or any other braindead-static language is left as a futile exercise for aficionados of those camps. You could even add a bit of nosiness via the If you were wondering when Hubris, the third principle virtue of a programmer, would come into play, here you have it. (More seriously, Hubris is just the pride in craftsmanship that comes from having written a sound bit of well-designed code.)
AUTOLOAD: Proxy MethodsAutoloading is a way to intercept calls to undefined methods. An autoload routine may choose to create a new function on the fly, either loaded from disk or perhaps just eval()ed right there. This define-on-the-fly strategy is why it's called autoloading. But that's only one possible approach. Another one is to just have the autoloaded method itself directly provide the requested service. When used in this way, you may think of autoloaded methods as ``proxy'' methods. When Perl tries to call an undefined function in a particular package and that function is not defined, it looks for a function in that same package called AUTOLOAD. If one exists, it's called with the same arguments as the original function would have had. The fully-qualified name of the function is stored in that package's global variable $AUTOLOAD. Once called, the function can do anything it would like, including defining a new function by the right name, and then doing a really fancy kind of What does this have to do with objects? After all, we keep talking about functions, not methods. Well, since a method is just a function with an extra argument and some fancier semantics about where it's found, we can use autoloading for methods, too. Perl doesn't start looking for an AUTOLOAD method until it has exhausted the recursive hunt up through @ISA, though. Some programmers have even been known to define a UNIVERSAL::AUTOLOAD method to trap unresolved method calls to any kind of object.
Autoloaded Data MethodsYou probably began to get a little suspicious about the duplicated code way back earlier when we first showed you the Person class, and then later the Employee class. Each method used to access the hash fields looked virtually identical. This should have tickled that great programming virtue, Impatience, but for the time, we let Laziness win out, and so did nothing. Proxy methods can cure this. Instead of writing a new function every time we want a new data field, we'll use the autoload mechanism to generate (actually, mimic) methods on the fly. To verify that we're accessing a valid member, we will check against an Here's what the module initialization code and class constructor will look like when taking this approach: package Person;
use Carp;
our $AUTOLOAD; # it's a package global my %fields = (
name => undef,
age => undef,
peers => undef,
); sub new {
my $that = shift;
my $class = ref($that) || $that;
my $self = {
_permitted => \%fields,
%fields,
};
bless $self, $class;
return $self;
}
If we wanted our record to have default values, we could fill those in where current we have Notice how we saved a reference to our class data on the object itself? Remember that it's important to access class data through the object itself instead of having any method reference %fields directly, or else you won't have a decent inheritance. The real magic, though, is going to reside in our proxy method, which will handle all calls to undefined methods for objects of class Person (or subclasses of Person). It has to be called AUTOLOAD. Again, it's all caps because it's called for us implicitly by Perl itself, not by a user directly. sub AUTOLOAD {
my $self = shift;
my $type = ref($self)
or croak "$self is not an object"; my $name = $AUTOLOAD;
$name =~ s/.*://; # strip fully-qualified portion unless (exists $self->{_permitted}->{$name} ) {
croak "Can't access `$name' field in class $type";
} if (@_) {
return $self->{$name} = shift;
} else {
return $self->{$name};
}
}
Pretty nifty, eh? All we have to do to add new data fields is modify %fields. No new functions need be written. I could have avoided the
Inherited Autoloaded Data MethodsBut what about inheritance? Can we define our Employee class similarly? Yes, so long as we're careful enough. Here's how to be careful: package Employee;
use Person;
use strict;
our @ISA = qw(Person); my %fields = (
id => undef,
salary => undef,
); sub new {
my $that = shift;
my $class = ref($that) || $that;
my $self = bless $that->SUPER::new(), $class;
my($element);
foreach $element (keys %fields) {
$self->{_permitted}->{$element} = $fields{$element};
}
@{$self}{keys %fields} = values %fields;
return $self;
}
Once we've done this, we don't even need to have an AUTOLOAD function in the Employee package, because we'll grab Person's version of that via inheritance, and it will all work out just fine.
Metaclassical ToolsEven though proxy methods can provide a more convenient approach to making more struct-like classes than tediously coding up data methods as functions, it still leaves a bit to be desired. For one thing, it means you have to handle bogus calls that you don't mean to trap via your proxy. It also means you have to be quite careful when dealing with inheritance, as detailed above. Perl programmers have responded to this by creating several different class construction classes. These metaclasses are classes that create other classes. A couple worth looking at are Class::Struct and Alias. These and other related metaclasses can be found in the modules directory on CPAN.
Class::StructOne of the older ones is Class::Struct. In fact, its syntax and interface were sketched out long before perl5 even solidified into a real thing. What it does is provide you a way to ``declare'' a class as having objects whose fields are of a specific type. The function that does this is called, not surprisingly enough, struct(). Because structures or records are not base types in Perl, each time you want to create a class to provide a record-like data object, you yourself have to define a Here's a simple example of using it: use Class::Struct qw(struct);
use Jobbie; # user-defined; see below struct 'Fred' => {
one => '$',
many => '@',
profession => Jobbie, # calls Jobbie->new()
}; $ob = Fred->new;
$ob->one("hmmmm"); $ob->many(0, "here");
$ob->many(1, "you");
$ob->many(2, "go");
print "Just set: ", $ob->many(2), "\n";$ob->profession->salary(10_000); You can declare types in the struct to be basic Perl types, or user-defined types (classes). User types will be initialized by calling that class's Here's a real-world example of using struct generation. Let's say you wanted to override Perl's idea of use Socket;
use Net::hostent;
$h = gethostbyname("perl.com"); # object return
printf "perl.com's real name is %s, address %s\n",
$h->name, inet_ntoa($h->addr);
Here's how to do this using the Class::Struct module. The crux is going to be this call: struct 'Net::hostent' => [ # note bracket
name => '$',
aliases => '@',
addrtype => '$',
'length' => '$',
addr_list => '@',
];
Which creates object methods of those names and types. It even creates a We could also have implemented our object this way: struct 'Net::hostent' => { # note brace
name => '$',
aliases => '@',
addrtype => '$',
'length' => '$',
addr_list => '@',
};
and then Class::Struct would have used an anonymous hash as the object type, instead of an anonymous array. The array is faster and smaller, but the hash works out better if you eventually want to do inheritance. Since for this struct-like object we aren't planning on inheritance, this time we'll opt for better speed and size over better flexibility. Here's the whole implementation: package Net::hostent;
use strict; BEGIN {
use Exporter ();
our @EXPORT = qw(gethostbyname gethostbyaddr gethost);
our @EXPORT_OK = qw(
$h_name @h_aliases
$h_addrtype $h_length
@h_addr_list $h_addr
);
our %EXPORT_TAGS = ( FIELDS => [ @EXPORT_OK, @EXPORT ] );
}
our @EXPORT_OK; # Class::Struct forbids use of @ISA
sub import { goto &Exporter::import } use Class::Struct qw(struct);
struct 'Net::hostent' => [
name => '$',
aliases => '@',
addrtype => '$',
'length' => '$',
addr_list => '@',
]; sub addr { shift->addr_list->[0] } sub populate (@) {
return unless @_;
my $hob = new(); # Class::Struct made this!
$h_name = $hob->[0] = $_[0];
@h_aliases = @{ $hob->[1] } = split ' ', $_[1];
$h_addrtype = $hob->[2] = $_[2];
$h_length = $hob->[3] = $_[3];
$h_addr = $_[4];
@h_addr_list = @{ $hob->[4] } = @_[ (4 .. $#_) ];
return $hob;
} sub gethostbyname ($) { populate(CORE::gethostbyname(shift)) } sub gethostbyaddr ($;$) {
my ($addr, $addrtype);
$addr = shift;
require Socket unless @_;
$addrtype = @_ ? shift : Socket::AF_INET();
populate(CORE::gethostbyaddr($addr, $addrtype))
} sub gethost($) {
if ($_[0] =~ /^\d+(?:\.\d+(?:\.\d+(?:\.\d+)?)?)?$/) {
require Socket;
&gethostbyaddr(Socket::inet_aton(shift));
} else {
&gethostbyname;
}
}1; We've snuck in quite a fair bit of other concepts besides just dynamic class creation, like overriding core functions, import/export bits, function prototyping, short-cut function call via You can look at other object-based, struct-like overrides of core functions in the 5.004 release of Perl in File::stat, Net::hostent, Net::netent, Net::protoent, Net::servent, Time::gmtime, Time::localtime, User::grent, and User::pwent. These modules have a final component that's all lowercase, by convention reserved for compiler pragmas, because they affect the compilation and change a builtin function. They also have the type names that a C programmer would most expect.
Data Members as VariablesIf you're used to C++ objects, then you're accustomed to being able to get at an object's data members as simple variables from within a method. The Alias module provides for this, as well as a good bit more, such as the possibility of private methods that the object can call but folks outside the class cannot. Here's an example of creating a Person using the Alias module. When you update these magical instance variables, you automatically update value fields in the hash. Convenient, eh? package Person; # this is the same as before...
sub new {
my $that = shift;
my $class = ref($that) || $that;
my $self = {
NAME => undef,
AGE => undef,
PEERS => [],
};
bless($self, $class);
return $self;
} use Alias qw(attr);
our ($NAME, $AGE, $PEERS); sub name {
my $self = attr shift;
if (@_) { $NAME = shift; }
return $NAME;
} sub age {
my $self = attr shift;
if (@_) { $AGE = shift; }
return $AGE;
} sub peers {
my $self = attr shift;
if (@_) { @PEERS = @_; }
return @PEERS;
} sub exclaim {
my $self = attr shift;
return sprintf "Hi, I'm %s, age %d, working with %s",
$NAME, $AGE, join(", ", @PEERS);
} sub happy_birthday {
my $self = attr shift;
return ++$AGE;
}
The need for the It would be nice to combine Alias with something like Class::Struct or Class::MethodMaker.
NOTES
Object TerminologyIn the various OO literature, it seems that a lot of different words are used to describe only a few different concepts. If you're not already an object programmer, then you don't need to worry about all these fancy words. But if you are, then you might like to know how to get at the same concepts in Perl. For example, it's common to call an object an instance of a class and to call those objects' methods instance methods. Data fields peculiar to each object are often called instance data or object attributes, and data fields common to all members of that class are class data, class attributes, or static data members. Also, base class, generic class, and superclass all describe the same notion, whereas derived class, specific class, and subclass describe the other related one. C++ programmers have static methods and virtual methods, but Perl only has class methods and object methods. Actually, Perl only has methods. Whether a method gets used as a class or object method is by usage only. You could accidentally call a class method (one expecting a string argument) on an object (one expecting a reference), or vice versa. From the C++ perspective, all methods in Perl are virtual. This, by the way, is why they are never checked for function prototypes in the argument list as regular builtin and user-defined functions can be. Because a class is itself something of an object, Perl's classes can be taken as describing both a ``class as meta-object'' (also called object factory) philosophy and the ``class as type definition'' (declaring behaviour, not defining mechanism) idea. C++ supports the latter notion, but not the former.
SEE ALSOThe following manpages will doubtless provide more background for this one: the perlmod manpage, the perlref manpage, the perlobj manpage, the perlbot manpage, the perltie manpage, and the overload manpage.
AUTHOR AND COPYRIGHTCopyright (c) 1997, 1998 Tom Christiansen All rights reserved. When included as part of the Standard Version of Perl, or as part of its complete documentation whether printed or otherwise, this work may be distributed only under the terms of Perl's Artistic License. Any distribution of this file or derivatives thereof outside of that package require that special arrangements be made with copyright holder. Irrespective of its distribution, all code examples in this file are hereby placed into the public domain. You are permitted and encouraged to use this code in your own programs for fun or for profit as you see fit. A simple comment in the code giving credit would be courteous but is not required.
COPYRIGHT
AcknowledgmentsThanks to Larry Wall, Roderick Schertler, Gurusamy Sarathy, Dean Roehrich, Raphael Manfredi, Brent Halsey, Greg Bacon, Brad Appleton, and many others for their helpful comments.
Talking about perltoot - Tom's object-oriented tutorial for perl (1)from http://perl.about.com/gi/dynamic/offsite.htm?zi=1/XJ/Ya&sdn=perl&cdn=compute&tm=20&gps=247_142_1020_541&f=22&tt=14&bt=0&bts=0&st=31&zu=http%3A//www.xav.com/perl/lib/Pod/perltoot.html
NAMEperltoot - Tom's object-oriented tutorial for perl
DESCRIPTIONObject-oriented programming is a big seller these days. Some managers would rather have objects than sliced bread. Why is that? What's so special about an object? Just what is an object anyway? An object is nothing but a way of tucking away complex behaviours into a neat little easy-to-use bundle. (This is what professors call abstraction.) Smart people who have nothing to do but sit around for weeks on end figuring out really hard problems make these nifty objects that even regular people can use. (This is what professors call software reuse.) Users (well, programmers) can play with this little bundle all they want, but they aren't to open it up and mess with the insides. Just like an expensive piece of hardware, the contract says that you void the warranty if you muck with the cover. So don't do that. The heart of objects is the class, a protected little private namespace full of data and functions. A class is a set of related routines that addresses some problem area. You can think of it as a user-defined type. The Perl package mechanism, also used for more traditional modules, is used for class modules as well. Objects ``live'' in a class, meaning that they belong to some package. More often than not, the class provides the user with little bundles. These bundles are objects. They know whose class they belong to, and how to behave. Users ask the class to do something, like ``give me an object.'' Or they can ask one of these objects to do something. Asking a class to do something for you is calling a class method. Asking an object to do something for you is calling an object method. Asking either a class (usually) or an object (sometimes) to give you back an object is calling a constructor, which is just a kind of method. That's all well and good, but how is an object different from any other Perl data type? Just what is an object really; that is, what's its fundamental type? The answer to the first question is easy. An object is different from any other data type in Perl in one and only one way: you may dereference it using not merely string or numeric subscripts as with simple arrays and hashes, but with named subroutine calls. In a word, with methods. The answer to the second question is that it's a reference, and not just any reference, mind you, but one whose referent has been bless()ed into a particular class (read: package). What kind of reference? Well, the answer to that one is a bit less concrete. That's because in Perl the designer of the class can employ any sort of reference they'd like as the underlying intrinsic data type. It could be a scalar, an array, or a hash reference. It could even be a code reference. But because of its inherent flexibility, an object is usually a hash reference.
Creating a ClassBefore you create a class, you need to decide what to name it. That's because the class (package) name governs the name of the file used to house it, just as with regular modules. Then, that class (package) should provide one or more ways to generate objects. Finally, it should provide mechanisms to allow users of its objects to indirectly manipulate these objects from a distance. For example, let's make a simple Person class module. It gets stored in the file Person.pm. If it were called a Happy::Person class, it would be stored in the file Happy/Person.pm, and its package would become Happy::Person instead of just Person. (On a personal computer not running Unix or Plan 9, but something like MacOS or VMS, the directory separator may be different, but the principle is the same.) Do not assume any formal relationship between modules based on their directory names. This is merely a grouping convenience, and has no effect on inheritance, variable accessibility, or anything else. For this module we aren't going to use Exporter, because we're a well-behaved class module that doesn't export anything at all. In order to manufacture objects, a class needs to have a constructor method. A constructor gives you back not just a regular data type, but a brand-new object in that class. This magic is taken care of by the While a constructor may be named anything you'd like, most Perl programmers seem to like to call theirs new(). However,
Object RepresentationBy far the most common mechanism used in Perl to represent a Pascal record, a C struct, or a C++ class is an anonymous hash. That's because a hash has an arbitrary number of data fields, each conveniently accessed by an arbitrary name of your own devising. If you were just doing a simple struct-like emulation, you would likely go about it something like this: $rec = {
name => "Jason",
age => 23,
peers => [ "Norbert", "Rhys", "Phineas"],
};
If you felt like it, you could add a bit of visual distinction by up-casing the hash keys: $rec = {
NAME => "Jason",
AGE => 23,
PEERS => [ "Norbert", "Rhys", "Phineas"],
};
And so you could get at This same model is often used for classes, although it is not considered the pinnacle of programming propriety for folks from outside the class to come waltzing into an object, brazenly accessing its data members directly. Generally speaking, an object should be considered an opaque cookie that you use object methods to access. Visually, methods look like you're dereffing a reference using a function name instead of brackets or braces.
Class InterfaceSome languages provide a formal syntactic interface to a class's methods, but Perl does not. It relies on you to read the documentation of each class. If you try to call an undefined method on an object, Perl won't complain, but the program will trigger an exception while it's running. Likewise, if you call a method expecting a prime number as its argument with a non-prime one instead, you can't expect the compiler to catch this. (Well, you can expect it all you like, but it's not going to happen.) Let's suppose you have a well-educated user of your Person class, someone who has read the docs that explain the prescribed interface. Here's how they might use the Person class: use Person; $him = Person->new();
$him->name("Jason");
$him->age(23);
$him->peers( "Norbert", "Rhys", "Phineas" );push @All_Recs, $him; # save object in array for later printf "%s is %d years old.\n", $him->name, $him->age;
print "His peers are: ", join(", ", $him->peers), "\n";printf "Last rec's name is %s\n", $All_Recs[-1]->name; As you can see, the user of the class doesn't know (or at least, has no business paying attention to the fact) that the object has one particular implementation or another. The interface to the class and its objects is exclusively via methods, and that's all the user of the class should ever play with.
Constructors and Instance MethodsStill, someone has to know what's in the object. And that someone is the class. It implements methods that the programmer uses to access the object. Here's how to implement the Person class using the standard hash-ref-as-an-object idiom. We'll make a class method called package Person;
use strict; ##################################################
## the object constructor (simplistic version) ##
##################################################
sub new {
my $self = {};
$self->{NAME} = undef;
$self->{AGE} = undef;
$self->{PEERS} = [];
bless($self); # but see below
return $self;
} ##############################################
## methods to access per-object data ##
## ##
## With args, they set the value. Without ##
## any, they only retrieve it/them. ##
############################################## sub name {
my $self = shift;
if (@_) { $self->{NAME} = shift }
return $self->{NAME};
} sub age {
my $self = shift;
if (@_) { $self->{AGE} = shift }
return $self->{AGE};
} sub peers {
my $self = shift;
if (@_) { @{ $self->{PEERS} } = @_ }
return @{ $self->{PEERS} };
}1; # so the require or use succeeds We've created three methods to access an object's data, name(), age(), and peers(). These are all substantially similar. If called with an argument, they set the appropriate field; otherwise they return the value held by that field, meaning the value of that hash key.
Planning for the Future: Better ConstructorsEven though at this point you may not even know what it means, someday you're going to worry about inheritance. (You can safely ignore this for now and worry about it later if you'd like.) To ensure that this all works out smoothly, you must use the double-argument form of bless(). The second argument is the class into which the referent will be blessed. By not assuming our own class as the default second argument and instead using the class passed into us, we make our constructor inheritable. While we're at it, let's make our constructor a bit more flexible. Rather than being uniquely a class method, we'll set it up so that it can be called as either a class method or an object method. That way you can say: $me = Person->new();
$him = $me->new();
To do this, all we have to do is check whether what was passed in was a reference or not. If so, we were invoked as an object method, and we need to extract the package (class) using the sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = {};
$self->{NAME} = undef;
$self->{AGE} = undef;
$self->{PEERS} = [];
bless ($self, $class);
return $self;
}
That's about all there is for constructors. These methods bring objects to life, returning neat little opaque bundles to the user to be used in subsequent method calls.
DestructorsEvery story has a beginning and an end. The beginning of the object's story is its constructor, explicitly called when the object comes into existence. But the ending of its story is the destructor, a method implicitly called when an object leaves this life. Any per-object clean-up code is placed in the destructor, which must (in Perl) be called DESTROY. If constructors can have arbitrary names, then why not destructors? Because while a constructor is explicitly called, a destructor is not. Destruction happens automatically via Perl's garbage collection (GC) system, which is a quick but somewhat lazy reference-based GC system. To know what to call, Perl insists that the destructor be named DESTROY. Perl's notion of the right time to call a destructor is not well-defined currently, which is why your destructors should not rely on when they are called. Why is DESTROY in all caps? Perl on occasion uses purely uppercase function names as a convention to indicate that the function will be automatically called by Perl in some way. Others that are called implicitly include BEGIN, END, AUTOLOAD, plus all methods used by tied objects, described in the perltie manpage. In really good object-oriented programming languages, the user doesn't care when the destructor is called. It just happens when it's supposed to. In low-level languages without any GC at all, there's no way to depend on this happening at the right time, so the programmer must explicitly call the destructor to clean up memory and state, crossing their fingers that it's the right time to do so. Unlike C++, an object destructor is nearly never needed in Perl, and even when it is, explicit invocation is uncalled for. In the case of our Person class, we don't need a destructor because Perl takes care of simple matters like memory deallocation. The only situation where Perl's reference-based GC won't work is when there's a circularity in the data structure, such as: $this->{WHATEVER} = $this;
In that case, you must delete the self-reference manually if you expect your program not to leak memory. While admittedly error-prone, this is the best we can do right now. Nonetheless, rest assured that when your program is finished, its objects' destructors are all duly called. So you are guaranteed that an object eventually gets properly destroyed, except in the unique case of a program that never exits. (If you're running Perl embedded in another application, this full GC pass happens a bit more frequently--whenever a thread shuts down.)
Other Object MethodsThe methods we've talked about so far have either been constructors or else simple ``data methods'', interfaces to data stored in the object. These are a bit like an object's data members in the C++ world, except that strangers don't access them as data. Instead, they should only access the object's data indirectly via its methods. This is an important rule: in Perl, access to an object's data should only be made through methods. Perl doesn't impose restrictions on who gets to use which methods. The public-versus-private distinction is by convention, not syntax. (Well, unless you use the Alias module described below in Data Members as Variables.) Occasionally you'll see method names beginning or ending with an underscore or two. This marking is a convention indicating that the methods are private to that class alone and sometimes to its closest acquaintances, its immediate subclasses. But this distinction is not enforced by Perl itself. It's up to the programmer to behave. There's no reason to limit methods to those that simply access data. Methods can do anything at all. The key point is that they're invoked against an object or a class. Let's say we'd like object methods that do more than fetch or set one particular field. sub exclaim {
my $self = shift;
return sprintf "Hi, I'm %s, age %d, working with %s",
$self->{NAME}, $self->{AGE}, join(", ", @{$self->{PEERS}});
}
Or maybe even one like this: sub happy_birthday {
my $self = shift;
return ++$self->{AGE};
}
Some might argue that one should go at these this way: sub exclaim {
my $self = shift;
return sprintf "Hi, I'm %s, age %d, working with %s",
$self->name, $self->age, join(", ", $self->peers);
} sub happy_birthday {
my $self = shift;
return $self->age( $self->age() + 1 );
}
But since these methods are all executing in the class itself, this may not be critical. There are tradeoffs to be made. Using direct hash access is faster (about an order of magnitude faster, in fact), and it's more convenient when you want to interpolate in strings. But using methods (the external interface) internally shields not just the users of your class but even you yourself from changes in your data representation.
Class DataWhat about ``class data'', data items common to each object in a class? What would you want that for? Well, in your Person class, you might like to keep track of the total people alive. How do you implement that? You could make it a global variable called $Person::Census. But about only reason you'd do that would be if you wanted people to be able to get at your class data directly. They could just say $Person::Census and play around with it. Maybe this is ok in your design scheme. You might even conceivably want to make it an exported variable. To be exportable, a variable must be a (package) global. If this were a traditional module rather than an object-oriented one, you might do that. While this approach is expected in most traditional modules, it's generally considered rather poor form in most object modules. In an object module, you should set up a protective veil to separate interface from implementation. So provide a class method to access class data just as you provide object methods to access object data. So, you could still keep $Census as a package global and rely upon others to honor the contract of the module and therefore not play around with its implementation. You could even be supertricky and make $Census a tied object as described in the perltie manpage, thereby intercepting all accesses. But more often than not, you just want to make your class data a file-scoped lexical. To do so, simply put this at the top of the file: my $Census = 0; Even though the scope of a Irrespective of whether you leave $Census a package global or make it instead a file-scoped lexical, you should make these changes to your Person::new() constructor: sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = {};
$Census++;
$self->{NAME} = undef;
$self->{AGE} = undef;
$self->{PEERS} = [];
bless ($self, $class);
return $self;
} sub population {
return $Census;
}
Now that we've done this, we certainly do need a destructor so that when Person is destroyed, the $Census goes down. Here's how this could be done: sub DESTROY { --$Census }
Notice how there's no memory to deallocate in the destructor? That's something that Perl takes care of for you all by itself.
Accessing Class DataIt turns out that this is not really a good way to go about handling class data. A good scalable rule is that you must never reference class data directly from an object method. Otherwise you aren't building a scalable, inheritable class. The object must be the rendezvous point for all operations, especially from an object method. The globals (class data) would in some sense be in the ``wrong'' package in your derived classes. In Perl, methods execute in the context of the class they were defined in, not that of the object that triggered them. Therefore, namespace visibility of package globals in methods is unrelated to inheritance. Got that? Maybe not. Ok, let's say that some other class ``borrowed'' (well, inherited) the DESTROY method as it was defined above. When those objects are destroyed, the original $Census variable will be altered, not the one in the new class's package namespace. Perhaps this is what you want, but probably it isn't. Here's how to fix this. We'll store a reference to the data in the value accessed by the hash key ``_CENSUS''. Why the underscore? Well, mostly because an initial underscore already conveys strong feelings of magicalness to a C programmer. It's really just a mnemonic device to remind ourselves that this field is special and not to be used as a public data member in the same way that NAME, AGE, and PEERS are. (Because we've been developing this code under the strict pragma, prior to perl version 5.004 we'll have to quote the field name.) sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = {};
$self->{NAME} = undef;
$self->{AGE} = undef;
$self->{PEERS} = [];
# "private" data
$self->{"_CENSUS"} = \$Census;
bless ($self, $class);
++ ${ $self->{"_CENSUS"} };
return $self;
} sub population {
my $self = shift;
if (ref $self) {
return ${ $self->{"_CENSUS"} };
} else {
return $Census;
}
} sub DESTROY {
my $self = shift;
-- ${ $self->{"_CENSUS"} };
}
Debugging MethodsIt's common for a class to have a debugging mechanism. For example, you might want to see when objects are created or destroyed. To do that, add a debugging variable as a file-scoped lexical. For this, we'll pull in the standard Carp module to emit our warnings and fatal messages. That way messages will come out with the caller's filename and line number instead of our own; if we wanted them to be from our own perspective, we'd just use use Carp;
my $Debugging = 0;
Now add a new class method to access the variable. sub debug {
my $class = shift;
if (ref $class) { confess "Class method called as object method" }
unless (@_ == 1) { confess "usage: CLASSNAME->debug(level)" }
$Debugging = shift;
}
Now fix up DESTROY to murmur a bit as the moribund object expires: sub DESTROY {
my $self = shift;
if ($Debugging) { carp "Destroying $self " . $self->name }
-- ${ $self->{"_CENSUS"} };
}
One could conceivably make a per-object debug state. That way you could call both of these: Person->debug(1); # entire class
$him->debug(1); # just this object
To do so, we need our debugging method to be a ``bimodal'' one, one that works on both classes and objects. Therefore, adjust the sub debug {
my $self = shift;
confess "usage: thing->debug(level)" unless @_ == 1;
my $level = shift;
if (ref($self)) {
$self->{"_DEBUG"} = $level; # just myself
} else {
$Debugging = $level; # whole class
}
} sub DESTROY {
my $self = shift;
if ($Debugging || $self->{"_DEBUG"}) {
carp "Destroying $self " . $self->name;
}
-- ${ $self->{"_CENSUS"} };
}
What happens if a derived class (which we'll call Employee) inherits methods from this Person base class? Then
Class DestructorsThe object destructor handles the death of each distinct object. But sometimes you want a bit of cleanup when the entire class is shut down, which currently only happens when the program exits. To make such a class destructor, create a function in that class's package named END. This works just like the END function in traditional modules, meaning that it gets called whenever your program exits unless it execs or dies of an uncaught signal. For example, sub END {
if ($Debugging) {
print "All persons are going away now.\n";
}
}
When the program exits, all the class destructors (END functions) are be called in the opposite order that they were loaded in (LIFO order).
Documenting the InterfaceAnd there you have it: we've just shown you the implementation of this Person class. Its interface would be its documentation. Usually this means putting it in pod (``plain old documentation'') format right there in the same file. In our Person example, we would place the following docs anywhere in the Person.pm file. Even though it looks mostly like code, it's not. It's embedded documentation such as would be used by the pod2man, pod2html, or pod2text programs. The Perl compiler ignores pods entirely, just as the translators ignore code. Here's an example of some pods describing the informal interface: =head1 NAME Person - class to implement people =head1 SYNOPSIS use Person; #################
# class methods #
#################
$ob = Person->new;
$count = Person->population; #######################
# object data methods #
####################### ### get versions ###
$who = $ob->name;
$years = $ob->age;
@pals = $ob->peers; ### set versions ###
$ob->name("Jason");
$ob->age(23);
$ob->peers( "Norbert", "Rhys", "Phineas" ); ########################
# other object methods #
######################## $phrase = $ob->exclaim;
$ob->happy_birthday;=head1 DESCRIPTION The Person class implements dah dee dah dee dah.... That's all there is to the matter of interface versus implementation. A programmer who opens up the module and plays around with all the private little shiny bits that were safely locked up behind the interface contract has voided the warranty, and you shouldn't worry about their fate.
AggregationSuppose you later want to change the class to implement better names. Perhaps you'd like to support both given names (called Christian names, irrespective of one's religion) and family names (called surnames), plus nicknames and titles. If users of your Person class have been properly accessing it through its documented interface, then you can easily change the underlying implementation. If they haven't, then they lose and it's their fault for breaking the contract and voiding their warranty. To do this, we'll make another class, this one called Fullname. What's the Fullname class look like? To answer that question, you have to first figure out how you want to use it. How about we use it this way: $him = Person->new();
$him->fullname->title("St");
$him->fullname->christian("Thomas");
$him->fullname->surname("Aquinas");
$him->fullname->nickname("Tommy");
printf "His normal name is %s\n", $him->name;
printf "But his real name is %s\n", $him->fullname->as_string;
Ok. To do this, we'll change Person::new() so that it supports a full name field this way: sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = {};
$self->{FULLNAME} = Fullname->new();
$self->{AGE} = undef;
$self->{PEERS} = [];
$self->{"_CENSUS"} = \$Census;
bless ($self, $class);
++ ${ $self->{"_CENSUS"} };
return $self;
} sub fullname {
my $self = shift;
return $self->{FULLNAME};
}
Then to support old code, define Person::name() this way: sub name {
my $self = shift;
return $self->{FULLNAME}->nickname(@_)
|| $self->{FULLNAME}->christian(@_);
}
Here's the Fullname class. We'll use the same technique of using a hash reference to hold data fields, and methods by the appropriate name to access them: package Fullname;
use strict; sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = {
TITLE => undef,
CHRISTIAN => undef,
SURNAME => undef,
NICK => undef,
};
bless ($self, $class);
return $self;
} sub christian {
my $self = shift;
if (@_) { $self->{CHRISTIAN} = shift }
return $self->{CHRISTIAN};
} sub surname {
my $self = shift;
if (@_) { $self->{SURNAME} = shift }
return $self->{SURNAME};
} sub nickname {
my $self = shift;
if (@_) { $self->{NICK} = shift }
return $self->{NICK};
} sub title {
my $self = shift;
if (@_) { $self->{TITLE} = shift }
return $self->{TITLE};
} sub as_string {
my $self = shift;
my $name = join(" ", @$self{'CHRISTIAN', 'SURNAME'});
if ($self->{TITLE}) {
$name = $self->{TITLE} . " " . $name;
}
return $name;
}1; Finally, here's the test program: #!/usr/bin/perl -w
use strict;
use Person;
sub END { show_census() } sub show_census () {
printf "Current population: %d\n", Person->population;
}Person->debug(1); show_census(); my $him = Person->new(); $him->fullname->christian("Thomas");
$him->fullname->surname("Aquinas");
$him->fullname->nickname("Tommy");
$him->fullname->title("St");
$him->age(1); printf "%s is really %s.\n", $him->name, $him->fullname;
printf "%s's age: %d.\n", $him->name, $him->age;
$him->happy_birthday;
printf "%s's age: %d.\n", $him->name, $him->age;show_census();
InheritanceObject-oriented programming systems all support some notion of inheritance. Inheritance means allowing one class to piggy-back on top of another one so you don't have to write the same code again and again. It's about software reuse, and therefore related to Laziness, the principal virtue of a programmer. (The import/export mechanisms in traditional modules are also a form of code reuse, but a simpler one than the true inheritance that you find in object modules.) Sometimes the syntax of inheritance is built into the core of the language, and sometimes it's not. Perl has no special syntax for specifying the class (or classes) to inherit from. Instead, it's all strictly in the semantics. Each package can have a variable called @ISA, which governs (method) inheritance. If you try to call a method on an object or class, and that method is not found in that object's package, Perl then looks to @ISA for other packages to go looking through in search of the missing method. Like the special per-package variables recognized by Exporter (such as @EXPORT, @EXPORT_OK, @EXPORT_FAIL, %EXPORT_TAGS, and $VERSION), the @ISA array must be a package-scoped global and not a file-scoped lexical created via my(). Most classes have just one item in their @ISA array. In this case, we have what's called ``single inheritance'', or SI for short. Consider this class: package Employee;
use Person;
@ISA = ("Person");
1;
Not a lot to it, eh? All it's doing so far is loading in another class and stating that this one will inherit methods from that other class if need be. We have given it none of its own methods. We rely upon an Employee to behave just like a Person. Setting up an empty class like this is called the ``empty subclass test''; that is, making a derived class that does nothing but inherit from a base class. If the original base class has been designed properly, then the new derived class can be used as a drop-in replacement for the old one. This means you should be able to write a program like this: use Employee;
my $empl = Employee->new();
$empl->name("Jason");
$empl->age(23);
printf "%s is age %d.\n", $empl->name, $empl->age;
By proper design, we mean always using the two-argument form of bless(), avoiding direct access of global data, and not exporting anything. If you look back at the Person::new() function we defined above, we were careful to do that. There's a bit of package data used in the constructor, but the reference to this is stored on the object itself and all other methods access package data via that reference, so we should be ok. What do we mean by the Person::new() function -- isn't that actually a method? Well, in principle, yes. A method is just a function that expects as its first argument a class name (package) or object (blessed reference). Person::new() is the function that both the Method Call Resulting Function Call
----------- ------------------------
Person->new() Person::new("Person")
Employee->new() Person::new("Employee")
So don't use function calls when you mean to call a method. If an employee is just a Person, that's not all too very interesting. So let's add some other methods. We'll give our employee data fields to access their salary, their employee ID, and their start date. If you're getting a little tired of creating all these nearly identical methods just to get at the object's data, do not despair. Later, we'll describe several different convenience mechanisms for shortening this up. Meanwhile, here's the straight-forward way: sub salary {
my $self = shift;
if (@_) { $self->{SALARY} = shift }
return $self->{SALARY};
} sub id_number {
my $self = shift;
if (@_) { $self->{ID} = shift }
return $self->{ID};
} sub start_date {
my $self = shift;
if (@_) { $self->{START_DATE} = shift }
return $self->{START_DATE};
}
Overridden MethodsWhat happens when both a derived class and its base class have the same method defined? Well, then you get the derived class's version of that method. For example, let's say that we want the $empl->peers("Peter", "Paul", "Mary");
printf "His peers are: %s\n", join(", ", $empl->peers);
will produce: His peers are: PEON=PETER, PEON=PAUL, PEON=MARY To do this, merely add this definition into the Employee.pm file: sub peers {
my $self = shift;
if (@_) { @{ $self->{PEERS} } = @_ }
return map { "PEON=\U$_" } @{ $self->{PEERS} };
}
There, we've just demonstrated the high-falutin' concept known in certain circles as polymorphism. We've taken on the form and behaviour of an existing object, and then we've altered it to suit our own purposes. This is a form of Laziness. (Getting polymorphed is also what happens when the wizard decides you'd look better as a frog.) Every now and then you'll want to have a method call trigger both its derived class (also known as ``subclass'') version as well as its base class (also known as ``superclass'') version. In practice, constructors and destructors are likely to want to do this, and it probably also makes sense in the To do this, add this to Employee.pm: use Carp;
my $Debugging = 0; sub debug {
my $self = shift;
confess "usage: thing->debug(level)" unless @_ == 1;
my $level = shift;
if (ref($self)) {
$self->{"_DEBUG"} = $level;
} else {
$Debugging = $level; # whole class
}
Person::debug($self, $Debugging); # don't really do this
}
As you see, we turn around and call the Person package's Person->debug($Debugging); But even that's got too much hard-coded. It's somewhat better to say $self->Person::debug($Debugging); Which is a funny way to say to start looking for a There is still something a bit off here. We've hard-coded our superclass's name. This in particular is bad if you change which classes you inherit from, or add others. Fortunately, the pseudoclass SUPER comes to the rescue here. $self->SUPER::debug($Debugging); This way it starts looking in my class's @ISA. This only makes sense from within a method call, though. Don't try to access anything in SUPER:: from anywhere else, because it doesn't exist outside an overridden method call. Things are getting a bit complicated here. Have we done anything we shouldn't? As before, one way to test whether we're designing a decent class is via the empty subclass test. Since we already have an Employee class that we're trying to check, we'd better get a new empty subclass that can derive from Employee. Here's one: package Boss;
use Employee; # :-)
@ISA = qw(Employee);
And here's the test program: #!/usr/bin/perl -w
use strict;
use Boss;
Boss->debug(1);my $boss = Boss->new(); $boss->fullname->title("Don");
$boss->fullname->surname("Pichon Alvarez");
$boss->fullname->christian("Federico Jesus");
$boss->fullname->nickname("Fred"); $boss->age(47);
$boss->peers("Frank", "Felipe", "Faust"); printf "%s is age %d.\n", $boss->fullname, $boss->age;
printf "His peers are: %s\n", join(", ", $boss->peers);
Running it, we see that we're still ok. If you'd like to dump out your object in a nice format, somewhat like the way the 'x' command works in the debugger, you could use the Data::Dumper module from CPAN this way: use Data::Dumper;
print "Here's the boss:\n";
print Dumper($boss);
Which shows us something like this: Here's the boss:
$VAR1 = bless( {
_CENSUS => \1,
FULLNAME => bless( {
TITLE => 'Don',
SURNAME => 'Pichon Alvarez',
NICK => 'Fred',
CHRISTIAN => 'Federico Jesus'
}, 'Fullname' ),
AGE => 47,
PEERS => [
'Frank',
'Felipe',
'Faust'
]
}, 'Boss' );
Hm.... something's missing there. What about the salary, start date, and ID fields? Well, we never set them to anything, even undef, so they don't show up in the hash's keys. The Employee class has no sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = $class->SUPER::new();
$self->{SALARY} = undef;
$self->{ID} = undef;
$self->{START_DATE} = undef;
bless ($self, $class); # reconsecrate
return $self;
}
Now if you dump out an Employee or Boss object, you'll find that new fields show up there now.
Multiple InheritanceOk, at the risk of confusing beginners and annoying OO gurus, it's time to confess that Perl's object system includes that controversial notion known as multiple inheritance, or MI for short. All this means is that rather than having just one parent class who in turn might itself have a parent class, etc., that you can directly inherit from two or more parents. It's true that some uses of MI can get you into trouble, although hopefully not quite so much trouble with Perl as with dubiously-OO languages like C++. The way it works is actually pretty simple: just put more than one package name in your @ISA array. When it comes time for Perl to go finding methods for your object, it looks at each of these packages in order. Well, kinda. It's actually a fully recursive, depth-first order. Consider a bunch of @ISA arrays like this: @First::ISA = qw( Alpha );
@Second::ISA = qw( Beta );
@Third::ISA = qw( First Second );
If you have an object of class Third: my $ob = Third->new();
$ob->spin();
How do we find a In practice, few class modules have been seen that actually make use of MI. One nearly always chooses simple containership of one class within another over MI. That's why our Person object contained a Fullname object. That doesn't mean it was one. However, there is one particular area where MI in Perl is rampant: borrowing another class's class methods. This is rather common, especially with some bundled ``objectless'' classes, like Exporter, DynaLoader, AutoLoader, and SelfLoader. These classes do not provide constructors; they exist only so you may inherit their class methods. (It's not entirely clear why inheritance was done here rather than traditional module importation.) For example, here is the POSIX module's @ISA: package POSIX;
@ISA = qw(Exporter DynaLoader);
The POSIX module isn't really an object module, but then, neither are Exporter or DynaLoader. They're just lending their classes' behaviours to POSIX. Why don't people use MI for object methods much? One reason is that it can have complicated side-effects. For one thing, your inheritance graph (no longer a tree) might converge back to the same base class. Although Perl guards against recursive inheritance, merely having parents who are related to each other via a common ancestor, incestuous though it sounds, is not forbidden. What if in our Third class shown above we wanted its
UNIVERSAL: The Root of All ObjectsWouldn't it be convenient if all objects were rooted at some ultimate base class? That way you could give every object common methods without having to go and add it to each and every @ISA. Well, it turns out that you can. You don't see it, but Perl tacitly and irrevocably assumes that there's an extra element at the end of @ISA: the class UNIVERSAL. In version 5.003, there were no predefined methods there, but you could put whatever you felt like into it. However, as of version 5.004 (or some subversive releases, like 5.003_08), UNIVERSAL has some methods in it already. These are builtin to your Perl binary, so they don't take any extra time to load. Predefined methods include isa(), can(), and VERSION(). $has_io = $fd->isa("IO::Handle");
$itza_handle = IO::Socket->isa("IO::Handle");
The $his_print_method = $obj->can('as_string');
Finally, the VERSION method checks whether the class (or the object's class) has a package global called $VERSION that's high enough, as in: Some_Module->VERSION(3.0);
$his_vers = $ob->VERSION();
However, we don't usually call VERSION ourselves. (Remember that an all uppercase function name is a Perl convention that indicates that the function will be automatically used by Perl in some way.) In this case, it happens when you say use Some_Module 3.0; If you wanted to add version checking to your Person class explained above, just add this to Person.pm: our $VERSION = '1.1'; and then in Employee.pm could you can say use Employee 1.1; And it would make sure that you have at least that version number or higher available. This is not the same as loading in that exact version number. No mechanism currently exists for concurrent installation of multiple versions of a module. Lamentably.
17 juin Package - PerlChapter 10. PackagesContents:In this chapter, we get to start having fun, because we get to start talking about software design. If we're going to talk about good software design, we have to talk about Laziness, Impatience, and Hubris, the basis of good software design. We've all fallen into the trap of using cut-and-paste when we should have defined a higher-level abstraction, if only just a loop or subroutine.[1] To be sure, some folks have gone to the opposite extreme of defining ever-growing mounds of higher-level abstractions when they should have used cut-and-paste.[2] Generally, though, most of us need to think about using more abstraction rather than less.
Caught somewhere in the middle are the people who have a balanced view of how much abstraction is good, but who jump the gun on writing their own abstractions when they should be reusing existing code.[3]
Whenever you're tempted to do any of these things, you need to sit back and think about what will do the most good for you and your neighbor over the long haul. If you're going to pour your creative energies into a lump of code, why not make the world a better place while you're at it? (Even if you're only aiming for the program to succeed, you need to make sure it fits the right ecological niche.) The first step toward ecologically sustainable programming is simply this: don't litter in the park. When you write a chunk of code, think about giving the code its own namespace, so that your variables and functions don't clobber anyone else's, or vice versa. A namespace is a bit like your home, where you're allowed to be as messy as you like, as long as you keep your external interface to other citizens moderately civil. In Perl, a namespace is called a package. Packages provide the fundamental building block upon which the higher-level concepts of modules and classes are constructed. Like the notion of "home", the notion of "package" is a bit nebulous. Packages are independent of files. You can have many packages in a single file, or a single package that spans several files, just as your home could be one small garret in a larger building (if you're a starving artist), or it could comprise several buildings (if your name happens to be Queen Elizabeth). But the usual size of a home is one building, and the usual size of a package is one file. Perl provides some special help for people who want to put one package in one file, as long as you're willing to give the file the same name as the package and use an extension of .pm, which is short for "perl module". The module is the fundamental unit of reusability in Perl. Indeed, the way you use a module is with the use command, which is a compiler directive that controls the importation of subroutines and variables from a module. Every example of use you've seen until now has been an example of module reuse. The Comprehensive Perl Archive Network, or CPAN, is where you should put your modules if other people might find them useful. Perl has thrived because of the willingness of programmers to share the fruits of their labor with the community. Naturally, CPAN is also where you can find modules that others have thoughtfully uploaded for everyone to use. See Chapter 22, "CPAN", and www.cpan.org for details. The trend over the last 25 years or so has been to design computer languages that enforce a state of paranoia. You're expected to program every module as if it were in a state of siege. Certainly there are some feudal cultures where this is appropriate, but not all cultures are like this. In Perl culture, for instance, you're expected to stay out of someone's home because you weren't invited in, not because there are bars on the windows.[4]
This is not a book about object-oriented methodology, and we're not here to convert you into a raving object-oriented zealot, even if you want to be converted. There are already plenty of books out there for that. Perl's philosophy of object-oriented design fits right in with Perl's philosophy of everything else: use object-oriented design where it makes sense, and avoid it where it doesn't. Your call. In OO-speak, every object belongs to a grouping called a class. In Perl, classes and packages and modules are all so closely related that novices can often think of them as being interchangeable. The typical class is implemented by a module that defines a package with the same name as the class. We'll explain all of this in the next few chapters. When you use a module, you benefit from direct software reuse. With classes, you benefit from indirect software reuse when one class uses another through inheritance. And with classes, you get something more: a clean interface to another namespace. Everything in a class is accessed indirectly, insulating the class from the outside world. As we mentioned in Chapter 8, "References", object-oriented programming in Perl is accomplished through references whose referents know which class they belong to. In fact, now that you know about references, you know almost everything difficult about objects. The rest of it just "lays under the fingers", as a pianist would say. You will need to practice a little, though. One of your basic finger exercises consists of learning how to protect different chunks of code from inadvertently tampering with each other's variables. Every chunk of code belongs to a particular package, which determines what variables and subroutines are available to it. As Perl encounters a chunk of code, it is compiled into what we call the current package. The initial current package is called "main", but you can switch the current package to another one at any time with the package declaration. The current package determines which symbol table is used to find your variables, subroutines, I/O handles, and formats. Any variable not declared with my is associated with a package--even seemingly omnipresent variables like $_ and %SIG. In fact, there's really no such thing as a global variable in Perl, just package variables. (Special identifiers like _ and SIG merely seem global because they default to the main package instead of the current one.) The scope of a package declaration is from the declaration itself through the end of the enclosing scope (block, file, or eval--whichever comes first) or until another package declaration at the same level, which supersedes the earlier one. (This is a common practice). All subsequent identifiers (including those declared with our, but not including those declared with my or those qualified with a different package name) will be placed in the symbol table belonging to the current package. (Variables declared with my are independent of packages; they are always visible within, and only within, their enclosing scope, regardless of any package declarations.) Typically, a package declaration will be the first statement of a file meant to be included by require or use. But again, that's by convention. You can put a package declaration anywhere you can put a statement. You could even put it at the end of a block, in which case it would have no effect whatsoever. You can switch into a package in more than one place; a package declaration merely selects the symbol table to be used by the compiler for the rest of that block. (This is how a given package can span more than one file.) You can refer to identifiers[5] in other packages by prefixing ("qualifying") the identifier with the package name and a double colon: $Package::Variable. If the package name is null, the main package is assumed. That is, $::sail is equivalent to $main::sail.[6]
The old package delimiter was a single quote, so in old Perl programs you'll see variables like $main'sail and $somepack'horse. But the double colon is now the preferred delimiter, in part because it's more readable to humans, and in part because it's more readable to emacs macros. It also makes C++ programmers feel like they know what's going on--as opposed to using the single quote as the separator, which was there to make Ada programmers feel like they knew what's going on. Because the old-fashioned syntax is still supported for backward compatibility, if you try to use a string like "This is $owner's house", you'll be accessing $owner::s; that is, the $s variable in package owner, which is probably not what you meant. Use braces to disambiguate, as in "This is ${owner}'s house". The double colon can be used to chain together identifiers in a package name: $Red::Blue::var. This means the $var belonging to the Red::Blue package. The Red::Blue package has nothing to do with any Red or Blue packages that might happen to exist. That is, a relationship between Red::Blue and Red or Blue may have meaning to the person writing or using the program, but it means nothing to Perl. (Well, other than the fact that, in the current implementation, the symbol table Red::Blue happens to be stored in the symbol table Red. But the Perl language makes no use of that directly.) For this reason, every package declaration must declare a complete package name. No package name ever assumes any kind of implied "prefix", even if (seemingly) declared within the scope of some other package declaration. Only identifiers (names starting with letters or an underscore) are stored in a package's symbol table. All other symbols are kept in the main package, including all the nonalphabetic variables, like $!, $?, and $_. In addition, when unqualified, the identifiers STDIN, STDOUT, STDERR, ARGV, ARGVOUT, ENV, INC, and SIG are forced to be in package main, even when used for other purposes than their built-in ones. Don't name your package m, s, y, tr, q, qq, qr, qw, or qx unless you're looking for a lot of trouble. For instance, you won't be able to use the qualified form of an identifier as a filehandle because it will be interpreted instead as a pattern match, a substitution, or a transliteration. Long ago, variables beginning with an underscore were forced into the main package, but we decided it was more useful for package writers to be able to use a leading underscore to indicate semi-private identifiers meant for internal use by that package only. (Truly private variables can be declared as file-scoped lexicals, but that works best when the package and module have a one-to-one relationship, which is common but not required.) The %SIG hash (which is for trapping signals; see Chapter 16, "Interprocess Communication") is also special. If you define a signal handler as a string, it's assumed to refer to a subroutine in the main package unless another package name is explicitly used. Use a fully qualified signal handler name if you want to specify a particular package, or avoid strings entirely by assigning a typeglob or a function reference instead: The notion of "current package" is both a compile-time and run-time concept. Most variable name lookups happen at compile time, but run-time lookups happen when symbolic references are dereferenced, and also when new bits of code are parsed under eval. In particular, when you eval a string, Perl knows which package the eval was invoked in and propagates that package inward when evaluating the string. (You can always switch to a different package inside the eval string, of course, since an eval string counts as a block, just like a file loaded in with do, require, or use.)
Alternatively, if an eval wants to find out what package it's in, the special symbol __PACKAGE__ contains the current package name. Since you can treat it as a string, you could use it in a symbolic reference to access a package variable. But if you were doing that, chances are you should have declared the variable with our instead so it could be accessed as if it were a lexical. 10.1. Symbol TablesThe contents of a package are collectively called a symbol table. Symbol tables are stored in a hash whose name is the same as the package, but with two colons appended. The main symbol table's name is thus %main::. Since main also happens to be the default package, Perl provides %:: as an abbreviation for %main::. Likewise, the symbol table for the Red::Blue package is named %Red::Blue::. As it happens, the main symbol table contains all other top-level symbol tables, including itself, so %Red::Blue:: is also %main::Red::Blue::. When we say that a symbol table "contains" another symbol table, we mean that it contains a reference to the other symbol table. Since main is the top-level package, it contains a reference to itself, with the result that %main:: is the same as %main::main::, and %main::main::main::, and so on, ad infinitum. It's important to check for this special case if you write code that traverses all symbol tables. Inside a symbol table's hash, each key/value pair matches a variable name to its value. The keys are the symbol identifiers, and the values are the corresponding typeglobs. So when you use the *NAME typeglob notation, you're really just accessing a value in the hash that holds the current package's symbol table. In fact, the following have (nearly) the same effect: The first is more efficient because the main symbol table is accessed at compile time. It will also create a new typeglob by that name if none previously exists, whereas the second form will not.
Since a package is a hash, you can look up the keys of the package and get to all the variables of the package. Since the values of the hash are typeglobs, you can dereference them in several ways. Try this: Since all packages are accessible (directly or indirectly) through the main package, you can write Perl code to visit every package variable in your program. The Perl debugger does precisely that when you ask it to dump all your variables with the V command. Note that if you do this, you won't see variables declared with my since those are independent of packages, although you will see variables declared with our. See Chapter 20, "The Perl Debugger".
Earlier we said that only identifiers are stored in packages other than main. That was a bit of a fib: you can use any string you want as the key in a symbol table hash--it's just that it wouldn't be valid Perl if you tried to use a non-identifier directly: Assignment to a typeglob performs an aliasing operation; that is,
causes variables, subroutines, formats, and file and directory handles accessible via the identifier richard to also be accessible via the symbol dick. If you want to alias only a particular variable or subroutine, assign a reference instead:*dick = *richard; That makes $richard and $dick the same variable, but leaves @richard and @dick as separate arrays. Tricky, eh?*dick = \$richard; This is how the Exporter works when importing symbols from one package to another. For example: imports the &richard function from package OtherPack into SomePack, making it available as the &dick function. (The Exporter module is described in the next chapter.) If you precede the assignment with a local, the aliasing will only last as long as the current dynamic scope.*SomePack::dick = \&OtherPack::richard; This mechanism may be used to retrieve a reference from a subroutine, making the referent available as the appropriate data type: Likewise, you can pass a reference into a subroutine and use it without dereferencing:
These are tricky ways to pass around references cheaply when you don't want to have to explicitly dereference them. Note that both techniques only work with package variables; they would not have worked had we declared %units with my.
Another use of symbol tables is for making "constant" scalars: Now you cannot alter $PI, which is probably a good thing, all in all. This isn't the same as a constant subroutine, which is optimized at compile time. A constant subroutine is one prototyped to take no arguments and to return a constant expression; see Section 10.4.1, "Inlining Constant Functions" in Chapter 6, "Subroutines", for details. The use constant pragma (see Chapter 31, "Pragmatic Modules") is a convenient shorthand:*PI = \3.14159265358979; Under the hood, this uses the subroutine slot of *PI, instead of the scalar slot used earlier. It's equivalent to the more compact (but less readable):use constant PI => 3.14159; That's a handy idiom to know anyway--assigning a sub {} to a typeglob is the way to give a name to an anonymous subroutine at run time.
Assigning a typeglob reference to another typeglob (*sym = \*oldvar) is the same as assigning the entire typeglob, because Perl automatically dereferences the typeglob reference for you. And when you set a typeglob to a simple string, you get the entire typeglob named by that string, because Perl looks up the string in the current symbol table. The following are all equivalent to one another, though the first two compute the symbol table entry at compile time, while the last two do so at run time: When you perform any of the following assignments, you're replacing just one of the references within the typeglob:
If you think about it sideways, the typeglob itself can be viewed as a kind of hash, with entries for the different variable types in it. In this case, the keys are fixed, since a typeglob can contain exactly one scalar, one array, one hash, and so on. But you can pull out the individual references, like this:*sym = \$frodo; *sym = \@sam; *sym = \%merry; *sym = \&pippin; You can say *foo{PACKAGE} and *foo{NAME} to find out what name and package the *foo symbol table entry comes from. This may be useful in a subroutine that is passed typeglobs as arguments:
This prints:
The *foo{THING} notation can be used to obtain references to individual elements of *foo. See the section Section 10.2.5, "Symbol Table References" in Chapter 8, "References" for details.You gave me main::foo You gave me bar::glarch This syntax is primarily used to get at the internal filehandle or directory handle reference, because the other internal references are already accessible in other ways. (The old *foo{FILEHANDLE} is still supported to mean *foo{IO}, but don't let its name fool you into thinking it can distinguish filehandles from directory handles.) But we thought we'd generalize it because it looks kind of pretty. Sort of. You probably don't need to remember all this unless you're planning to write another Perl debugger. Talking about PERL -- PackagesPackagesPerl provides a mechanism for alternate namespaces to protect packages from stomping on each others variables. By default, a perl script starts compiling into the package known as "main". By use of the package declaration, you can switch namespaces. The scope of the package declaration is from the declaration itself to the end of the enclosing block (the same scope as the local() operator). Typically it would be the first declaration in a file to be included by the "require" operator. You can switch into a package in more than one place; it merely influences which symbol table is used by the compiler for the rest of that block. You can refer to variables and filehandles in other packages by prefixing the identifier with the package name and a single quote. If the package name is null, the "main" package as assumed.Only identifiers starting with letters are stored in the packages symbol table. All other symbols are kept in package "main". In addition, the identifiers STDIN, STDOUT, STDERR, ARGV, ARGVOUT, ENV, INC and SIG are forced to be in package "main", even when used for other purposes than their built-in one. Note also that, if you have a package called "m", "s" or "y", the you can't use the qualified form of an identifier since it will be interpreted instead as a pattern match, a substitution or a translation. Eval'ed strings are compiled in the package in which the eval was compiled in. (Assignments to $SIG{}, however, assume the signal handler specified is in the main package. Qualify the signal handler name if you wish to have a signal handler in a package.) For an example, examine perldb.pl in the perl library. It initially switches to the DB package so that the debugger doesn't interfere with variables in the script you are trying to debug. At various points, however, it temporarily switches back to the main package to evaluate various expressions in the context of the main package. The symbol table for a package happens to be stored in the associative array of that name prepended with an underscore. The value in each entry of the associative array is what you are referring to when you use the *name notation. In fact, the following have the same effect (in package main, anyway), though the first is more efficient because it does the symbol table lookups at compile time: local(*foo) = *bar; local($_main{'foo'}) = $_main{'bar'};You can use this to print out all the variables in a package, for instance. Here is dumpvar.pl from the perl library: package dumpvar;
sub main'dumpvar {
($package) = @_;
local(*stab) = eval("*_$package");
while (($key,$val) = each(%stab)) {
{
local(*entry) = $val;
if (defined $entry) {
print "\$$key = '$entry'\n";
}
if (defined @entry) {
print "\@$key = (\n";
foreach $num ($[ .. $#entry) {
print " $num\t'",$entry[$num],"'\n";
}
print ")\n";
}
if ($key ne "_$package" && defined %entry) {
print "\%$key = (\n";
foreach $key (sort keys(%entry)) {
print " $key\t'",$entry{$key},"'\n";
}
print ")\n";
}
}
}
}
Note that, even though the subroutine is compiled in package dumpvar, the name of the subroutine is qualified so that its name is inserted 16 juin Talking about VHDL & Verilog Compared & Contrasted
VHDL & Verilog Compared & Contrasted
Douglas J. Smith |