Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Best Practice for replace sub

by Skeeve (Vicar)
on Mar 01, 2013 at 09:59 UTC ( #1021213=perlquestion: print w/ replies, xml ) Need Help??
Skeeve has asked for the wisdom of the Perl Monks concerning the following question:

Hi

I often find myself writing code like this:

# Encoding stuff#################################### my %ENCODE=( '"' => '&quot;', '&' => '&amp;', '<' => '&lt;', '>' => '&gt;', map((chr($_), "&#$_;"), (0..31)), ); my $ENCODE= join('', keys %ENCODE); $ENCODE= qr/([${ENCODE}])/; sub encode { my($text)= @_; return '' unless defined $text; $text=~ s/$ENCODE/$ENCODE{$1}/g; return $text; } ####################################################

Note: Please don't tell me about moduls being able to do exactly this encoding/replacements as this is just an example for several tasks where I need to replace substrings with other strings.

My bad feeling about this is: I'm using kind of global variables which I initialize once because I simply don't want to assign the hash (%ENCODE) and the accompanying scalar ($ENCODE) each time the encode($string) is invoked. So they need to be on global level. But it does not "feel right".

What's your proposal against this? Or what's your view on this?


s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
+.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e

Comment on Best Practice for replace sub
Select or Download Code
Re: Best Practice for replace sub
by tmharish (Friar) on Mar 01, 2013 at 10:11 UTC
Re: Best Practice for replace sub
by tobyink (Abbot) on Mar 01, 2013 at 12:17 UTC

    Perl 5.10 and above have state variables, but they don't work for hashes and arrays - just scalars. Still, you can use hashrefs/arrayrefs.

    sub encode { state $lookup = { '"' => '&quot;', '&' => '&amp;', '<' => '&lt;', '>' => '&gt;', map((chr($_), "&#$_;"), (0..31)), }; state $re = do { my $tmp = join('', keys %$lookup); qr/([$tmp])/ } +; my ($text) = @_; return '' unless defined $text; $text =~ s/$re/$lookup->{$1}/g; return $text; }

    If you need to support older versions of Perl, then curly braces can be used to limit the scope of lexical variables...

    { my $lookup = { '"' => '&quot;', '&' => '&amp;', '<' => '&lt;', '>' => '&gt;', map((chr($_), "&#$_;"), (0..31)), }; my $re = do { my $tmp = join('', keys %$lookup); qr/([$tmp])/ }; sub encode { my ($text) = @_; return '' unless defined $text; $text =~ s/$re/$lookup->{$1}/g; return $text; } }

    Or even better (because it delays populating the variables until they're needed):

    { my ($lookup, $re); sub encode { $lookup ||= { '"' => '&quot;', '&' => '&amp;', '<' => '&lt;', '>' => '&gt;', map((chr($_), "&#$_;"), (0..31)), }; $re ||= do { my $tmp = join('', keys %$lookup); qr/([$tmp])/ } +; my ($text) = @_; return '' unless defined $text; $text =~ s/$re/$lookup->{$1}/g; return $text; } }
    package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
Re: Best Practice for replace sub
by Anonymous Monk on Mar 01, 2013 at 16:05 UTC
    I'd put the encoding-work in a subroutine and give no further thought to initializing and tearing-down the variable. Unless you are truly doing this millions of times such that you can clearly demonstrate that there's a problem to be solved here, you have no problem. The code should be clear and well tested and easily changed, with low chances of compromising some other part of the system by doing so. This to me is an argument against "globals."

      In HTML::HTML5::Entities I've got a hash with 2231 entries. It would be wasteful in the extreme to rebuild that hash every time the encode_entities function is called.

      Closing over a lexical variable is a perfectly safe thing to do.

      (As it happens, I use a package variable for HTML::Entities because that's what HTML::Entities does, and the aim is to provide a compatible API.)

      package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1021213]
Approved by marto
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (13)
As of 2014-08-01 09:17 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (257 votes), past polls