Professional Perl | 21
[previous] |
Professional Perl
Assignable Subroutines
Some of Perl's built-in functions allow us to assign to them as well as use them in expressions. In programming parlance, the result of the function is an lvalue, or a value that can appear on the left hand side of an assignment. The most common and obvious lvalues are variables, which we assign to all the time:
$scalar_value = "value";
Some Perl functions can also be assigned to in this way, for example the substr function:
$mystring = "this is some text";
substr ($mystring, 0, 7) = "Replaced";
print $mystring; # produces "Replaced some text";
The substr function returns part of a string. If the string happens to be held in a variable then this returned string segment is an lvalue, and can be assigned to. Perl does not even require that the new text be the same length, as the above example illustrates. It would be wonderful to be able to do this kind of thing in our own subroutines.
In fact, Perl does allow us to this, albeit only experimentally at the moment. Assignable subroutines make use of subroutine attributes (an experimental feature of Perl in version 5.6). Since attributes are likely to evolve, or possibly even disappear entirely, this technique is not guaranteed to work and should be avoided for production code. However, for the moment, to make a subroutine assignable we can use the special attribute lvalue, as this simple assignable subroutine script demonstrates:
#!/usr/bin/perl
# assignable.pl
use warnings;
use strict;
my $scalar = "Original String";
sub assignablesub : lvalue {
$scalar;
}
print $scalar, "\n";
assignablesub = "Replacement String";
print $scalar, "\n";
In order for an assignable subroutine to function correctly, it must return a variable. In addition, it must not use return, because with an assignable subroutine data can pass in as well as out. Currently (as of Perl 5.6) only scalar values may be used as assignable return values. This includes an array element or hash value, however. Future versions of Perl are expected to lift this restriction.
Attributes do not preclude prototypes. If we want to specify a prototype, we can do so after the subroutine, before any attributes. The following example shows a prototyped assignable subroutine that provides an example of assigning to an array via the returned lvalue.
my @array = (1, 2, 3);
sub set_element (\@$) : lvalue {
@{$_[0]} [$_[1]]; # return element of passed array
# @{$_[0]} is the array
# [$_[1]] is the $_[1]th element of that array
}
set_element (@array, 2) = 5;
In itself this is not a particularly useful example, of course, but it may lead to some interesting possibilities.
[previous] |
Created: April 18, 2001
Revised: April 18, 2001