I have a function to convert documents into different formats, which then calls another function based on the type document. It's pretty straight forward for everything aside from HTML documents which require a bit of cleaning up, and that cleaning up is different based on where it's come from. So I had the idea that I could pass a reference to a subroutine to the convert function so the caller has the opportunity to modify the HTML, kinda like so (I'm not at work so this isn't copy-and-pasted):
package Converter;
...
sub convert
{
my ($self, $filename, $coderef) = @_;
if ($filename =~ /html?$/i) {
$self->_convert_html($filename, $coderef);
}
}
sub _convert_html
{
my ($self, $filename, $coderef) = @_;
my $html = $self->slurp($filename);
$coderef->(\$html); #this modifies the html
$self->save_to_file($filename, $html);
}
which is then called by:
Converter->new->convert("./whatever.html", sub { s/<html>/<xml>/i });
I've tried a couple of different things along these lines but I keep on getting 'Use of uninitialized value in substitution (s///)'. Is there any way of doing what I'm trying to do?
Thanks
If it were me, I would avoid modifying the scalar ref and just return the changed value:
sub _convert_html
{
my ($self, $filename, $coderef) = @_;
my $html = $self->slurp($filename);
$html = $coderef->( $html ); #this modifies the html
$self->save_to_file($filename, $html);
}
However, if you want to modify a sub's arguments, it is worth knowing that all sub arguments are pass-by-reference in Perl (the elements of @_
are aliased to the arguments of the sub call). So your conversion sub can look like:
sub { $_[0] =~ s/<html>/<xml>/ }
But if you really want to operate on $_
, like you have in your desired code example, you need to make _convert_html()
look like:
sub _convert_html
{
my ($self, $filename, $coderef) = @_;
my $html = $self->slurp($filename);
$coderef->() for $html;
$self->save_to_file($filename, $html);
}
The for
is an easy way to properly localize $_
. You can also do:
sub _convert_html
{
my ($self, $filename, $coderef) = @_;
local $_ = $self->slurp($filename);
$coderef->();
$self->save_to_file($filename, $_);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With