Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
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

Replies are listed 'Best First'.
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 tmharish (Friar) on Mar 01, 2013 at 10:11 UTC
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?
[karlgoethebier]: shmem: yes - i f you manage it to get on the bike. and pray if you must stop...
[shmem]: in the french alpes, at the end of a gravel road, we had a beer at a hut - and heard an enduro coming up.
[shmem]: not by the road, but from there below where you wouldn't want to walk.
[shmem]: the biker stopped the machine at the table and took off his helmet.
[shmem]: long white hair, long beard the same, then he proceeded to get off the bike
[shmem]: saying "biking itself isn't that much, but getting up and down - hell!"
[shmem]: up and down: on and off the bike, of course

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (7)
As of 2017-06-25 20:10 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    How many monitors do you use while coding?















    Results (570 votes). Check out past polls.