{ # use a closure to make a private memory for sub. my %escapes; sub uri_escape { my($text) = @_; # the first time the sub is called %escapes is undef # so we build a char->hex map. because we use a closure # %escapes survives from one calling of this function # to the next so we only map this once %escapes || do{ $escapes{chr $_} = sprintf("%%%02X", $_) for 0..255 }; return undef unless defined $text; $text =~ s/([^A-Za-z0-9\-_.!~*'()])/$escapes{$1}/g; return $text; } }