[ Perl tips index]
[ Subscribe to Perl tips ]
In our last Perl tip, we discussed the hash locking functions available in Hash::Util. This week we'll look at some of the very useful functions available in another one of Perl's standard modules, Scalar::Util.
Perl only cleans up memory once its reference count has dropped to zero. The reference count is the number of variables which link to that location. This is illustrated in the following example:
my $a = "string"; # $a's memory location has 1 reference
my $b = \$a; # $a's memory location has 2 references
{
my $c = \$a; # now 3 references
}
# $c has gone out of scope, so back to 2 references
$b = 0; # now back to 1 reference.
This means that reference loops can result in memory being kept even after the variables have gone out of scope and the memory can no longer be reached. This is called "memory leakage". The following code is a very simple example of this:
{
my $a;
my $b = \$a;
$a = \$b;
}
# $a and $b are out of scope, but the memory cannot be
# cleaned up
Circular, referential structures often occur in complex situations. Consider an object oriented game of chess. The individual chess pieces need access to the chess board. In return, the board needs to know where each chess piece is. It is difficult to resolve this problem without circular references while still ensuring data encapsulation and no data duplication.
Fortunately, since version 5.6.0, Perl has had a concept of weak references. A weak reference does not cause a reference count to be held on the object it references. Thus, when the reference count reaches 0, the memory is cleaned up and the reference is set to undef.
To weaken a reference, we use Scalar::Util's weaken():
use Scalar::Util qw/weaken/;
my $a;
{
my $b = "some very big thing";
$a = \$b;
weaken($a); # Make $a a weak reference
}
# $b has gone out of scope, since $a was a weak reference
# $b can now be cleaned up and $a is set to undef
If we want to know if a reference has already been weakened or not, we can use isweak():
unless( isweak($a) ) {
weaken($a);
}
If you've ever thought that ref() could be a little bit more helpful, then you might be interested in blessed() and reftype() in the Scalar::Util module.
Perl's inbuilt ref() returns a true value if its argument is a reference. This true value is either the underlying type of the reference (SCALAR, ARRAY, HASH ...) or the name of a class, in the case of an object.
Scalar::Util's blessed() returns a true value if its argument is a blessed reference (ie a Perl object). This true value is the name of the class the reference is blessed into.
Scalar::Util's reftype() returns a true value if its argument is a reference, but always returns the type of the variable referenced. Thus both hash references and references to objects based on hashes returns HASH.
Thus, if you want to find out:
* Is this a reference of any kind? Use ref()
* Is this an object? Use blessed()
* What is underneath? Use reftype()
use Scalar::Util qw/blessed reftype/;
my $scalar;
ref($scalar); # undef
blessed($scalar); # undef
reftype($scalar); # undef
my $hashref = {};
ref($hashref); # HASH
blessed($hashref); # undef
reftype($hashref); # HASH
my $obj = bless $hashref, "Foo";
ref($obj); # Foo
blessed($obj); # Foo
reftype($obj); # HASH
Perl's error variable $! returns different values in numerical contexts and string contexts. When used numerically $! returns the C "errno" value and when used in a string context it returns the associated error string. For example:
| numerical | string |
|---|---|
| 1 | Operation not permitted |
| 2 | No such file or directory |
| 3 | No such process |
Sometimes it would be handy to be able to duplicate this effect in our own error variables. An example is when we're working with the HTTP protocol, we may wish a variable to return '404' as a number, but "page not found" as a string. We may wish We can do this by using Scalar::Util's dualvar():
use Scalar::Util qw/dualvar/;
my $response = dualvar 404, "Page not found."
There are many other good subroutines provided by Scalar::Util, such as tainted() which enables the programmer to determine if a variable contains tainted data, and readonly() which returns true if is argument is readonly (for example a literal string).
We invite you to refer to the documentation to Scalar::Util to find out more about these functions.
[ Perl tips index ]
[ Subscribe to Perl tips ]
| Location | Course | Course Date | Duration | Early Bird Date |
|---|---|---|---|---|
| Melbourne | Programming Perl | Tue 2 Sep 2008 | 4 days | Mon 4 Aug 2008 |
| Sydney | Programming Perl | Tue 7 Oct 2008 | 4 days | Mon 8 Sep 2008 |
| Canberra | Programming Perl | Mon 24 Nov 2008 | 4 days | Mon 27 Oct 2008 |
For future dates, please see our training calendar.
This Perl tip and associated text is copyright Perl Training Australia. You may freely distribute this text so long as it is distributed in full with this Copyright noticed attached.
If you have any questions please don't hesitate to contact us:
| Email: | contact@perltraining.com.au |
| Phone: | 03 9354 6001 (Australia) |
| International: | +61 3 9354 6001 |
Copyright 2001-2008 Perl Training Australia. Contact us at contact@perltraining.com.au