in reply to Closure producing 'Modification of read-only value' error

You can avoid modifying $_ within the sub, by doing the initialization of $hash_ref in a BEGIN block:

{ my $hash_ref; BEGIN { while (<DATA>){ chomp; my ($str, $num) = split /\|/; $hash_ref->{$str} = $num; } } sub get_number{ my ($num) = @_; return $hash_ref->{$num}; } }
As a small bonus, the sub doesn't need to perform a test that would have been true only once.

Update: In light of hv's comments below, I conclude that, in this case at least, saving the while (<DATA>) is not worth all the fuss and worry over $_. Hence in the revision below, the loop does not use $_.

{ my $hash_ref; BEGIN { while (defined (my $line = <DATA>)){ chomp $line; my ($str, $num) = split /\|/, $line; $hash_ref->{$str} = $num; } } sub get_number{ my ($num) = @_; return $hash_ref->{$num}; } }

the lowliest monk

Replies are listed 'Best First'.
Re^2: Closure producing 'Modification of read-only value' error
by hv (Prior) on Jun 11, 2005 at 11:49 UTC

    You can avoid modifying $_ within the sub, by doing the initialization of $hash_ref in a BEGIN block

    Of course that doesn't avoid modifying $_, just moves the modification to BEGIN time - if this ends up in a module, for example, it will instead corrupt the caller's $_ at the point they require This::Module, which is much nastier (and usually pretty hard for the caller to debug).

    I'd recommend always localising the scope of any changes to $_, with either a local $_ or a local *_ as appropriate.

    Hugo