Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Meditations

( #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
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.

    Results:

    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!!

    L*

    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 smtp.google.com 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 +mail.com 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 https://support.google.com/mail/ +?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: host=smtp.gmail.com tls=on auth=on user=tallh +arry84 from=tallharry84@gmail.com recipients=tallharry84@gmail.com sm +tpstatus=534 smtpmsg='534-5.7.9 Application-specific password require +d. Learn more at\n534 5.7.9 https://support.google.com/mail/?p=Inval +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, https://www.theregister.com/2022/05/23/npm_dependencies_vulnerable/ 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 https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=cpan. There's not a lot there, and many of them are closed in the latest version. But looking at one of them, https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-4184, 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.

    Regards,

    John Davies

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

RFC: Creating Dancer2 validation plugin.
3 direct replies — Read more / Contribute
by AlexP
on May 04, 2022 at 10:30

    Hello monks, this is requests for comments, so if you are interested in this topic, please leave any.

    Preface

    Dancer2 is a lightweight framework that provides us with rich routing and serialization features out of the box. The rest is left to the developer, including working with the database, models and data in general.

    When working with data, especially received from a user, you want to be sure of their consistency. In other words, I don't want to get a number where the username should be and the word in the age field (like age => twenty).

    Perl is a language with very powerful regular expressions and many hackers use them. However, this approach has the following disadvantages:

    • It is not declarative, you need to validate all fields manually
    • It's hard to reuse
    • Code is cumbersome and hard to read

    Instead of writing if ($age !~ /^\d+$/) {…} else {…} and so for each field received from the user, I want to use a construction like (age => 'integer').

    And here you should pay attention to special modules that simplify the validation process.

    Modules

    I've found some useful modules on cpan:

    They all have their pros and cons, but none of them met all my criteria.

    Criteria

    1. Control flow the field to the validator, and not vice versa

    This means that the code used fields as first class entities:

    { email => qw(required, email), age => qw(integer, min:18), }

    And not validators:

    { required => qw(email), email => qw(email), integer => qw(age), min => { filed => ‘age’, num => 18 }, }

    2. Required is validator too

    Very often you can see:

    { required => … , validators => { … } }

    Requred is the same validator and it is not clear to me why to extract it into a separate entity.

    3. Has a set of built-in validators

    Not all modules have built-in validators and you need to implement them yourself.

    4. Easily extendable with new modules or custom code

    This feature is provided by most modules.

    5. It has a minimal set of dependencies and does not require the mandatory use of DBIc or Moose

    Because we have a Dancer2 project and maybe we don't use DBIc models at all.

    6. Multilingual support

    Didn't find it anywhere.

    7. Tightly integrated with Dancer2 and provides a set of handy dsl words and html templates tokens

    I do not want to constantly get and transfer data to the template like errors or old input.

    Dancer2::Plugin::FormValidator

    Based on the above criteria, I decided to write my plugin specifically for Dancer2. Since this is my first big OS project, I ask respected monks to share their opinion on what I got as a result.

    use Dancer2; use Dancer2::Plugin::FormValidator; package RegisterForm { use Moo; with 'Dancer2::Plugin::FormValidator::Role::Profile'; sub profile { return { username => [ qw(required alpha_num_ascii length_min:4 + length_max:32) ], email => [ qw(required email length_max:127) ], password => [ qw(required length_max:40) ], password_cnf => [ qw(required same:password) ], confirm => [ qw(required accepted) ], }; } } post '/form' => sub { if (validate profile => RegisterForm->new) { my $valid_hash_ref = validated; save_user_input($valid_hash_ref); redirect '/success_page'; } redirect '/form'; };

    Plugin can be found on Metacpan => Dancer2::Plugin::FormValidator.
    Github repo => dancer2-plugin-formvalidator.

    I am think about the following questions:

    • How convenient is the dsl keywords interface? Is the word validated redundant? Moreover, it uses a global variable. But it looks helpful.
    • How complete is the set of basic validators, is it worth expanding it, with what?
    • In tests, pieces of code are often repeated, is there a generally accepted method of reusing them?
    • Is the documentation clear, what should be added or removed?
    • Are the interfaces friendly to extensions: Extension.pm, Validator.pm
FY411: Missing Perl on package managers for Mac and Windows
1 direct reply — Read more / Contribute
by perlfan
on May 03, 2022 at 14:12
Pangram challenge: greed and Scrabble
2 direct replies — Read more / Contribute
by Athanasius
on Apr 24, 2022 at 10:43

    Task 2 of the current Perl Weekly Challenge is to generate a pangram from the English dictionary provided. “A pangram or holoalphabetic sentence is a sentence using every letter of a given alphabet at least once.”1 However, for this challenge the requirement that the words form a sentence is removed: a list of unrelated words is all that is required.

    The bonus challenge is to “Constrain or optimize for something interesting,” and the first suggestion given is:

    Shortest possible pangram (difficult)

    Ok, so just how difficult would it be to perform an exhaustive search? I don’t know the answer, but since the search space increases exponentially as words are added to the dictionary, a search for sequences (of varying lengths) drawn from a pool of 23,610 words (see below) would appear highly impractical. I haven’t attempted it.

    Before we proceed, it should be noted that the dictionary can be significantly reduced in size before the search begins. Where groups of words share the same set of letters, only one word from the group (the shortest) need be kept. For example, “abdicate,” “diabetic,” and “abdicated” all have the letter set {a, b, c, d, e, i, t}, so “abdicate” is retained but “diabetic” and “abdicated” are filtered out. This reduces the dictionary size from 39,172 to 23,610 — a saving of 15,562 words!

    As noted above, 23,610 is still far too many words for an exhaustive search. So we’re looking for a way to get a close-to-optimum result in a reasonable time. And as we’ve just noted, each dictionary word can be considered as a set of its component letters. So the task is to find a minimum set cover, a well-studied problem in combinatorics and computer science.2 And there is an algorithm that is known to give good results in polynomial time: the greedy algorithm:

    at each stage, choose the set that contains the largest number of uncovered elements.

    My initial implementation of this algorithm produced the following pangram:

    oversimplification ladybug hawk jazz equinox (40 letters)

    I wasn’t satisfied with this, so began looking for ways to improve the search. It occurred to me that words with rare letters should be preferred over words with common letters. This immediately suggested the Scrabble3 points system:

    const my %ALPHABET => ( a => 1, b => 3, c => 3, d => 2, e => 1, f => 4, g => 2, h => 4, i => 1, j => 8, k => 5, l => 1, m => 3, n => 1, o => 1, p => 3, q => 10, r => 1, s => 1, t => 1, u => 1, v => 4, w => 4, x => 8, y => 4, z => 10 );

    With this I was able to give each word a weighting based on its component letters, and prefer words with higher weightings. This produced the following pangram:

    sympathized quarterbacking reflexive jawbone (41 letters)

    — no improvement at all! The problem appears to be that the selected words contain too much deadweight — too many redundant letters. So would it help to adjust the weighting for each word by deducting points for redundant letters? I experimented with different values of $DUP_WEIGHT, the amount to deduct for each redundant letter. Here are the results:

    $DUP_WEIGHT Pangram Letter Count
    1 sympathized quarterbacking jinx overflow 37
    2 sympathized quacking overflow jinx be 33
    3 sympathized quacking fox jaw verb all 32
    4 sympathized unblock xv jaw qt frog 29

    Eureka! At 29 letters, the last pangram is only 3 letters above the theoretical best-possible result of 26. (For values of $DUP_WEIGHT above 4, the result does not change.)

    It should be emphasized that my improved results are not an improvement on the greedy algorithm. That algorithm applies to sets, whereas my search for pangrams is a search over words, which are essentially bags because they contain multiple instances of the same letters.

    For the implementation, I found the Set::Tiny module very useful. I highly recommend it for working with sets of strings.

    Wikipedia1 gives the following as a short pangram:

    Waltz, bad nymph, for quick jigs vex. (28 letters)

    Since all these words occur in the given dictionary, it would be possible for a search to improve on my best solution by at least one letter. Challenge: can anyone implement a search which finds this pangram (or a shorter one) within a reasonable time?

    Full code listings for my solution (in Perl and Raku) will shortly be are available on the Weekly Challenge’s GitHub repository at https://github.com/manwar/perlweeklychallenge-club/tree/master/challenge-161/athanasius.

    Cheers,

    1“Pangram, ” Wikipedia, https://en.wikipedia.org/wiki/Pangram
    2“Set cover problem,” Wikipedia, https://en.wikipedia.org/wiki/Set_cover_problem
    3 “Scrabble letter distributions,” Wikipedia, https://en.wikipedia.org/wiki/Scrabble_letter_distributions#English

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Trading compile time for faster runtime?
7 direct replies — Read more / Contribute
by melez
on Apr 20, 2022 at 09:54

    Perl optimizations are pretty basic, and it compiles fast - which is great for utility scripts, but sometimes it feels like a waste of potential. A lot of Perl code actually runs persistently, either behind mod_perl, plack server, mojolicious server or just as a daemon.

    I've been thinking - what if we had a switch (executable flag?) that would turn on additional set of compile time optimizations? It could hypothetically be a big performance win, and not affect programs that need to boot fast. I have close to no experience in XSUB, so that's a big if.

    For example, one of my projects has I think close to 100 .pm files and compiles in 800 ms. It will then run for a long time (in production) and require performance. Other than testing and development, I wouldn't mind spending 10 seconds extra if that would mean some crucial parts would run 50% faster. Or maybe I could care less about using small subroutines in tight loops, as they would get inlined.

    Comments? Was it attempted already?

Critique of some perl code.
3 direct replies — Read more / Contribute
by jwkrahn
on Apr 17, 2022 at 03:03

    Hello Everyone,

    I occasionally like to download perl programs off the web to see how they work. And if there are any bugs I try to report back to the original author.

    This code was found verbatim (except for the file name) in two different files.


    my $conf = which_conf($configuration_file); if (-f $conf) { my @conf_args; open(my $conffile, '<', "$conf") or warn "$P: Can't find a readable $configuration_file file $! +\n";

    It looks like there is a race condition between the file test and the file open.

    The file test does not print a message if the file is not found but the file open does.

    If the file cannot be opened a message is printed and then another message is printed when readline tries to read from an invalid file handle.

    The file name is copied to a string.


    while (<$conffile>) { my $line = $_;

    Data is assigned to $_ and then copied to $line but $_ is never used inside the loop.


    $line =~ s/\s*\n?$//g;

    This is the line that gobsmacked me. I ran some tests with Benchmark and re 'debug' compared to the FAQ answer "s/\s+$//;" and it turns out that this is a good example of what not to do.

    This substitution was found in five places in one file and two places in the other file.


    $line =~ s/^\s*//g;

    Not as bad as the previous line but still not as good as the FAQ answer.


    $line =~ s/\s+/ /g;

    Correct code, nothing to see here.


    next if ($line =~ m/^\s*#/); next if ($line =~ m/^\s*$/);

    Why check for whitespace after you've just removed it?


    my @words = split(" ", $line); foreach my $word (@words) { last if ($word =~ m/^#/); push (@conf_args, $word); }

    This code is where the work is done and obviates the need for the previous five lines. split(" ", $line) removes all whitespace. foreach will not loop if @words is empty. $word =~ m/^#/ will skip to the next line if a '#' comment is found.


    close($conffile);

    Correct code, nothing to see here.


    unshift(@ARGV, @conf_args) if @conf_args;

    The conditional is not really required.


    Where I found this code:

Remembering Sven Guckes - a perl hacker perspective
No replies — Read more | Post response
by cavac
on Apr 15, 2022 at 06:29

    A couple of months ago, my friend Sven Guckes passed away.

    When we met in person, once or twice a year, it was mostly him teaching me new stuff. That's what he always did, with everyone: Showed people new tips and tricks for the command line, helped them out whenever he could without asking anything in return. In February 2021, he asked in Twitter for a way to convert his text-only conference "diary" (a list of events at a conference) to an RSS feed. I whipped up a quick proof of concept. It was not perfect by any means, but he liked it.

    He had a format in his text files like this:

    * 2021-02-15 08:10:00 Working for Twitter now? Sven on Twitter asked to whip up a script to turn diaries into RSS fee +ds. * 2021-02-15 08:20:00 That was easy! All done! This was easier than expected!

    And this is what i came up with.

    #!/usr/bin/env perl use strict; use warnings; use HTTP::Date; use Time::Piece; use Carp; my $gmtoffset = 1; # Hours print '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" +xmlns:atom="http://www.w3.org/2005/Atom">', "\n"; print '<channel>', "\n"; my ($date, $title); my @content; while((my $line = <>)) { chomp $line; if($line =~ /^\*\ (\d\d\d\d\-\d\d\-\d\d\ \d\d\:\d\d\:\d\d)/) { my $temp = $1; if(defined($date)) { printItem(); } $date = $temp;; $title = <>; @content = (); chomp $title; next; } next unless defined($date); push @content, $line; } if(defined($date)) { printItem(); } print '</channel>', "\n"; print '</rss>', "\n"; exit 0; sub printItem { print '<item>', "\n"; print '<title>', $title, '</title>', "\n"; print '<pubDate>', toWebdate($date), '</pubDate>', "\n"; print '<description>', join('<br/>', @content), '</description>', +"\n"; print '</item>', "\n"; return; } sub toWebdate { my ($localdate) = @_; my $webdate; my $unixtime = Time::Piece->strptime($localdate, "%Y-%m-%d %H:%M:% +S")->epoch(); $unixtime -= $gmtoffset * 3600; $webdate = time2str($unixtime); return $webdate; }

    Then you run it with perl diary2rss.pl < testdiary.txt and get:

    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:a +tom="http://www.w3.org/2005/Atom"> <channel> <item> <title>Working for Twitter now?</title> <pubDate>Mon, 15 Feb 2021 07:10:00 GMT</pubDate> <description><br/>Sven on Twitter asked to whip up a script to turn di +aries into RSS feeds.<br/></description> </item> <item> <title>That was easy!</title> <pubDate>Mon, 15 Feb 2021 07:20:00 GMT</pubDate> <description><br/>All done!<br/><br/>This was easier than expected!</d +escription> </item> </channel> </rss>

    We were planning to get together this year, maybe look into writing a proper tool for him to use. But sadly, this will not happen.

    Thank you, Sven, for teaching me so much. I just wish i could have returned the favours.

    perl -e 'use Crypt::Digest::SHA256 qw[sha256_hex]; print substr(sha256_hex("the Answer To Life, The Universe And Everything"), 6, 2), "\n";'
Module name: PDL::WebSocket?
2 direct replies — Read more / Contribute
by etj
on Apr 06, 2022 at 13:22
    The git-latest PDL (not yet released as 2.078) has, as a new part of its "3d" demo, a 3D model of the Earth (using PDL's OpenGL support), with shading, and shape information. It also has a bug-fixed version of the 3D graph-evolving code added in the late 1990s, which animates the evolution of a molecule-like graph structure, using a form of publish/subscribe.

    Having just looked at https://www.lightningmaps.org/, it uses a websocket to get a live feed of lightning strikes every few seconds, updating a flat Leaflet/OpenStreetMap world map.

    It occurs to me that a module that connected a Mojo::WebSocket to such a live feed, could create a live-updating ndarray to display lightning strikes on our shiny new 3D Earth globe, in a decently eye-catching demo module (using PDL's new plugin-based demo system). What would such a module be called? PDL::WebSocket?

PDL
No replies — Read more | Post response
by etj
on Mar 23, 2022 at 11:28
RFC: nicer subs with GetOptionsFromArray from Getopt::Long
2 direct replies — Read more / Contribute
by Discipulus
on Mar 23, 2022 at 08:09
    Hello esteemed folks,

    As few posts running around these days I propose you an idea I had recently and that seems to work as I expected.

    The goal is, as the title says, to use GetOptionsFromArray from Getopt::Long to parse arguments passed to a sub adding the flexibility in arg specification and adding also a primitive type check.

    In the below code the sub test (yeah! what a great name! ;) defines the hash %opts where initial default values are declared and where GetOptionsFromArray will soon put passed in arguments and defines also a @template to hold definitions of various arguments type (with the benefit of a minimal type check for free)

    Here my actual code:

    use strict; use warnings; use Getopt::Long qw(GetOptionsFromArray); use Data::Dumper; my $debug = 0; # 0-2 Getopt::Long::Configure ("debug") if $debug > 1; sub test{ if ($debug){ print "\@_ received: ",Dumper \@_; } # default values in the destination hash my %opts = ( len => 42, switchx => '', # colors => [qw(red yellow green)], # these are NOT ov +erwritten, why? colors => [], ); # copy for debug purpose my %default = %opts; # template for valid options my @template = ( "len|lunghezza=i", "switchx", "tick=i", "colors=s@", ); my $ret = GetOptionsFromArray(\@_, \%opts, @template ) ; # handle errors unless($ret){ print "template for this sub is:\n", "\t",(join "\n\t", @template),"\n", "default values are:\n", ( map{ "\t$_ = ". ( ref ($default{$_}) eq 'ARRAY' ? (join ' ',@{ +$default{$_}}) : $default{$_} ). "\n"}sort keys %default ),"\n"; return; # this should be die } if ($debug){ print "GetOptionsFromArray returned: $ret\n"; } if ($debug){ print "\@_ after GetOptionsFromArray: ", Dumper \ +@_; } print "final \%opts result: ", Dumper \%opts; print "remaining in \@_:", Dumper \@_ if @_; } foreach my $argtest ( [( qw(-len 1111) )], [( qw(-l 11) )], [( qw(-lunghezza 12121212) )], [( qw(-len AAAA) )], [( qw(-len 2222 -un known) )], [( qw(-len 2222 -tick 3333) )], [( qw(-len 2222 -colors blue -colors cyan -colors orange) )], [( qw(-len 2222 --switchx) )], [( qw(-len 3333 --switchx -- Alpha Bravo) )], ){ print "PASSING: (",(join ' ', @$argtest),")\n"; test ( @$argtest ); print "\n"; }

    ..and the output

    I wonder if this behaviour can be put into a module (the original idea was to use Class::Method::Modifiers to inject code just before the original subroutine) but I wonder if it is worth to and notably which interface to expose. Perhaps something like Sub::Getopt::Long is a nice name for this.

    An eventual module interface should be similar to a simple:

    use Sub::Getopt::Long qw( longargs ); sub MyOwnStuff{ my %opts = ( len => 1, wid => 2); # defaults %opts = longargs( \%opts, [qw( len=i wid=i )], @_ ); # or simply my %opts = longargs( {len => 1, wid => 2}, [qw( len=i +wid=i )], @_ ); }

    Any comment or suggestions are as always warmly welcome!

    L*

    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.
Combining Function::Parameters with Type::Standard's InstanceOf
1 direct reply — Read more / Contribute
by choroba
on Mar 16, 2022 at 10:33
    When using the Types::Standard's InstanceOf in combination with Function::Parameters, the code using plain InstanceOf doesn't compile:

    #!/usr/bin/perl use warnings; use strict; use feature qw{ say }; { package My; sub new { bless {}, shift } } use Function::Parameters; use Types::Standard qw( InstanceOf ); fun validate(InstanceOf['My'] $m) { # <- Fails :-( say "object:", $m; } my $m = 'My'->new; validate($m);

    The exact error message is

    In fun validate: missing type name after '[' at 1.pl line 13.

    It seems both the modules extend the parser somehow and they step on each other's toes.

    Fortunately, it's pretty easy to fix that: you can prevent Function::Parameters from interpreting the InstanceOf before Types::Standard handles it by enclosing it into parentheses:

    fun validate((InstanceOf['My']) $m) { # <- Works :-) # ~ ~

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

Add your Meditation
Title:
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?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (3)
As of 2022-07-05 09:24 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?