Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine


( #480=superdoc: print w/replies, xml ) Need Help??

If you've discovered something amazing about Perl that you just need to share with everyone, this is the right place.

This section is also used for non-question discussions about Perl, and for any discussions that are not specifically programming related. For example, if you want to share or discuss opinions on hacker culture, the job market, or Perl 6 development, this is the place. (Note, however, that discussions about the PerlMonks web site belong in PerlMonks Discussion.)

Meditations is sometimes used as a sounding-board — a place to post initial drafts of perl tutorials, code modules, book reviews, articles, quizzes, etc. — so that the author can benefit from the collective insight of the monks before publishing the finished item to its proper place (be it Tutorials, Cool Uses for Perl, Reviews, or whatever). If you do this, it is generally considered appropriate to prefix your node title with "RFC:" (for "request for comments").

User Meditations
Types, objects, and systems, oh my!
No replies — Read more | Post response
by awncorp
on Sep 19, 2022 at 17:01
What if Perl had an OO standard library?
8 direct replies — Read more / Contribute
by awncorp
on Aug 23, 2022 at 07:39

    Programming in Perl is choices all the way down. An OO standard library would make it a lot easier to write Perl in a way that avoids having to come up with similar or the same solutions to common computing tasks, but, ... sustained object-orientation in Perl is difficult because the concept and mechanisms were bolted onto the language as an afterthought, and because it's optional, so one has to oscillate between this paradigm and others, i.e. some things are objects, most things are not, so when using Perl you have to constantly reaffirm your object-orientation. What do you think?

    "I am inevitable." - Thanos
Problems with String::ShellQuote
3 direct replies — Read more / Contribute
by afoken
on Aug 18, 2022 at 13:53

    I have bashed String::ShellQuote several times:

    Most times, it was because the module promises to solve a problem that simply disappears completely if you avoid the shell. See The problem of "the" default shell.

    Now, ovedpo15 came up with a problem that looks like a good reason to have a module like String::ShellQuote, and choroba proposed String::ShellQuote.

    The problem boils down to generate a shell script from perl that will be run by different a user, perhaps on a different computer:

    My Perl utility generates a bash script that consists of mkdir/rsync/cp commands. This bash script is later used by users (this means that I don't want to actually run those commands when my utility runs, rather just to generate the script).

    And, in an answer to a previous bashing, ikegami stated:

    You seem to allege some problem with shell_quote, but none of the linked post identify one. The all seemed centered around the idea of avoiding the shell is better. While true, that's not a problem with shell_quote.

    So, let's have a look at the source code of String::ShellQuote version 1.04, dated 2010-06-11.

    The module clearly states in "Bugs" that ...

    Only Bourne shell quoting is supported.

    Bourne is a large family of shells, but not every shell is a bourne shell. Also, not every default shell is a bourne shell. See Quite obviously, neither from DOS and Windows nor cmd.exe from Windows are even vaguely similar to a bourne shell. The Almquist shell variants are very similar to bourne, but not exactly: The korn shells obviously aren't bourne shells, either.

    So, as stated by the author, you should not expect the result values of the various functions to be compatible with anything but bourne shells.

    With that out of the way, let's assume some bourne shell.

    A 7th edition Bourne shell surely is a bourne shell, right?

    There is a script that tries to find the version of your bourne compatible shell: Did you notice something? There is also a commented version of that script at The very first explaining comment is this:

    : '7th edition Bourne shell aka the V7 shell did not know # as com +ment sign, yet.' : 'Workaround: the argument to the : null command can be considere +d a comment,' : 'protect it, because the shell would have to parse it otherwise. +'

    So, shell_comment_quote() should better use the null command followed by a single-quoted string so that the output works with the bourne shell.

    This is the documentation:

    shell_comment_quote quotes the string so that it can safely be included in a shell-style comment (the current algorithm is that a sharp character is placed after any newlines in the string).

    And this is the code:

    sub shell_comment_quote { return '' unless @_; unless (@_ == 1) { croak "Too many arguments to shell_comment_quote " . "(got " . @_ . " expected 1)"; } local $_ = shift; s/\n/\n#/g; return $_; }

    It does what is documented, but not every bourne shell will accept the output as comment. Oops #1.

    There are two similar functions wrapping the quoting backend function:

    sub shell_quote { my ($rerr, $s) = _shell_quote_backend @_; if (@$rerr) { my %seen; @$rerr = grep { !$seen{$_}++ } @$rerr; my $s = join '', map { "shell_quote(): $_\n" } @$rerr; chomp $s; croak $s; } return $s; }


    sub shell_quote_best_effort { my ($rerr, $s) = _shell_quote_backend @_; return $s; }

    The backend function returns a reference to an error array and the quoted string. shell_quote() removes repeated error messages, and finally croak()s. The only reason for this overhead I can think of is to get a list of all errors at once instead of getting just the first error. shell_quote_best_effort() just ignores all errors and returns whatever survived the backend function. If errors occured, that may be plain wrong. At least, this behaviour is documented:

    This is like shell_quote, excpet [sic!] if the string can't be safely quoted it does the best it can and returns the result, instead of dying.

    Now, what errors may be returned by the backend function?

    sub _shell_quote_backend { my @in = @_; my @err = (); # ... return \@err, '' unless @in; # ... if (s/\x00//g) { push @err, "No way to quote string containing null (\\000) + bytes"; } # ... return \@err, $ret; }

    Yes, that's all. There is only one possible error. It does not like ASCII NUL, because ASCII NUL can not be passed as argument to programs. And because it does not like them, they are simply removed.

    Whenever shell_quote() throws an error, at least one of its arguments contained at least one NUL character. shell_quote_best_effort(), in the same situation, just silently damages your data. Oops #2.

    In all other cases, shell_quote_best_effort() behaves exactly like shell_quote().

    Now, let's look at the quoting:

    shell_quote(), which calls _shell_quote_backend(), is documented as following:

    shell_quote quotes strings so they can be passed through the shell. Each string is quoted so that the shell will pass it along as a single argument and without further interpretation. If no strings are given an empty string is returned.

    This is the code:

    sub _shell_quote_backend { my @in = @_; my @err = (); if (0) { require RS::Handy; print RS::Handy::data_dump(\@in); } return \@err, '' unless @in; my $ret = ''; my $saw_non_equal = 0; foreach (@in) { if (!defined $_ or $_ eq '') { $_ = "''"; next; } if (s/\x00//g) { push @err, "No way to quote string containing null (\\000) + bytes"; } my $escape = 0; # = needs quoting when it's the first element (or part of a # series of such elements), as in command position it's a # program-local environment setting if (/=/) { if (!$saw_non_equal) { $escape = 1; } } else { $saw_non_equal = 1; } if (m|[^\w!%+,\-./:=@^]|) { $escape = 1; } if ($escape || (!$saw_non_equal && /=/)) { # ' -> '\'' s/'/'\\''/g; # make multiple ' in a row look simpler # '\'''\'''\'' -> '"'''"' s|((?:'\\''){2,})|q{'"} . (q{'} x (length($1) / 4)) . q{"' +}|ge; $_ = "'$_'"; s/^''//; s/''$//; } } continue { $ret .= "$_ "; } chop $ret; return \@err, $ret; }

    Right at the start of the foreach loop, an undefined parameter is treated like an empty string and simply returns ''. Note that next jumps to the continue block at the end of the foreach loop. Personally, I would not accept an undefined value, because probably something went wrong in the caller if we get undefined parameters.

    Following that, NUL characters are killed, and data is damaged at the same time. See above. Personally, I would throw an error right here, NUL characters are a sure sign that something went wrong in the caller, and it makes no sense to continue.

    The next step following the first comment in the forech loop is explained in that comment. A feature rarely known to beginners is that you can set environment variables for just the invoked program by prefixing the program with a list of key-value pairs. FOO=1 BAR=2 baz answer=42 invokes baz with the environment variables FOO and BAR set to 1 and 2, and a single argument answer=42. If you want to invoke a program named FOO=1 instead, and pass it the arguments BAR=2, baz, and answer=42, you need to quote at least the first equal sign.

    The flag variables in the first if-then-else: $escape is reset for each parameter, $saw_non_equal is set as soon as a parameter does not contain an equal sign, and stays set. If an equal sign is found, and all previous parameters (if any) also contained equal signs, $escape is set, which forces quoting. This is not strictly needed: If the first parameter contains an equal sign and is quoted, it is taken as program name, and everything following will be read as arguments. So it would be sufficient to check the first parameter for an equal sign. On the other hand, it also does not hurt to quote every string that contains an equal sign, and it would make the code much simpler.

    The whitelist matching if: If the parameter contains a character that is (quoting the output of YAPE::Regex::Explain) any character except: word characters (a-z, A-Z, 0-9, _), '!', '%', '+', ',', '\-', '.', '/', ':', '=', '@', '^', the $escape flag is set. The intention seems to be to avoid quoting if not strictly needed. I'm not sure if all of those characters in the whilelist are harmless. At least in bash (which is a bourne shell), at least the '!' does have a special meaning in the first position:

    >bash --version GNU bash, version 4.3.48(1)-release (x86_64-slackware-linux-gnu) Copyright (C) 2013 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later < +l.html> This is free software; you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. >echo with some arguments ! with some arguments ! >foo with some arguments ! -bash: foo: command not found >'!' foo -bash: !: command not found >! foo -bash: foo: command not found >

    Note: the last example fails to find the "foo" command, not the "!" command. So "!" should better not be in that whitelist. Oops #3.

    The last if in the foreach loop: You want to escape if the $escape flag is set. Sure. But you also want to escape if the $saw_non_equal flag is not set, i.e. all previous parameters, if any, contained an equal sign, and at the same time, the current parameter also contains an equal sign. Do you remember this condition? A few lines above, the $escape flag was already set, depending on exactly this condition. This second condition is completely redundant. Belts and braces, or lost in code?

    The escaping: Singe quotes are replaced with the sequence '\'', which will end a single-quoted string, then add a single quote (quoted by the backslash), and finally begins a new single-quoted string. Ignore the next, long subsitution for now. $_ = "'$_'"; puts the partly-escaped string in a pair of single quotes. The next two substitutions s/^''//; and s/''$//; remove a leading resp. trailing empty single-quoted string. This may happen if the original parameter begins resp. ends with a single quote.

    The long substitution replaces a sequence of at least two escaped single quotes ('\'') by '", followed by a bare single quote for each orignal single quote, followed by "'. This works almost like '\'', ending a single quoted string, then adding a double quoted string of single quotes, and finally starting a new single quoted string. For an original parameter of two single quotes, this finally results in "''" instead of \'\', with every further single quote, the double quoted string will be shorter that the bashslashed string ("'''" instead of \'\'\').

    Joining the quoted strings: The foreach loop replaces the elements of @in with the quoted string in $_ ($_ is aliased to each element of @in). The continue block appends each quoted string and a space to $ret. Finally, chop $ret removes the last space. Is a simple join(' ',@in) too obvious?

    Combining Oops #3 and the suppressed quoting of equal signs:

    >bash --version GNU bash, version 4.3.48(1)-release (x86_64-slackware-linux-gnu) Copyright (C) 2013 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later < +l.html> This is free software; you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. >perl -MString::ShellQuote=shell_quote -E 'say shell_quote("!","FOO=BA +R","baz")' ! FOO=BAR baz >! FOO=BAR baz -bash: baz: command not found >'!' FOO=BAR baz -bash: !: command not found >! 'FOO=BAR' baz -bash: FOO=BAR: command not found >

    In ! FOO=BAR baz, the bash treats baz as the executable, as indicated by the error message, and FOO=BAR as extra environment for the executable.

    In shell_quote("!","FOO=BAR","baz"), ! should be the executable, simply because it is the first argument. Oops #3 prevents that it is quoted. Because the first parameter to shell_quote() does not contain an equal sign, escaping of equal signs is disabled for the remaining parameters. Oops #4.


    String::ShellQuote does not even work properly for bourne shells.

    Oops #1: Assumes every bourne shell accepts # for comments. Most of them do, but the ancient V7 bourne shell does not. Oh well. Document it as limitation and ship it.

    Oops #2: Silent damaging of data. IMHO not acceptable.

    Oops #3: Not quoting a character that will be interpreted by at least one a bourne shell (bash) if not quoted. IMHO not acceptable.

    Oops #4: Oops #3 may cause more missing quoting due to overly complex escaping descision. IMHO not acceptable.


    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
My Perl journey begins
7 direct replies — Read more / Contribute
by oldB51
on Aug 17, 2022 at 19:53

    My Perl journey began 48 hours ago. My Mac now hosts v 5.36.0 in HOME/localperl. I have discovered cpanm and used it to effortlessly install perltidy and perlcritic into HOME/perl5. What I thought was an easy system halted with attempts to install Padre and ptkdb debugger. Both installations appeared to go well with countless OKs on the way…then at the last test fail.

    I think I’m right in saying neither will in fact install on 64bit Macs. But - if this is the case - why does the installation begin. Surely cpanm knows what system it is trying to install into and should stop the process immediately with a polite message.

    Padre is unlikely to be a loss - I now have vscode set up for perl and it recognises v 5.36.0, perltidy and perlcritic. Red squiggles appear when I forget - so far deliberately - to end a line with a ‘;’. It is likely that my debug tactic will be to print variables at various stages until the problem is found. This is usually easier than a formal debugger anyway.

    The next stage of my journey will be working through Beginning Perl and Beginner Perl Maven. So far I’ve only dipped into them. The associated vids on the Perl Maven course are excellent introductions.

    I suspect I will soon be seeking advice from Perl Monks - so many thanks in advance.

Reading Perl documentation in Emacs
2 direct replies — Read more / Contribute
by haj
on Aug 08, 2022 at 13:53

    These days I came round to package an Emacs command which I am using since some time now: <M-x> perl-doc. It is a viewer for POD in Emacs, and it has been accepted in GNU ELPA, so it can be installed with <M-x> package-install.

    But why? There are already plenty of ways to read POD. They work (sort of), but I was not totally happy with any of them:
    • The perldoc command in a shell is nice. It knows what I've installed in my Perl, and I can add own projects to its search path by adding to PERL5LIB. It is not so useful with documents like the Moose::Manual which contain many cross-references.
    • Pod::Webserver is a nice way to get the same information in your browser. But it needs you to run two extra programs and does not provide an equivalent of perldoc -f split.
    • Pod::Perldoc::ToTk is supposed to display POD in a GUI, but the command in the synopsis perldoc -o tk Some::Modulename & fails with Undefined subroutine &Pod::Perldoc::ToTk::MainLoop called. I have Tk::Pod and Pod::Perldoc installed and don't want to chase that error.
    • Emacs has <M-x>cperl-perldoc which per default tries to get information for the thing where your cursor is, and displays the document in another window. But internally it uses man which isn't available on Windows, and until now I was too lazy to install any of the replacements (man for Windows, or woman.el. Also, it needs man pages installed, so I need to build those when I want to read documentation from sources I'm working on.
    • Emacs::PodMode (available via CPAN, not ELPA) is targeted for writing POD, it shows all the markup.
    • The Perl menu in CPerl mode still refers to Perl documentation in info format, which is no longer shipped with Perl and never was available for CPAN modules. Eventually these items should be deleted from the menu.
    • Edited to add (2022-08-09): In the meantime I found perl-pod-preview.el which also provides a man formatted view of POD. I like the fact that it works on (unsaved) buffers and might add a similar feature to perl-doc.el.

    So, trying to combine the good parts, <M-x>perl-doc defaults to the thing where the cursor is, respects PERL5LIB to find your POD (also accepts file names), does not need extra programs and has a decent formatting which allows to follow links between your documents.

How has your coding style changed over the years?
10 direct replies — Read more / Contribute
by stevieb
on Aug 06, 2022 at 21:42

    Since I started coding C and C++ in 2000, and Perl very shortly afterwards, my style hasn't fundamentally changed. If anything, I've simply become more pedantic about certain things. I'm bored so I thought I'd put a list together off the top of my head. What's your list look like?

    - Four space tabs!

    - I like no space between function parens:

    function($param1, \%param2);

    - I'm very much a K&R style person who likes 'else' type statements on their own line:

    sub function { if ($_[0] == 1) { do_something(); } else { do_something_else(); } }

    - When dereferencing a list, I always use whitespace:

    my @list = keys %{ $href->{thing} };

    - I always use the deref indicator where it is needed:

    my $thing = $hash{one}->{two}; my $other = $href->{one};

    - In my personal Perl code (60+ CPAN distributions), I always put the POD at the bottom of the file after all code (at $work, it's inline):

    package Blah; ... 1; =head1 NAME Blah - The thing with the guy and the place ...

    - I *ALWAYS* write unit tests before or at least during writing each function/method. I use the test scripts as test runs to prototype the code I'm writing instead of having a separate script. The test scripts are inherently part of the test suite. I also *ALWAYS* review my unit test suite for each piece of functionality and update it if necessary if patching/updating subs days, weeks or years later.

    - I (almost) *ALWAYS* write POD documentation as I'm writing the code (rarely before, but sometimes I do that too).

    - I frequently peruse the documentation of a random publication of my own software (regardless of language), and make fixes or produce relevant updates I may have missed.

    - I use the same editor all the time (vi/Vim) when I don't have my IDE handy, intelliJ IDEA (with vim support, of course). (VSCode for some of my work projects).

    - I rarely have to use the perl debugger, because I almost always find base issue cause through Data::Dumper statements. If I do use a debugger, it's more often for C code than it is for Perl code.

    - One of my favourite topics for new development is writing code to help other developers (including me). Introspection and unit test software is a big thing for me.

    - I love PPI, and am fluent enough with it that I rarely need to refer to the documentation when I want to use some of its functionality.

    - For my Perl code, I strive with great effort to achieve 95%+ unit test coverage, and that coverage generally covers that 95% 16 ways from Sunday. I often write additional code just so that tests can test code it just cant cover. This includes special constants, env vars etc. Some of my software has complete routines as add-ons just to get a single statement covered that otherwise couldn't have been.

    - I use Continuous Integration testing (CI) for almost everything. Mostly Github Actions (formerly Travis CI until they pissed me off tremendously), but some of my code can't run there, so I use my own Test::BrewBuild for such software.

    - I used to, but not so much anymore, review CPAN latest releases to try to find bugs to fix, even if its just documentation.

    - I am very specific about honouring other artist's copyright information. To further, I regard and honour the license of projects I've taken over from other authors. I'm a published author, poet, lyricist and music producer so the copyright thing in ingrained and imprinted. Appreciating other's art ownership isn't a desire to me, it's a core instinct.

    - I am diligent in acknowledging contributors to my software. My Changes files and commits generally have the persons name and/or CVS username embedded.

    - I take criticism very well; that said, I *ALWAYS* give credit where it is due, and *NEVER* claim credit for things I did not myself do

    - I take bug/issue/feature requests very seriously, and do my utmost to respond in as timely a manner as I humanly can (sometimes I don't, but that's very rare).

    - I use a bug tracker for almost everything I find myself; new features, real life bugs, security issues or even POD typos. If I'm perusing a random distribution of my own and I see a typo in the SYNOPSIS, I create a ticket for it.

    - I never use shift in an OOP module, I always use my ($self, ...) = @_;

    - I *ALWAYS* do parameter validation in each and every function/method.

    - I use pure perl OOP; very, very rarely do I ever use any of the helpers. The only time that happens is if I'm requiring a distribution that has that required already.

    - My POD format for subs is typically:

    =head2 method($param) Contemplates the reason for life, using common sense as a modifier. my $explanation = My::Continuity->new; my $thing = 'Reason for living'; my $reasoning = $explanation->method($thing); I<Parameters>: $param I<Mandatory, String>: The explanation of the formation of humanity in +a single string. I<Return>: Hash reference, where each key is a continent, and its valu +e is a colour. C<croak>s on failure.

    - I very sparsely use comments. Almost always my comments within code refer to *why* something is happening. It very rarely (if ever anymore) refer to 'what' is happening. The code says what is happening. Said comments when I make them are generally one to two lines only, and I use them only when I, myself will need to be reminded why in the fsck I did something so bizarre.

    I'm sure I can add a hundred other particulars I've formed over the years, but that's a start. How about you?

    Edit: Oh dear, I completely forgot. If it isn't blaringly obvious, Perl is my language of choice. Always has been, and I'm sure always will be. I'm decently fluent in C, C++, C#, wrote code in Python for four years as part of a job, can dabble my way through Javascript/JS, but I always lean back to Perl. Need an API for something (eg. Raspberry Pi)?, I'm making it available in Perl! New unofficial API for a new toy (eg. Tesla)? I'm ensuring it can be accessed with Perl! My priorities in life: My health, contentedness and happiness, my sobriety, my wife and children, Perl, everything else :)

RFC: A guide to installing modules for Win32 (2022 Edition)
9 direct replies — Read more / Contribute
by pryrt
on Jul 25, 2022 at 16:05

    Pursuant to Re^3: Can't locate Convert/ , here is a suggested version for "A guide to installing modules for Win32 (2022 Edition)"

    After any suggested updates (I don't pretend to be an expert, so feel free to correct and nitpick), would this go better as a reply to holli's original A guide to installing modules for Win32, or as a new top-level post in the Tutorials section?

    I included the case-sensitivity section because that was an issue in the recent thread Can't locate Convert/, even though I'm not sure how general-use that note really is, or whether it really belongs in this tutorial.

    Updates: Here is a history of the edits made as a result of suggestions.

    1. Fix cpan arguments (per brian_d_foy's reply)
    2. Add perl Makefile.PL to the "standard recipe" (per syphilis's reply)
    3. Switch to a table, to avoid & (avoiding single & per many recommendations)
    4. Fix formatting syntax (per Discipulus's reply)
    5. Add a note about alternative build recipes (to cover Build.PL and possibly others)
    6. Add a note about incompatible modules
    7. s/skill/system/ in the last paragraph (per hippo's comment

    A guide to installing modules for Win32 (2022 Edition)

    Nearly two decades later, holli's excellent A guide to installing modules for Win32 could use some updated information.

    ActiveState phased out using PPM in 2021 (¹), so starting with ActivePerl 5.28, PPM is no longer included.

    And since 2008 (²), there's been an alternative distribution, Strawberry Perl, which comes with it's own gcc/g++ compiler and build environment. Modern Strawberry Perl versions not require using PPM for installation either (though it still ships with a PPM client, if you can find PPM repositories to use it with), so the original Win32 Guide's PPM instructions are not as useful as they once were.

    ActiveState's ActivePerl

    The modern method of "installing" modules on ActivePerl, as announced in The ActiveState Platform and Perl 5.32, is to make a binary build with the State Tool, where you tell it all the modules you need, and it will provide a binary build with all of those modules (and their dependencies) already installed.

    Strawberry Perl

    One of the benefits of Strawberry Perl is that they include a working gcc/g++ compiler and build environment, complete with a variant of make (dmake for older versions, gmake for newer versions; see perl -V:make to find out which your copy of Strawberry Perl uses) that means you can easily build and install modules similarly to how it's done on Linux and other OS:

    The default client comes with Strawberry Perl, so installing Some::Module as easy as cpan Some::Module. Strawberry Perl also comes pre-installed with cpanm, an alternative CPAN client that handles dependencies, allowing installation with cpanm Some::Module. You can install cpanplus or other of the advanced CPAN clients on Strawberry Perl as well.

    Finally, if you are a traditionalist and want to manually build using the traditional recipe, you can look at the output of perl -V:make and then pick the appropriate variant of the recipe:

    perl Makefile.PL make make test make install
    perl Makefile.PL dmake dmake test dmake install
    perl Makefile.PL gmake gmake test gmake install

    Some modules may specify their own recipe for building and installing. If so, then try following their directions; the Strawberry build environment is pretty good. But if they specify a different recipe, it doesn't work, and the CPAN-client options don't work, you should file a bug report with the author, because any distributed module should be installable using cpan, cpanm, cpanplus and the like.

    For any of these installation techniques: If you have an installed copy of Strawberry Perl, your path should point to the Perl and C binaries already; if you have a portable copy of Strawberry Perl, you may need to run portableshell.bat to get the environment set up correctly.

    Other Alternatives

    If you have built your own Perl, or for Windows Subsystem for Linux, or cygwin, or other Windows tools that provide bash or bash-like environments, you should still be able to follow the instructions in the original A Guide to Installing Modules for installing, or use cpanm or cpanplus or other clients not mentioned in the original guide.

    Win32 Caveat: Module Case Sensitivity

    File names on Windows are not case-sensitive, so some Windows users are used to typing PATHS IN ALL CAPS. Do not type module names in all caps, even when using a CPAN client from the Windows command line (cmd.exe or powershell), as Perl and the CPAN tools will not treat SOME::MODULE and Some::Module the same, even if they resolve to the same ...\Some\ file.

    Windows Incompatibility

    Please note that some modules have been created in such a way that they are incompatible with the Windows operating system. This guide cannot help you install and use a module that is not compatible with your OS. (You can check the CPAN Testers reports linked from the page for each module: if it doesn't show any passing results on the mswin32 platform, you may have difficulty installing the module.)

I don't like annotation syntax
3 direct replies — Read more / Contribute
by Liebranca
on Jul 13, 2022 at 06:25


    By 'annotations' I mean 'attributes'. And by 'do not like', 'hate' and 'utter disgust that makes me wish for my own unborn demise' I actually mean it just doesn't click right (hey, that's a way to put it).

    And I wonder if anyone actually likes the :annotation(:attribute) syntax because I seldom see it outside of a *certain* OOP proposal that at least to me smells an awful lot like weird C++ fetish roleplay during which someone must've forgotten the safe word.

    Alright, hey, listen. I know that's too harsh. But if I want weird octopus dog for dinner, then I'll just have that. A 'class' keyword and all derived farts incumbent on the ever philosophizing theorymongers of objectification, I really do not care for.

    So why am I going on about this? I'm writing a preprocessor. It doesn't really introduce new syntax, just fake attributes that are removed before the compiler even gets to see them.

    The purpose of these attributes is simple: marking subroutines for inlining and variables as blessed references to one or another package -- just because I need to know where to pull a definition from before I get to inlining anything. It's a pinky-promise, not a typecheck.

    But this syntax...

    my $eyes :bleed = '<-whenever I see :this and :that';

    ... is frankly not my cup of tea. But I *do* wonder who likes it, if anyone, and why. I mean, I get it. I'm an outcast, a widower and I'm pissed. To say I'm out of touch is an understatement. So alright, I'm willing to listen to reason. Where is reason?

    I can transform an entire file, and therefore am entirely in possession of the arcane power to change the language itself into hexspeak spaghetti; I'd much rather work on something other people can read. Or more like, I'd much rather work on something that doesn't require you to basically relearn the language in order to use it.

    It must FEEL like it's still the same thing. That is why I care to do this:

    use inline; MyPackage::MySub(); # contents of sub will be inlined no inline; MyPackage::MySub(); # will not be inlined

    ^because it's what feels more natural, more Perl-esque, far as I'm able to tell. It's the same to perl the binary because the preprocessor in question strips those two use/no lines anyhoo, so they could just be whatever I say. I could just enforce Turbo C on 16-bit Windows rules because that's how I was taught way back when and it makes me feel nostalgic to #include <conio.h> and define functions inside a macro just because I can. Wouldn't that be silly of me?

    Yes, it would be silly. Sorry, this is a lot of ranting. I'm trying to think of a better way to make the pinky-promise to the preprocessor that a given variable is a blessed ref that isn't just simply adding the pinky-promise keyword and calling it a day. This is driving me crazy.

    If people feel annotations for this are alright then I must defer to their judgement. Mostly because I can't think of anything better that doesn't look like C. And that's that, you know.

    Have a good day.

Good day fellow monks. Back after a while
3 direct replies — Read more / Contribute
by Charles_okhumode
on Jul 13, 2022 at 05:31

    It's been a while i have being a member of perl monks. I have being on and off in my participation in here. I guess administrators would have picked up on my in ability to recaĺl my username, password,and email to my previous account.

    This is because i have being in and out of hospital and the mobile number i was using in the past for the email account i misplaced it and the sim pack. Making it difficult to retrieve the number.

    Now i am slowlly recovering and sooner rather than latter ill be back on my foot and able to be more active in here.

    I consider myself an intermediate perl programmer and have a working knowledge of unix/linux. I am also comfortable in systems asministration. My goal now is to major on web application development using perl.

    I have began my search for the right MVC i can use for this. I know there are quite a few. Please your guidiance and mentoring will be gladly welcomed.

    I hope my time in here will be fun and relatively peaceful. I wish to have a friend whom i can grow and share my learning experience with.

    Thanks and God bless.

Reflections after going through all PDL-featuring nodes on PerlMonks
3 direct replies — Read more / Contribute
by etj
on Jul 08, 2022 at 16:58
    As a few will have seen (I assume they look at "Newest Nodes" - and kindly upvoted some of my replies, for which many thanks), I've been posting replies to some old nodes on here. This was after deciding a couple of months ago that after looking at the front page each day and voting on various posts and replies, I'd then go back over all the nodes featuring the text "PDL" and vote on (to use the rest of that day's votes) / reply to ones where that seemed useful. I kept track of where I was up to by looking at "Nodes (I) Wrote" and seeing the date of the original thread I was replying to on my most-recent post.

    Some of the things I have learned:

    • of a few non-reported bugs in PDL that are now fixed
    • of a few former keen PDL users who now apparently don't visit PerlMonks anymore
    • back in 2001, there was a thing called "Program Design Language" which gave some false positives on my searching
    • protein sequences using the coding gave some false positives when folks using Perl for biology stuff included some data with the string "PDL"
    • Despite PDL being around since 1997 in various forms, it only started getting discussed on here in mid-to-late 2000 or so
    It's been really interesting to take this journey back through time, and see how Perl, and the PerlMonks site, and PDL have developed over time.
perl 5.36 and the for_list feature - a simple speed comparison
1 direct reply — Read more / Contribute
by swl
on Jun 21, 2022 at 05:32

    Perl 5.36 has a new feature that iterates over multiple values at a time in a for loop (perldelta entry here). Any number of values can be specified, but the pairwise case is the focus here.

    The for_list feature is a useful alternative to a while-each idiom over a hash when working with key-value pairs. It also allows one to natively work with arrays of key-value pairs without converting them to a hash (and thus losing values associated with duplicate keys).

    Speed is one factor in the decision to updated code, so I figured I would see how fast the new feature is compared with while-each and some other approaches using List::Util functions. Some benchmark code is below (inside readmore tags), with results following.

    Benchmark labels starting with a_ operate on array data while those with h_ operate on hash data.

    I note that it is fairly well documented that the while-each idiom is best avoided because the hash iterator has global state and thus can cause action at a distance. In the benchmark code the hash is only accessed this way in one sub.

    The summation of the hash values in the loops is merely something for the loop to do that would have relatively low overhead compared with the looping itself.

    The hash_vals sub is done as a point of comparison. There is no reason why one would iterate over both keys and values when only the values are needed.

    Code was run under Ubuntu 20.04 under WSL2 for Windows.

    The main conclusion is that the new feature is faster than all the others when an array is used. It is faster than all of the hash approaches that use both keys and values. Profiling shows the cause of the slowdown when using List::Util::pairs is the dereference of the pair array, which is not surprising. Using the declared_refs feature does not help in this case.

    Overall I quite like the new for_list feature. Aside from being faster than many of the alternatives, it is also much cleaner.


    2500050000 2500050000 2500050000 2500050000 2500050000 2500050000 2500050000 2500050000 Rate a_pairs_alias a_pairs h_by_key h_each h_for_list +h_vals a_pair_vals a_for_list a_pairs_alias 87.9/s -- -9% -19% -35% -51% + -82% -83% -89% a_pairs 96.5/s 10% -- -11% -28% -47% + -80% -81% -88% h_by_key 109/s 24% 13% -- -19% -40% + -77% -78% -87% h_each 135/s 53% 40% 24% -- -25% + -72% -73% -84% h_for_list 181/s 106% 88% 66% 34% -- + -62% -64% -78% h_vals 477/s 443% 394% 338% 254% 164% + -- -6% -42% a_pair_vals 506/s 476% 424% 364% 275% 180% + 6% -- -39% a_for_list 827/s 841% 757% 659% 513% 357% + 73% 63% --
20 is a round number
4 direct replies — Read more / Contribute
by Discipulus
on Jun 13, 2022 at 07:54
    Hello dear community,

          Happy Monkday!!1!
          You've been here 20 fruitful years.
          Haven't you grown up yet?

    is the message I've found today entering the halls of our lovable place.

    I planned for today a spectacular obfuscation, but lacking currently the inspiration I just have for you a little resume of my partecipation.

    Yes: I grown up here. It was in 2002 when I moved my first baby steps in the Programming Art, Perl declination of it, so poor in English and in Perl that I wrote my code in Italian.

    During these early years I attempted to automate as much as possible my daily job with windows, IIS et similia. My scripts incredibly worked even in this ugly environment. My mad vein was already there, for exmple I wanted to modify my source at runtime: substitution in $0.

    In this early stage I used a lot of CGI and I started having fun with Tk under the mentorship of master zentara.

    At that time node reputation was in hundreds of votes: many brilliant hackers here and my lack of understanding them.. nice days :)

    Then, starting from Murder of a Perl coder (announced), I had bad times with Perl at work, with only eleven posts here during 2005-2008.

    Then, since 2009, a personal rebirth: Perl is too much addictive to be killed by job bosses: I published here the first naive CUFP: when no ping say 'moo!' and I used it to spot the right eth cable in the datacenter, detaching them in serie, in the time no cable were numbered.. a mess :) This was the first of 23 CUFP.

    New techniques, modules usage and a modern Perl for me: I started coding my own modules.

    Among my personal Cool Uses for Perl you can find the acme of my heresy: the biggest string eval ever attempted by a coder: CPAN Namespace Navigator evals the whole 02packages.details.txt from CPAN. I'm still proud of it.

    In 2012 my Ten (years) Here marked the beginning of yet another era: I found that I had something interesting to share with you and that I'm able to give a little help to newcomers, always as humble amateur.

    The majority of my Meditations are since then. As heretic perl programmer I started an incomplete serie: Antiquitates - liber I and Antiquitates - liber II aiming to link ancient wisdom with our beloved perl art. Worth to notice also Binary Comedy -- 01 - 000001 where I poetically met Larry in Dante's Inferno.

    After fifteen years here it started again a time of troubles, with work involving in a mess with absolutely no more room for my perl, now that I'm almost ready to become a professional perl coder, simply the perl job marked is something not existing anymore.

    But dont give up! During this golden age you can find my 12 Obfuscations and my Poetry.

    In the same years I became a oneliner addicted with 76 oneliners published here, let me feeling the younger of the old hacker generation and the acme of ameteur perl coders.

    Thanks you all for these 7305 amazing days!!


    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
Work-around for Gmailpocalypse
1 direct reply — Read more / Contribute
by Aldebaran
on Jun 02, 2022 at 20:41

    Hi Monks,

    I just wanted to write up what happened with on the 30th of May. Auth 2.0 came into effect, which deprecated use of a username and a password, requiring instead an app key. An effective work-around is described in Re^3: sending an email from my rpi to my droplet [gmail workaround].

    I found the error message instructive:

    $ echo "BEEP BEEP" | mailx -s "Subject: This is a test!" tallharry84@g send-mail: authentication failed (method PLAIN) send-mail: server message: 534-5.7.9 Application-specific password req +uired. Learn more at send-mail: server message: 534 5.7.9 +?p=InvalidSecondFactor s8-20020a62e708000000b0051835ccc008sm2037121pf +h.115 - gsmtp send-mail: could not send mail (account default from /home/pi/.msmtprc +) send-mail: cannot log to /var/log/msmtp.log: cannot open: Permission d +enied send-mail: log info was: tls=on auth=on user=tallh +arry84 sm +tpstatus=534 smtpmsg='534-5.7.9 Application-specific password require +d. Learn more at\n534 5.7.9 +idSecondFactor s8-20020a62e708000000b0051835ccc008sm2037121pfh.115 - +gsmtp' errormsg='authentication failed (method PLAIN)' exitcode=EX_NO +PERM Can't send mail: sendmail process failed with error code 77 $

    Typing in the 16-letter app output in the place of the password does the trick.

    I went ahead and opened up the site they mention and found it worth a read: Signing in with App Passwords. The world is a-changin' as far as authentication goes. Passwords are no longer for sticky notes on the wall. 2-factor auth is necessary, and if you don't have a phone number to give google, they're not gonna let you play.

How to get programming help
7 direct replies — Read more / Contribute
by jdporter
on May 23, 2022 at 11:21
    "Every time I have a programming question and I rly need help, I post it on PerlMonks and then log into another account and reply to it with an obscenely incorrect answer. Ppl don’t care about helping others but they LOVE correcting others. Works 100% of the time"
    -- @soychotic
Libraries and security
2 direct replies — Read more / Contribute
by davies
on May 23, 2022 at 10:25

    An article in today's Register, has got me thinking. One quote from it is "These 2,415 people with these email addresses are currently more trusted than your own software engineers as they can effectively run any code they want on your production infrastructure without review from anyone". When the Log4J vulnerability appeared, I found out (I hardly ever use Java) that the offending module could be in any .jar without it being obvious to the programmer. At least, when I install a CPAN module, I can see a list of the modules it brings with it, even if I don't usually pay enough attention. But sometimes I need to be very security conscious.

    Looking for vulnerabilities in CPAN took me to There's not a lot there, and many of them are closed in the latest version. But looking at one of them,, I see that the module was updated <update>last month two years ago, seven years after the vulnerability was reported</update>, but that there is nothing in the changes file to indicate that the vulnerability has been addressed even though it's nine years old. Nor is there anything in the docs even acknowledging the existence of the vulnerability.

    The changes file does, however, reveal another worry.

    1.148 Thu Nov 16 10:21 2006
    - Debian has chosen to distribute their own Data::UUID, which has a different interface and breaks other modules.

    What, then, do people do in the real world? Are checks for CVEs enough? Do people do code reviews of every module they use in every language? It sounds beyond the bounds of reasonability to me. Are there certifications for modules (and if so, who certifies the certifiers - that old question)? I know people who prefer to install Perl packages on Debian via apt because it makes them easier to delete, but the quote above makes me fear that the CPAN and apt packages need not be the same.


    John Davies

    Update: I read the date carelessly & got it wrong. Thanks, Hippo.

Add your Meditation
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":

  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or or How to display code and escape characters are good places to start.
Log In?

What's my password?
Create A New User
Domain Nodelet?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others pondering the Monastery: (2)
As of 2022-09-29 02:11 GMT
Find Nodes?
    Voting Booth?
    I prefer my indexes to start at:

    Results (125 votes). Check out past polls.