Category: Programming

  • Lightweight object-​oriented Perl scripts: From modulinos to moodulinos

    Lightweight object-​oriented Perl scripts: From modulinos to moodulinos

    Last week I found myself devel­op­ing a Perl script to cat­a­log some infor­ma­tion for our qual­i­ty assur­ance team. Unfortunately, as these things some­times do, the scrip­t’s com­plex­i­ty and require­ments start­ed increas­ing. I still want­ed to keep it as a sim­ple script. Yet, it was grow­ing com­mand line argu­ments that need­ed extra val­i­da­tion. I also need­ed to test some func­tions with­out wait­ing for the entire script to run.

    As with many things Perl, the basic solu­tion is fair­ly old. Over twen­ty years ago, bri­an d foy pop­u­lar­ized the mod­uli­no pat­tern. in which Perl scripts that you exe­cute from the com­mand line can also act as Perl mod­ules. You can even use these mod­ules in oth­er con­texts, for exam­ple test­ing.* A mod­uli­no seemed like the per­fect solu­tion for test­ing indi­vid­ual script func­tions, but writ­ing object-​oriented Perl out­side of a frame­work (or the new Perl class syn­tax) can be chal­leng­ing and verbose.

    Enter the cow (Moo)

    The Moo sys­tem of mod­ules are billed as a light­weight way to con­cise­ly define objects and roles with a con­ve­nient syn­tax that avoids the details of Perl’s object sys­tem.” It does­n’t have any XS code. Thus, it does­n’t need a C com­pil­er to install. Unlike its inspi­ra­tion, Moose, it’s opti­mized for the fast start­up time need­ed for a command-​line script. Sure, you don’t get a full-​strength meta-​object pro­to­col for query­ing and manip­u­lat­ing class­es, objects, and attributes—those capa­bil­i­ties are con­cerns for larg­er appli­ca­tions or libraries. In keep­ing with the light­weight theme, you can use Type::Tiny con­straints for para­me­ter val­i­da­tion. Additionally, there are sev­er­al solu­tions for turn­ing command-​line argu­ments into object attrib­ut­es. (I chose to use MooX::Options, main­ly because of its easy avail­abil­i­ty as an Ubuntu Linux pack­age.)

    I’m not about to dump a pro­pri­etary script here on my blog. Yet, I have worked up an illus­tra­tive exam­ple of how to incor­po­rate Moo into a mod­uli­no. Call it a mooduli­no” if you like; here’s a short-​ish script to tell Perl just how you feel at this time of day:

    #!/usr/bin/env perl
    
    use v5.38;
    
    package moodulino;
    use Moo;
    use MooX::Options;
    use Types::Standard qw(ArrayRef Str);
    
    option name => (
        is       => 'ro',
        isa      => Str,
        required => 1,
        short    => 'n',
        doc      => 'your name here',
        format   => 's',
    );
    
    option moods => (
        is        => 'ro',
        isa       => ArrayRef [Str],
        predicate => 1,
        short     => 'm',
        doc       => 'a list of how you might feel',
        format    => 's@',
        autosplit => ',',
    );
    
    has time_of_day => (
        is      => 'ro',
        isa     => Str,
        builder => 1,
    );
    
    sub _build_time_of_day ($self) {
        my %hours = (
             5 => ‘morning’,
            12 => 'afternoon',
            17 => 'evening',
            21 => 'night',
        );
    
        for ( sort { $b <=> $a } keys %hours ) {
            return $hours{$_} if (localtime)[2] >= $_;
        }
        return 'night';
    }
    
    sub run ($self) {
        printf "Good %s, %s!\n",
          $self->time_of_day,
          $self->name;
    
        if ( $self->has_moods ) {
            say 'How are you feeling?';
            say "- $_?" for $self->moods->@*;
        }
    }
    
    package main;
    
    main() unless caller;
    
    sub main { moodulino->new_with_options->run() }

    And here’s what hap­pens when I run it:

    % chmod a+x moodulino.pm
    % ./moodulino.pm
    name is missing
    USAGE: moodulino.pm [-h] [long options ...]
    
        -m --moods=[Strings]  a list of how you might feel
        -n --name=String      your name here
    
        --usage               show a short help message
        -h                    show a compact help message
        --help                show a long help message
        --man                 show the manual
    % ./moodulino.pm --name Mark
    Good afternoon, Mark!
    % ./moodulino.pm —name Mark --moods happy --moods sad --moods excited
    Good afternoon, Mark!
    How are you feeling?
    - happy?
    - sad?
    - excited?
    % ./moodulino.pm —name Mark --moods happy,sad,excited
    Good afternoon, Mark!
    How are you feeling?
    - happy?
    - sad?
    - excited?

    If the mood strikes, I can even write a test script for my script:

    #!/usr/bin/env perl
    
    use v5.38;
    use Test2::V0;
    use moodulino;
    
    plan(3);
    
    my $mood = moodulino->new( name => 'Bessy' );
    isa_ok( $mood, 'moodulino' );
    can_ok( $mood, 'time_of_day' );
    
    is( $mood->time_of_day,
        in_set( qw(
            morning
            afternoon
            evening
            night
        ) ) );

    And run it:

    % prove -I. t/time_of_day.t
    t/daytime.t .. ok
    All tests successful.
    Files=1, Tests=3,  0 wallclock secs ( 0.00 usr  0.00 sys +  0.07 cusr  0.01 csys =  0.08 CPU)
    Result: PASS

    * foy lat­er expand­ed this idea into the chap­ter Modules as Programs” in Mastering Perl (2007). You can also read more in his 2014 arti­cle Rescue lega­cy code with mod­uli­nos”. Also explore Gábor Szabó’s arti­cles on the top­ic. ↩︎

  • WordPress, ActivityPub, and Friends

    I’ve also been mess­ing with the Friends and ActivityPub plu­g­ins for WordPress on my blog, and I share Shelley’s con­cerns about the for­mer bloat­ing the data­base with feed items. You can con­trol this some­what by set­ting reten­tion val­ues in days or a num­ber of posts, but you have to go into each friend’s Feeds tab and do it manually–there’s no default setting.

    After read­ing that post, I’m also con­sid­er­ing dis­abling Friends in favor of a feed read­er, espe­cial­ly because (as Shelley also not­ed) there are gaps when with favorites and com­ment con­ver­sa­tions bridg­ing between WordPress and Mastodon servers. Like her, I’m not keen on installing a single-​user Mastodon instance or oth­er fedi­verse serv­er that requires man­ag­ing an unfa­mil­iar pro­gram­ming language.

    I’m also try­ing to do this in tan­dem with a suite of IndieWeb plu­g­ins, and I’m run­ning into an issue with my friends feed page not show­ing any posts when the Post Kinds plu­g­in is acti­vat­ed. I real­ly want to keep this plu­g­in because it lets me inter­act bet­ter with oth­er IndieWeb sites as well as the Bridgy POSSE/​back­feed ser­vice con­nect­ing me to oth­er social networks.

    My ide­al is a per­son­al web­site where I write every­thing, includ­ing long-​form arti­cles, short sta­tus­es, and replies like these. Folks can then find me via a sin­gle iden­ti­fi­able address and then subscribe/​follow the entire fire­hose of con­tent or choose sub­sets accord­ing to post types, top­ics, or tags. They’d then be able to reply or react on my site or their favored plat­form, which my site would col­lect regard­less of ori­gin, with sub­se­quent replies and reac­tions get­ting pushed out to them. Oh, and it should work with both ActivityPub clients and servers, IndieWeb sites, and syndicate/​backfeed to oth­er social net­works either with or akin to the Bridgy ser­vice I men­tioned above.

    So far I haven’t seen any­thing that ticks all these box­es, and I’m get­ting itchy to write my own. Perl is my favorite pro­gram­ming lan­guage, so I’m look­ing at the Yancy CMS as a base. But I know that it would still be a hell of a project, and one of the rea­sons I chose WordPress for blog­ging was that it was well-​established and ‑sup­port­ed but still eas­i­ly exten­si­ble so that I could con­cen­trate on writ­ing instead of end­less­ly tweak­ing the engine. Unfortunately, I’m start­ing to fall into that trap anyway.

  • Epochalypse soon

    Paraphrasing Jay‑Z: If your time_t is 32-​bit, I feel bad for you, son. I got 9,223,372,036,854,775,807 prob­lems but an Epochalypse ain’t one

    Follow-​up: Paul Bennett on Facebook asks, When are we going to move to 128-​bit signed inte­ger epoch sec­onds with a 128-​bit IEEE 754 float­ing point off­set in sec­onds?

    I’m not sure how use­ful quadruple-​precision float­ing point sec­onds are, but as for epoch sec­onds, Trond Endrestøl con­clud­ed in a  blog that we would need to move by ear­ly December in the year 292,277,026,596. It would­n’t be much of a year, though, as the sun will have long ago engulfed the Earth (so how do you mea­sure a year?), our entire Local Group of galax­ies will have merged into one super-​galaxy, and all the oth­er galax­ies will have reced­ed out­side the observ­able uni­verse.

    So 292 gigayears should be enough for any­one (that’s still rec­og­niz­ably human), just as 640 kilo­bytes was once enough for any­one”.

  • MetaCPAN on Fastly—no Fastly on MetaCPAN?

    I’m tremen­dous­ly grate­ful for Fastlys sup­port of the Perl MetaCPAN search engine over the past ten years, but the for­mer’s page says they only start­ed serv­ing open source” for eight.
    logos: Rust, Python, Ruby, Scratch, LF, ASF, curl

    And I’m not sure how MetaCPAN is explic­it­ly part of this ini­tia­tive. I don’t see it mentioned.

  • Perl lightning talk: Don’t Fear map and grep”

    This week’s Perl and Raku Conference 2022 in Houston was packed with great pre­sen­ta­tions, and I humbly added to them with a five-​ish minute light­ning talk on two of Perl’s more mis­un­der­stood func­tions: map and grep.

    Sorry about the um”s and ah”s…

    I’ve writ­ten much about list pro­cess­ing in Perl, and this talk was based on the fol­low­ing blog posts:

    Overall I loved attend­ing the con­fer­ence, and it real­ly invig­o­rat­ed my par­tic­i­pa­tion in the Perl com­mu­ni­ty. Stay tuned as I resume reg­u­lar posting!

    Update for Raku

    On Twitter I nudged promi­nent Raku hack­er (and recov­ered Perl hack­er) Elizabeth Mattijsen to write about the Raku pro­gram­ming language’s map and grep func­tion­al­i­ty. Check out her five-​part series on DEV.to.