# Now let's use an array slice instead of a hash my @rot = do { my $c; map { $c = chr($_); exists $rot{$c} ? ord($rot{$c}) : $_ } 0 .. 255; }; rot13sub "arrayslice", sub { pack "C*", @rot[unpack("C*", $_[0])]; }; # Now let's try some solutions with s, as demerphq has suggested. # The first one has to know the exact character range to be replaced. rot13sub "gsub-class", sub { (my $s = $_[0]) =~ s/([a-zA-Z])/$rot{$1}/g; $s; }; rot13sub "gsub-dot", sub { (my $s = $_[0]) =~ s/(.)/$rotd{$1}/gs; $s; }; # Now your tr equivalent rot13sub "tr", sub { (my $s = shift) =~ tr/a-zA-Z/n-za-mN-ZA-M/; $s; };