Tag: CPAN

  • Perl can escape the Lisp Curse

    Perl can escape the Lisp Curse

    Ten years ago Rudolf Winestock wrote The Lisp Curse,an essay that ​“attempt[ed] to rec­on­cile the pow­er of the Lisp pro­gram­ming lan­guagewith the inabil­i­ty of the Lisp com­mu­ni­ty to repro­duce their pre-AI Winterachievements.”

    His con­clu­sion? The pow­er and expres­sive­nessof Lisp have con­spired to keep its devel­op­ers indi­vid­u­al­ly pro­duc­tive, but col­lec­tive­ly unable to orga­nize their workinto com­plete, stan­dard­ized, well-​documented, ‑test­ed, and ‑main­tained pack­ages that they could coa­lesce into inter­op­er­a­ble and widely-​adopted solu­tions. Everything from object sys­tems to types to asyn­chro­nous non-​blocking pro­gram­ming and con­cur­ren­cy is up for grabs and has mul­ti­ple com­pet­ing implementations.

    These social effects have doomed Lisp to also-​ran sta­tusin an indus­try where ​“employ­ers much pre­fer that work­ers be fun­gi­ble, rather than max­i­mal­ly pro­duc­tive.” Free tool­ing sup­port has lagged; although Emacscan be hacked end­less­ly to do any­thing, there is no out-​of-​the-​box inte­grat­ed devel­op­ment envi­ron­ment or batteries-​included defaults to imme­di­ate­ly ease new pro­gram­mers into their job.

    Does this all sound famil­iar to Perl developers?

    Perl is renowned for its expres­sive capa­bil­i­ties, enshrined in the TIMTOWTDI(There Is More Than One Way To Do It) design prin­ci­ple. Stories abound of the pro­duc­tiv­i­ty achieved by Perl pro­gram­mers stitch­ing togeth­er mod­ules from CPANwith their own code. Select an object sys­tem(or don’t), maybe throw in an excep­tion han­dler(or don’t), and you too can have a code­base that fel­low devel­op­ers cri­tique for not fol­low­ing their favored tech­niques. Meanwhile, man­agers are strug­gling to fill the rest of the teamwith new pro­gram­mers look­ing for IDE sup­port and find­ing only a grab-​bag of Vimextensions.

    But there’s hope.

    Perl has start­ed incor­po­rat­ing fea­turesexpect­ed of mod­ern pro­gram­ming lan­guagesinto its core while mak­ing roomfor fur­ther exper­i­men­ta­tion via CPAN. The Language Server Protocol(from Microsoft of all places!) has enabled Perl IDE fea­turesin text edi­tors to boost pro­duc­tiv­i­ty for new and expe­ri­enced devel­op­ersalike. And there’s a pilot Request For Comment processfor fur­ther improvements.

    These efforts point to a future where Perl’s expres­sive strength is mar­ried with sen­si­ble defaults and fea­tures with­out break­ing back­ward com­pat­i­bil­i­ty. Maybe the curse can be overcome.

  • A list of Perl list processing modules

    A list of Perl list processing modules

    As pre­vi­ous­ly writ­ten, I like list pro­cess­ing. Many com­put­ing prob­lems can be bro­ken down into trans­form­ing and fil­ter­ing lists, and Perl has got the fun­da­men­tals cov­eredwith func­tions like map, grep, and sort. There is so much more you might want to do, though, and CPANhas a pletho­ra of list and array pro­cess­ing modules.

    However, due to the vicis­si­tudes of Perl mod­ule main­te­nance, we have a sit­u­a­tion where it’s not clear at a glance where to turn when you’ve got a list that needs pro­cess­ing. So here’s anoth­er list: the list mod­ules of CPAN. Click through to dis­cov­er what func­tions they provide.

    • We’ve got List::Utilwhich has been released as part of Perl since ver­sion 5.7.3.
    • We’ve got List::MoreUtilswhich has some func­tions which are named the same as Util but behave differently.
    • We’ve got List::SomeUtilswhich dupli­cates MoreUtils but with few­er dependencies.
    • We’ve got List::UtilsBywhich MoreUtils has also cribbed some func­tions from.
    • We’ve got List::AllUtilswhich attempts to con­sol­i­date Util, SomeUtils, and ListBy but has some excep­tions to called mod­ules because of the afore­men­tioned dupli­ca­tion between Util and SomeUtils.
    • We’ve got List::Util::MaybeXSwhich helps with pure Perl fall­backs in case your ver­sion of Util is too old to have a cer­tain function.
    • We’ve got List::MoreUtils::XSwhich pro­vides (some?) faster ver­sions of MoreUtils’ func­tions (but you still have to useMoreUtils).
    • And last­ly, we have Util::Anywhich lets you import func­tions from Util, MoreUtils, and just for good mea­sure Scalar::Util, Hash::Util, String::Util, String::CamelCase, List::Pairwise, and Data::Dumper. But it has­n’t been updat­ed since 2016, so it does­n’t nec­es­sar­i­ly export the func­tions added to those mod­ules since then.

    Am I miss­ing any­thing? Probably!But these are the ones most asso­ci­at­ed with being upstream on the CPAN River, so they (or the mod­ules they con­sol­i­date) have more projects depend­ing on them.

  • Avoid CPAN conflicts in your personal Perl modules

    Avoid CPAN conflicts in your personal Perl modules

    If you’re writ­ing Perl that’s nev­er going to the Comprehensive Perl Archive Network (CPAN), heed this little-​known noteon the Perl Authors Upload Server (PAUSE):

    By con­ven­tion, the top-​level Localname­space should nev­er con­flict with any­thing on CPAN. This allows you to be con­fi­dent that the name you choose under Localisn’t going to con­flict with any­thing from the out­side world.

    PAUSE: On The Naming of Modules

    So, Local::MyModule, Local::App::MyApp, what­ev­er. This is also good advice for bespoke appli­ca­tions and libraries(the so-​called DarkPAN) you’re devel­op­ing in-​house. The last thing you need is to acci­den­tal­ly bring in (per­haps via depen­den­cies) a mod­ule that gets loaded instead of yours.

  • Perl and XML in 2021: A few lessons learned

    Perl and XML in 2021: A few lessons learned

    It’s been years since I’ve had to hack on any­thing XML-relat­ed, but a recent project at work has me once again jump­ing into the waters of gen­er­at­ing, pars­ing, and mod­i­fy­ing this 90s-​era doc­u­ment for­mat. Most devel­op­ers these days like­ly only know of it as part of the curiously-​named XMLHTTPRequestobject in web browsers used to retrieve data in JSONfor­mat from servers, and as the ​“X” in AJAX. But here we are in 2021, and there are still plen­ty of APIs and doc­u­ments using XML to get their work done.

    In my par­tic­u­lar case, the task is to update the API calls for a new ver­sion of Virtuozzo Automator. Its API is a bit unusu­al in that it does­n’t use HTTP, but rather relies on open­ing a TLS-encrypt­ed sock­et to the serv­er and exchang­ing doc­u­ments delim­it­ed with a null char­ac­ter. The pre­vi­ous ver­sion of our code is in 1990s-​sysadmin-​style Perl, with man­u­al blessing of objects and pars­ing the XML using reg­u­lar expres­sions. I’ve decid­ed to update it to use the Mooobject sys­tem and a prop­er XML pars­er. But which pars­er and mod­ule to use?

    Selecting a parser

    There are sev­er­al gener­ic XML mod­ulesfor pars­ing and gen­er­at­ing XML on CPAN, each with its own advan­tages and dis­ad­van­tages. I’d like to say that I did a com­pre­hen­sive sur­vey of each of them, but this project is pressed for time (aren’t they all?)and I did­n’t want to cre­ate too many extra depen­den­cies in our Perl stack. Luckily, XML::LibXMLis already avail­able, I’ve had some pre­vi­ous expe­ri­ence with it, and it’s a good choice for per­for­mant standards-​based XML pars­ing (using either DOMor SAX) and generation.

    Given more time and lee­way in adding depen­den­cies, I might use some­thing else. If the Virtuozzo API had an XML Schemaor used SOAP, I would con­sid­er XML::Compileas I’ve had some suc­cess with that in oth­er projects. But even that uses XML::LibXML under the hood, so I’d still be using that. Your mileage may vary.

    Generating XML

    Depending on the size and com­plex­i­ty of the XML doc­u­ments to gen­er­ate, you might choose to build them up node by node using XML::LibXML::Nodeand XML::LibXML::Elementobjects. Most of the mes­sages I’m send­ing to Virtuozzo Automator are short and have easily-​interpolated val­ues, so I’m using here-​documentislands of XML inside my Perl code. This also has the advan­tage of being eas­i­ly val­i­dat­ed against the exam­ples in the documentation.

    Where the inter­po­lat­ed val­ues in the mes­sages are a lit­tle com­pli­cat­ed, I’m using this idiominside the here-docs:

    @{[ ... ]}

    This allows me to put an arbi­trary expres­sion in the … part, which is then put into an anony­mous array ref­er­ence, which is then imme­di­ate­ly deref­er­enced into its string result. It’s a cheap and cheer­ful way to do min­i­mal tem­plat­ing inside Perl strings with­out load­ing a full tem­plat­ing library; I’ve also had suc­cess using this tech­nique when gen­er­at­ing SQLfor data­base queries.

    Parser as an object attribute

    Rather than instan­ti­ate a new XML::LibXMLin every method that needs to parse a doc­u­ment, I cre­at­ed a pri­vate attribute:

    package Local::API::Virtozzo::Agent {
        use Moo;
        use XML::LibXML;
        use Types::Standard qw(InstanceOf);
        ...
        has _parser => (
            is      => 'ro',
            isa     => InstanceOf['XML::LibXML'],
            default => sub { XML::LibXML->new() },
        );
        sub foo {
            my $self = shift;
            my $send_doc = $self->_parser
              ->parse_string(<<"END_XML");
                <foo/>
    END_XML
            ...
        }
    ...
    }

    Boilerplate

    XML doc­u­ments can be ver­bose, with ele­ments that rarely change in every doc­u­ment. In the Virtuozzo API’s case, every doc­u­ment has a <packet>ele­ment con­tain­ing a versionattribute and an idattribute to match requests to respons­es. I wrote a sim­ple func­tion to wrap my doc­u­ments in this ele­ment that pulled the ver­sion from a con­stant and always increased the idby one every time it’s called:

    sub _wrap_packet {
        state $send_id = 1;
        return qq(<packet version="$PACKET_VERSION" id=")
          . $send_id++ . '">' . shift . '</packet>';
    }

    If I need to add more attrib­ut­es to the <packet>ele­ment (for instance, name­spaces for attrib­ut­es in enclosed ele­ments, I can always use XML::LibXML::Element::setAttributeafter pars­ing the doc­u­ment string.

    Parsing responses with XPath

    Rather than using brit­tle reg­u­lar expres­sions to extract data from the response, I use the shared pars­er object from above and then the full pow­er of XPath:

    use English;
    ...
    sub get_sampleID {
        my ($self, $sample_name) = @_;
        ...
        # used to separate documents
        local $INPUT_RECORD_SEPARATOR = "\0";
        # $self->_sock is the IO::Socket::SSL connection
        my $get_doc = $self->_parser( parse_string(
          $self->_sock->getline(),
        ) );
        my $sample_id = $get_doc->findvalue(
            qq(//ns3:id[following-sibling::ns3:name="$sample_name"]),
        );
        return $sample_id;
    }

    This way, even if the order of ele­ments change or more ele­ments are intro­duced, the XPath pat­terns will con­tin­ue to find the right data.

    Conclusion… so far

    I’m only about halfway through updat­ing these API calls, and I’ve left out some non-​XML-​related details such as set­ting up the TLS sock­et con­nec­tion. Hopefully this arti­cle has giv­en you a taste of what’s involved in XML pro­cess­ing these days. Please leave me a com­ment if you have any sug­ges­tions or questions.