Perl Tutorial
Fundamentals
Input and Output
Control Flow
Arrays and Lists
Hash
Scalars
Strings
Object Oriented Programming in Perl
Subroutines
Regular Expressions
File Handling
Context Sensitivity
CGI Programming
Misc
In many programming languages, parameters passed to functions or methods can be categorized as mutable or immutable. In simple terms:
In Perl, the distinction is a bit nuanced due to Perl's dynamic nature and its use of references. Let's delve into this concept within the context of Perl.
Scalar values in Perl (like numbers and strings) are passed by value to subroutines. This means the subroutine gets a copy of the value, and changes to this value inside the subroutine don't affect the original value outside.
sub modify_scalar { my ($val) = @_; $val += 10; print "Inside subroutine: $val\n"; } my $number = 5; modify_scalar($number); print "Outside subroutine: $number\n"; # Outputs: 5
If you pass an array or hash to a subroutine, you're actually passing a copy of the array or hash. However, if you pass a reference to the array or hash, changes made to the dereferenced array or hash inside the subroutine will affect the original array or hash outside.
sub modify_array { my ($arr_ref) = @_; push @$arr_ref, "new_item"; } my @array = ("item1", "item2"); modify_array(\@array); print "@array\n"; # Outputs: item1 item2 new_item
In Perl, while you can modify what a reference points to (i.e., the data it refers to), you can't change the reference itself inside a subroutine to point to something else.
sub try_modify_ref { my ($ref) = @_; $ref = [5, 6, 7]; # this won't affect the original reference } my $arr_ref = [1, 2, 3]; try_modify_ref($arr_ref); print "@$arr_ref\n"; # Outputs: 1 2 3
When you want to avoid side effects (i.e., changes inside the subroutine affecting data outside), pass scalar values or use references and then clone the data inside the subroutine. The Clone
module can be helpful for this purpose.
If you want changes to persist outside the subroutine, use references and make your intention clear in the code and documentation.
readonly
ModuleIf you want to ensure that certain values are immutable, you can use the readonly
module:
use Readonly; Readonly my $immutable_scalar => 42; $immutable_scalar = 43; # This will throw an error
In Perl, whether a parameter is mutable or immutable depends on how you pass it (value or reference) and how you handle it in your subroutine. Being aware of this distinction is crucial for writing predictable and bug-free code.
Passing mutable parameters in Perl:
sub increment { my ($num) = @_; $num++; print "Inside subroutine: $num\n"; } my $value = 5; increment($value); print "Outside subroutine: $value\n";
Immutable variables in Perl functions:
sub increment_immutable { my ($num) = @_; $num++; print "Inside subroutine: $num\n"; return $num; } my $value = 5; $value = increment_immutable($value); print "Outside subroutine: $value\n";
Perl subroutine parameter mutability:
sub modify { my ($var) = @_; $var = "Modified"; print "Inside subroutine: $var\n"; } my $data = "Original"; modify($data); print "Outside subroutine: $data\n";
Using references for mutable parameters in Perl:
sub increment_by_ref { my ($num_ref) = @_; $$num_ref++; print "Inside subroutine: $$num_ref\n"; } my $value = 5; increment_by_ref(\$value); print "Outside subroutine: $value\n";
Avoiding side effects with immutable parameters in Perl:
sub modify_immutable { my ($var) = @_; $var = "Modified"; print "Inside subroutine: $var\n"; return $var; } my $data = "Original"; my $result = modify_immutable($data); print "Outside subroutine: $data\n";
Perl scalar mutability:
sub modify_scalar { my ($scalar) = @_; $scalar = "Modified"; print "Inside subroutine: $scalar\n"; } my $text = "Original"; modify_scalar($text); print "Outside subroutine: $text\n";
Mutable and immutable data structures in Perl:
# Mutable array my @mutable_array = (1, 2, 3); push @mutable_array, 4; # Immutable array my @immutable_array = (1, 2, 3); my @new_array = (@immutable_array, 4);
Pass-by-reference in Perl:
sub modify_array { my ($array_ref) = @_; push @$array_ref, 4; } my @data = (1, 2, 3); modify_array(\@data);