Perl Module(s) Of The Week - 2019 Week 10 - Mojo::Util

Yogi Betta once said "you can observe a lot just by watching".

I somehow agree with that statement, in a way, to a certain extend.

And one amusing thing I noticed among startups or local meetups here in MY, their web tech stack is always chasing the latest greatest in the industry. Fair enough, who don't like new shinny stuff? It does make you feels at the forefront of the industry and it looks good on your resume as well. Or maybe because we have to keep learning in a rapid changing industry? Or maybe we just fear of missing out?

The funny thing is, as I observed, poking fun at PHP is a common theme here. PHP is seen like a second class programming language and it's a sin to use PHP in a web stack these days. Ironically, most of their front facing website or landing page is hosted in LAMP stack and powered by Wordpress. Which some of them admitted themselves, should have been done in a system of their own chosen and favorite latest greatest web programming language. This is doable but the financial cost of hiring a freelancer to design and setup a professional looking website far outweigh the former choice. 

The thing is, PHP these days, PHP 7 to be exact, have move from the "Visual Basic" of the web to the "Java" of the web. Gone are the days where you would hack a site with tremendous amount of global utility functions. These days, it's more mature, with a standard packaging system, numerous web frameworks, and a more Object-Oriented (OO) and types support. Yes, you still can use back all the global helper functions like you used to.

Why all these discussions about PHP? Well, this is related to the Perl module we're reviewing this week, Mojo::Util, a module that contains a bunch of portable utility functions. These functions is not the same as global helper functions. According to C2 wiki, helper functions are:
"Functions that do not aid code reusability are helper functions; their sole purpose is to "help" a single function by cleaning the code and making the logic clearer."
As usual, the installation.
$ cpanm Mojo::Util

Let's try using some of the helper functions from the module. Example code using Punycode, a representation of Unicode characters in ASCII characters used in domain names, as shown below.
# punycode.pl
use diagnostics; # To display details of any warnings.
use strict;
use warnings;
use utf8; # Since we've Chinese characters, ensure the file is UTF8.
use feature qw ( say );
use Mojo::Util qw ( punycode_decode punycode_encode );

# Ensure our standard output is UTF8 since we're printing UTF8 characters.
# Otherwise we will encounter "Wide character in say at punycode.pl line 14."
# error.
binmode STDOUT, ':utf8';

my $string = qq|百度|;
my $punycode = punycode_encode $string;

say $punycode;
say punycode_decode $punycode;

# Expected output
$ perl punycode.pl    
wxtr44c
百度

Mojo::Utils contains a list of alias functions that reduce complexity of the code. Some of these are aliases to other modules. For example, these MD5 helper functions which reduce unnecessary typing of the fully qualified names.
sub md5_bytes { Digest::MD5::md5(@_) }
sub md5_sum   { Digest::MD5::md5_hex(@_) }

As mentioned earlier, utility functions is not the same as helper functions. As shown below, the `_unescape` helper function is used once for `html_escape` utility function.
# Helper for html_unescape
sub _unescape {
  if ($_[0]) {
    return chr hex $_[0] if substr($_[0], 0, 1) eq 'x';
    return chr $_[0];
  }
  return exists $ENTITIES{$_[1]} ? chr $ENTITIES{$_[1]} : "&$_[1];";
}

While going through the code, I've found some interesting and funny The Simpsons quotes. The quotes and the relevant codes are pretty much self-explanatory.

(1) "Bart, stop pestering Satan!".
# "Bart, stop pestering Satan!"
our @EXPORT_OK = qw/b64_decode b64_encode camelize decamelize decode encode/;
push @EXPORT_OK, qw/get_line hmac_md5_sum hmac_sha1_sum html_escape/;
push @EXPORT_OK, qw/html_unescape md5_bytes md5_sum punycode_decode/;
push @EXPORT_OK, qw/punycode_encode qp_decode qp_encode quote/;
push @EXPORT_OK, qw/secure_compare sha1_bytes sha1_sum trim unquote/;
push @EXPORT_OK, qw/url_escape url_unescape xml_escape/;

(2) "Daddy, I'm scared. Too scared to even wet my pants. Just relax and it'll come, son."
# "Daddy, I'm scared. Too scared to even wet my pants.
#  Just relax and it'll come, son."
sub html_unescape {
  my $string = shift;
  $string =~ s/
    &
    (?:
      \#
      (
        (?:
          \d{1,7}             # Number
          |
          x[0-9A-Fa-f]{1,6}   # Hex
        )
      )
      |
      ([A-Za-z]{1,8})         # Name
    )
    ;
  /_unescape($1, $2)/gex;
  return $string;
}

No comments:

Post a Comment