Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
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
A recipe for testing and debugging with vim
2 direct replies — Read more / Contribute
by nysus
on Mar 07, 2017 at 21:10

    I've patched together some vim scripts, a vim plugin, tmux, perl modules, and a three-line bash script to create an efficient way of running and debugging my code with minimal effort. I thought I'd share and get some feedback and maybe others will find this useful, too. As easy as this is to get set up, it took me a lot of trial and error to get right so hopefully I will save some of you out there looking to do something similar a lot of pain and aggravation. And, yes, I realize there are other vim plugins for this task but none of them satisfied my exact needs (especially the syntax highlighting) or they came with lots of other baggage I didn't want or need. Plus, I wanted to get more familiar with vim so I decided to roll my own.

    Note: I don't believe this will work with gvim because this solution relies on tmux, a terminal-based program.

    Synopsis

    With a *.t test file open in vim, hit <F7> (without even having to save first!) to run a prove command on your test. The output of the test gets opened in a new tmux pane (Pane B) to the right of my vim window. As the test runs, you can still edit your file since output of the test is in a tmux pane. The other advantage to seeing the live output of prove is that it gives your peace of mind that your script is actually working while also getting a rough gauge on which parts of the code are slow or if your script is stuck in some infinite loop. Mixed in with prove's output are messages generated by the Log4perl module (trace, debug, info, etc. statements). Once the script finishes running, prove's raw output in Pane B gets replaced with a new vim session which pulls in prove's output that was saved using prove's --archive option. The reason for re-displaying prove's output in vim is so you can have it syntax highlighted to a high degree to help you pick out the relevant files and line numbers where errors occurred, as well as easily pick out debug information and other useful output. After the test script's output gets loaded into vim, focus is automatically returned back to your test file in the pane on the left. Once errors and warnings are fixed up, you can code some more and then hit <F7> again to start the process over.

    Ingredients needed

    • vim text editor
    • tmux terminal multiplexer
    • log4perl module (optional)
    • Test::More module plus other test modules you may desire
    • A simple bash script
    • simple vim scripts that go into the .vimrc file
    • tmuxify vim plugin
    • vim file for syntax highlighting of test output
    • A wide monitor to accommodate a wide terminal window (optional)

    I won't go into any detail on getting any of these components installed or how they work. Google is your friend.

    vim config

    Here are the needed lines to get your vim files working with the tmuxify plugin once it's installed. Replace <your_home_directory> in the last line with something suitable for your machine. If you don't have a wide terminal, or want your output to appear along the bottom of the your test script instead of next to it, change the -h in the third line to a -d.

    nmap <F7> :w<CR>\mk:q!\ms<CR>\mq\mr imap <F7> <ESC>:w<CR>\mk:q!\ms<CR>\mq\mr let g:tmuxify_custom_command = 'tmux split-window -h' let g:rel_file_name = @% let g:tmuxify_run = { 'perl': '<your_home_directory>/run_tests.sh ' . +g:rel_file_name }

    vim syntax highlighting file

    This is what makes the output of your test code super readable. In your .vim directory, create a new directory called syntax (if it doesn't already exist) and place the following code into a file called test.vim. You can, of course, tweak and improve this to your liking. I am not an expert at vim syntax highlighting so this can probably be improved and definitely shortened a great deal.

    syn match Good "^ok " syn region okline contains=Good start="^ok" end="\n" syn match builder_line "Builder\.pm line \d\+\." syn match lineno "line \d\+\.*\n" syn match line_no "Line \d\+\:" syn match error_msg "^# \t.*at"hs=s+3 syn match perl_lib "perl_lib\/.*\.pm"hs=s+9 syn match file " at [^\/]\+\.p[ml] "hs=s+3 syn match subtest_file "^\s\+#\s\+.*at .*line \d\+\.\n"hs=s+5 syn match test_file "\/[^\/]\+\/t\/.*\.t "hs=s+1 syn match my_error "^[^(ok |not ok |#)].*line \d\+\.\n" syn region not_ok_subtest contains=subtest_file start="^\s\+not ok \d\ ++" end="^\s\+#.*expected.*\n" " end="^\s\+#.*line \d\+\.\n" syn region Bad contains=warning start="^not ok " end="^\ze[^#]"re=e-1, +he=e-1 syn region warning contains=test_file,file,lineno,perl_lib,error_msg,b +uilder_line start="^#\s\+Failed" end="^\ze[^#]"re=e-1,he=e-1 syn match comment "^#.*\n" syn match premature "^# Looks like.*\n" syn region dump start="$VAR\d\+\s=\s"rs=s-1 end=";\n" syn match divider "----*" syn match warn 'WARN\|ERROR' syn match script contains=warn '[A-Z]\{4,5}.*> ' hi Good cterm=bold ctermfg=Green hi divider cterm=bold ctermfg=yellow ctermbg=black hi dump ctermfg=LightBlue hi okline ctermfg=Green hi warning cterm=none ctermfg=Red hi my_error cterm=none ctermfg=Red hi premature cterm=none ctermfg=Red hi failed cterm=none ctermfg=Red hi Bad cterm=bold,underline ctermfg=Red&#9251; hi comment ctermfg=Cyan hi lineno ctermfg=White hi line_no ctermfg=White hi file ctermfg=White hi test_file ctermfg=White hi perl_lib ctermfg=White hi error_msg ctermfg=Green hi builder_line cterm=none ctermfg=Red hi not_ok_subtest ctermfg=Red hi warn ctermfg=Red hi subtest_file ctermfg=White hi script ctermfg=White

    Bash script

    This simple script gets run by tmuxify when you hit the <F7> key. Call the file run_tests.sh and place it into the home directory on your machine (the same directory referenced in the .vimrc file above.

    prove --merge --normalize -v $1 -a test.tgz vim -nR -c ":silent 0read ! tar xfO test.tgz $1" -c ':set nonumber' -c + ':syntax sync fromstart' -c ':set syntax=test' -c ':silent !tmux se +lect-pane -L' !!! PUT A BLANK LINE HERE !!!!

    Note that the 3rd line should be a blank line. For some reason, it seems to be needed to avoid having to hit the return key after the last command is run. And don't forget to chmod the bash file to make it executable.

    Other good stuff

    You will of course need to make sure your test file has use Test::More at the top of the file. Also, I highly recommend the log4perl module to help sprinkle your output with helpful debug output and other useful information that will help you keep track of what your code is doing and how it is behaving.

    That's it. Happy testing and debugging!

    $PM = "Perl Monk's";
    $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate";
    $nysus = $PM . ' ' . $MCF;
    Click here if you love Perl Monks

RFC: My first GitHub contribution
1 direct reply — Read more / Contribute
by dollar_sign
on Mar 05, 2017 at 17:34

    Hi there everyone, I made my first contribution to an open source project today. Well, to be honest, the project was just a list of links and the contribution was just a script that most of you could have hacked together in 10 minutes... But I felt really good about it :D.

    Why did I make this script?

    I am a frequent visitor of the programmer discord server, which is a discord server for programmers (surprise, surprise). This server was started by a couple of programming enthusiasts over at reddit. It has grown out to a huge community of 5000+ programmers, with at least 1000 programmers concurrently online at any time of the day to discuss programming with and to get real time support from when you get stuck. One of the channels on this server is titled Collaborations-and-projects, and someone posted there that he had made a list of resources for people who want to learn about programming/computer science. The only problem was that now that he had made this list, it was going to be a huge pain to sort all of the resources by name in alphabetic order per category. To which my response was, of course, "THIS IS A TASK FOR PERL". So I asked for the link to his GitHub repo, put this script together, and let it run through all of the files in the repo, after which I committed all the changes.

    links I would like to share

    • The link to join the programmer discord: https://discord.gg/9zT7NHP At the moment there is no Perl channel there yet, and when I asked why, they told me there was no interest!! So please, if you feel like it, join the server so that there is yet another place to discuss Perl in this world :)
    • The link to the GitHub repository I contributed to: https://github.com/TumblrCommunity/coding-masterpost

    Now, as I am pretty new to Perl (and just started programming this year) and I'm sure that my code is pretty clunky because of that, I figured that it might be a good idea to ask for some comments on the first 30+ line program I have ever written in Perl. Are my comments on point for example? Should I comment more/less? And could my code have been shorter? Please feel free to criticize every single character and white space in my script! It won't hurt me (much).

    First I'll give you an idea of the way the files are formatted; The <> tags are not in the real files!

    # <CATEGORY HEADER> [<name of resource>] (www.hyperlink.com) some text about the resource [<name of resource>] (www.hyperlink.com) some text about the resource [<name of resource>] (www.hyperlink.com) some text about the resource #<HEADER OF NEXT CATEGORY> [<name of resource>] (www.hyperlink.com) some text about the resource [<name of resource>] (www.hyperlink.com) some text about the resource

    Now my $code:

    Don't mind me, just another IT student wandering around the monastery in awe of its wonders.
Resolving issues while installing Net::SSH2 on Ubuntu 16.04.2
1 direct reply — Read more / Contribute
by pritesh_ugrankar
on Mar 04, 2017 at 09:28

    Hi,

    I wanted to try out plenv and install modules without "disturbing" system perl. Followed the instructions and plenv installed without any issues. While installing the Net::SSH2 modules, I kept getting errors. The steps given below are for those who might face similar issues. Hope someone here finds it helpful.

    Apologies if this is posted in wrong section. Just wanted to post this to help those who might be in a similar situation

    Before you install Net::SSH2, install the following:

    sudo apt install libssh2-1-dev sudo apt install openssh-server sudo apt install zlib1g-dev

    Once these are installed successfully, then proceed with installing the Net::SSH2 module. Since I had earlier installed plenv, it seems to have installed cpanm in my home directory as shown below.

    pritesh@thinkpad:~$ which cpanm /home/pritesh/.plenv/shims/cpanm pritesh@thinkpad:~$

    Then I simply installed Net::SSH2 using the following command

    cpanm Net::SSH2

    Then just to see if all is well, I ran the following command

    pritesh@thinkpad:~$ perl -e "Net::SSH2" pritesh@thinkpad:~$

    Updated as per the error pointed out. Thanks.

    pritesh@thinkpad:~$ perl -e "use Net::SSH2" pritesh@thinkpad:~$

    Indeed all is well.

    Note:- Big thank you to the Strawberry Perl folks. While on Windows, I was using Strawberry Perl and installing a module was trivial. Only upon trying to install the Net::SSH2 module on linux did I understand how much care the Strawberry Perl folks have taken to make things work on Windows.

    Unfortunately I will not be able to go back to Windows on this laptop. After upgrading the RAM, Windows would not boot. Reinstalling the OS also did not help and I kept getting random blue screens, both with Windows 7 and 10. Memory tests ran all fine. So tried Ubuntu 16.04.2 and it seems to have no issues.

Pie Explosion
3 direct replies — Read more / Contribute
by jmlynesjr
on Feb 28, 2017 at 13:15

    The February 2017 issue of Circuit Cellar magazine includes an interview with Eben Upton the head of the Raspberry Pi Foundation.

    The key factoid is that they are shipping 300,000 to 400,000 units per month. A possible large audience for Perl and wxPerl.

    Are there any RPi/Perl books in the works?

    James

    There's never enough time to do it right, but always enough time to do it over...

Holy Crap! Programming Well is Hard Work
4 direct replies — Read more / Contribute
by nysus
on Feb 24, 2017 at 12:50

    As a hobbyist programmer and someone fascinated with the world of programming and learning what I can about it, it strikes me more and more just how obsessive to detail good programmers are. That's never been a strong suit of mine, unfortunately. I'm impatient and I often make wrong and bad assumptions that make it tough for me to write solid code. And I think what I like about programming so much–even though it often humbles me by making me feel like a bit of a dunce–is that it forces me to think like an engineer. But I have to work pretty damn hard at it and the process is slow and frequently frustrating.

    In the programming field, there is an extraordinary amount of information to take in, process, and put into practice. It seems the more I learn, the less I feel like I know. I marvel at the programmers to be able to do that and who have a natural knack for it. I'd like nothing better than to spend 15 hours a day lost in code (which I've been doing lately) but it still sometimes feels like I'm pushing a rock up a mountain. I have a few projects I want to write and write well but I end up getting diverted by having to learn some new skill first. Every day there seems to be countless new idioms, tools, and concepts that I need to learn and put into practice.

    But I'm eager for the day when it all just clicks, when I can look at someone else's piece of code and read it like a newspaper and know everything that's going on with it (or at least have a pretty good idea). It's frustrating to go down three dead ends or spend an hour figuring out why your code won't do what you want because of a stupid mental error. I'm guessing most programmers like me have gone through a similar phase where they can write code that gets simple stuff accomplished but aren't good enough to take on a really large or complex project.

    Anyway, just needed to vent. I feel better now. And thanks to the Perlmonks who have helped me on my journey toward my goal of achieving programming excellence. I could not keep pushing on this rock without you.

    $PM = "Perl Monk's";
    $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate";
    $nysus = $PM . ' ' . $MCF;
    Click here if you love Perl Monks

Look at the next value of hash when sorting by values
2 direct replies — Read more / Contribute
by Cow1337killr
on Feb 13, 2017 at 12:15
    #!/usr/bin/perl # Program name: next-value-of-hash.pl Run it, thusly: perl next-value +-of-hash.pl Look at the next value of hash when sorting by values # From perlmonks Chatterbox 20170213 reply by [ambrus] # [stu96art] I am hoping to get some help with hashes. Working on l +ooking at the next value when sorting by values, but don't know how t +o reference it. # [stu96art] My code is on my scratchpad: /padstu96art # [ambrus] stu96art: perhaps try to first assign the sorted key lis +t to an array variable, then iterate through that array with indexes # [stu96art] Gotcha. That makes sense. Appreciate the help. # [ambrus] like my@s = sort keys %a; for my$i (keys@s) { print "cur +rent: $s[$i] => $a{$s[$i]}, next: ", ($i+1<@s ? "$s[$i+1] => $a{$s[$i ++1]}" : "none"); } # [stu96art] Thanks again. I will work on that. use strict; use warnings; # Example hash from https://perlmaven.com/perl-hashes my %color_of = ( "apple", "red", "orange", "orange", "grape", "purple", "tomato", "red", "lettuce", "green", "peanut", "tan", ); my @s = sort keys %color_of; for my $i ( keys @s ) { print "current: $s[$i] => $color_of{$s[$i]}, next: ", ( $i + 1 < @s ? "$s[$i+1] => $color_of{$s[$i+1]}" : "none" ); print "\n"; } __END__

    Close readers will note the following: stu96art specified "when sorting by values".

    It is debatable whether he meant Sort the values of the hash or Sort the hash in alphabetical order of its keys.

    https://perlmaven.com/how-to-sort-a-hash-in-perl is a good place to start to learn this particular subject.

Working Solo and in a Team
3 direct replies — Read more / Contribute
by eyepopslikeamosquito
on Feb 13, 2017 at 04:29

    I've worked solo, and in teams, for many years now, and in many different organisations. Yet I still feel dissatisified somehow.

    While I enjoy working alone -- especially when I'm in the zone -- I have to acknowledge that individuals working alone in my organisations have produced some pretty quirky and unmaintainable code over the years. At least, that's what I've seen.

    Moreover, I write better and more relevant code not when working solo, but when receiving regular feedback from others.

    Sadly, I've found that working closely with others can be difficult and stressful, especially when personality clashes arise. The tragic human condition -- as I'm reminded every day when reading the news -- is that there are so many factors that can cause conflict in teams: gender, politics, religion, baby boomers vs generation-y, introvert versus extrovert, perl vs java, the list goes on and on.

    Pair Programming

    One of the drawbacks of being chosen to lead humanity's push to become an interplanetary species is having to give up your privacy. "You could hear everything else that happened in the dome, and they could hear you," Ms Johnston recounted.

    -- What it's like to spend a year pretending to live on Mars (news article)

    I've tried pair programming eight hours a day and hated it. Like the budding Mars astronauts, I discovered how much I value my privacy.

    High Performing Teams

    Despite my unfortunate pair programming experiences, I acknowledge the crucial importance of teamwork and effective teams. Though I've rarely experienced it personally, I know that the elusive harmonious, high performing team is certainly possible. How best to achieve it?

    According to a recent study at Google the five keys to a successful team are:

    • Psychological safety: Can we take risks on this team without feeling insecure or embarrassed?
    • Dependability: Can we count on each other to do high quality work on time?
    • Structure & clarity: Are goals, roles, and execution plans on our team clear? Do we have an effective decision-making process?
    • Meaning of work: Are we working on something that is personally important for each of us?
    • Impact of work: Do we fundamentally believe that the work we're doing matters?

    Some ideas you might try from the Google study to improve teamwork:

    • Google's gTeams exercise: a 10-minute pulse-check on the five dynamics above, a report that summarizes how the team is doing, a live in-person conversation to discuss the results, and tailored developmental resources to help teams improve.
    • Google found that teams who adopted a "new group norm" improved more than other teams. An example of a new group norm is "Kick off every team meeting by sharing a risk you took in the previous week".

    Feedback

    I'd love to hear of your experiences. What's been your workplace experiences, both working solo, and in a team? Which do you prefer? I'm especially interested to learn what you feel is the key to working in an effective team.

    References

Mining and war as a metaphor for programming
2 direct replies — Read more / Contribute
by nysus
on Feb 11, 2017 at 08:58

    Heads up, this doesn’t have much to do with Perl but, in my highly unqualified opinion, PerlMonks are the smartest programmers around (at least maybe the only smart ones who will give me the time of day (barely)) so I thought I’d post this here.

    So anyway, I had a few beers last night and a couple of cocktails to boot and I started getting a little philosophical about programming. What is it programming, exactly? I decided the best definition I could come up with is that it is “the automation of the creation and extraction of meaning from the world.” It’s basically a mining exercise where the “natural resource” is meaning.

    Once the meaning is extracted, it can be used to help guide decisions, help increase efficiency of processes (including the mining of more meaning even faster and more automatically), or help us uncover how the universe works as in the case of scientific research.

    Then I got to wondering where programmers fit into this cosmic extraction of meaning. It struck me that programmers are like foot soldiers. Those who employ soldiers and direct them are like generals. The generals would be equivalent to the business leaders and bureaucrats who make big picture decisions. And then somewhere in the middle are computer scientists, who study the extraction and processing of meaning with computers. The generals rely on the knowledge of computer scientists to determine which strategies to employ to help extract meaning. The computer scientists would be like war strategists, determining the best tools and methods for automating the extraction of meaning.

    Outside of these three major roles are people like IT folks who would be like Seabees; those who set up the infrastructure and equipment needed to process the meaning. The companies that write software workhorses are like defense contractors who manufacture equipment (the tanks, jets, and ships) that do a lot of heavy lifting (IBM, Google, Microsoft, Facebook, Apple, etc.).

    Of course, the lines between these roles are much blurrier than in war. For example, a programmer running a small business writing consumer software is often the general, the foot solider, and the Seabee (probably not so much a war strategist). A consultant who helps businesses develop complex custom software is probably much less of a foot soldier and more of a war strategist.

    My thought is the most valuable programmers are those who have a good idea about what would be of value to leaders, are very familiar with computer science and are highly expert on wielding the most powerful tools used to automate the extraction meaning.

    $PM = "Perl Monk's";
    $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate";
    $nysus = $PM . ' ' . $MCF;
    Click here if you love Perl Monks

How to remove the overlaps (MIRA - Bioinformatics)
No replies — Read more | Post response
by Cow1337killr
on Feb 07, 2017 at 12:27
What killed Perl?
4 direct replies — Read more / Contribute
by Anonymous Monk
on Feb 06, 2017 at 17:07
    Easy. If, instead of focusing on Perl 6, the community had made things like installing Perl web server as easy as installing PHP, Perl5 would still be in top 10 like PHP is. Maybe it is not too late ...
Improve readability of Perl code. Naming reference variables.
7 direct replies — Read more / Contribute
by hakonhagland
on Jan 19, 2017 at 15:05
    Hello Monks!

    I've been learning Perl for some years now. At the same time, moving from writing awk scripts to writing Perl scripts, I have found Perl to be an amazing resource for getting things done.

    Still, I have some minor issues with the language design that I have not yet been able to understand/resolve. This is what I want to discuss here.

    Background

    It sometimes bugs me that it is so difficult to write Perl code that is readable (easy to follow) when working with references. For example, if I see a variable $var in the middle of some code, it can be a scalar variable, a scalar reference, an array reference, a hash reference, and so on. Hence, I often end up guessing or having to scan source code nearby in order to determine the type of the variable. I find this workflow less than optimal. Would it not be better if the variable could (optionally) be made self-documenting with respect to reference type?

    In the book Perl Best Practices, the problem is mentioned in another setting, and the solution suggested is to add the suffix _ref to the variable name. So one could write,

    $var_href = { a => 1 };
    to create a hash ref, and
    $var_aref = [ 1, 2, 3];
    to create an array reference.

    However, a problem with this convention could be that the suffix is not optional. You should not be forced to used the more verbose form of the variable name. I think, the programmer should have a choice to decide whether he finds it advantageous to include the suffix at given place or not. For example, when declaring the variable as

    $var = [ 1, 2, 3 ];
    it is rather obvious that it is an array reference, and there is no need to write:
    $var_aref = [ 1, 2, 3 ];
    The latter is in my opinion too verbose. However, if the reference is just defined as
    my $var;
    it would often be better to include the suffix. If there is no indication on the next lines or so whether $var will be used as an array reference or not, it would be more readable to define it as
    my $var_aref;

    A new idea for reference variable naming syntax

    So this lead me to an idea: Could the postfix dereferencing syntax be extended for this use case?

    The Postfix Dereferening Syntax (PDS) was introduced as experimental in 5.20. And starting from 5.24 it is included in the Perl language by default.

    Currently PDS is used for dereferencing:

    my @array = $var->@*;
    Notice that the PDS includes a star after the sigil. It is a syntax error not to include the star. But let's say for the moment that if the star was omitted, the dereferencing was to be simply ignored instead. So
    my $var->@;
    would mean the same as
    my $var;
    and produce no syntax error.

    Let's denote this new syntax by Optional Postfix Reference Declaration Syntax (OPRDS). So when using OPRDS, should it be entirely up to the user to ensure that he used the correct sigil. For example, if I write

    $var->@ = 12;
    when I really meant
    $var->@ = [ 12 ];
    should it produce a compile time error? I think it would be very helpful if the compiler could use OPRDS to check for consistency. But it might be difficult to implement? I do not know. If it is difficult to implement, some alternatives might be used instead? I don't know much of Perl internals, so this is a point where I need help.

    When I started out with this idea, compile time type-checking was not on my mind at all. But I see now that OPRDS would offer the opportunity for stricter type checking.

    But type checking was not the main issue I wanted to discuss. What I would like to discuss is how to deal with reference variable names. Reading and understanding written Perl code can be difficult since the $ sigil can be used for many data types. How could this situation be improved?

RFC: Module for testing asynchronous event series
No replies — Read more | Post response
by Dallaylaen
on Jan 18, 2017 at 16:57

    Let's say we are going to test a module that is supposed to be run asynchronously - using threads, AnyEvent, or Coro, or some other means. And we need to check that certain events happen in certain sequence, because some of them depend on the others.

    Probably the best way to achieve this would be of course to minimize interdependencies and use mathematically correct synchronization for whatever is left. Of course, that is not always achievable, due to limited time.

    So I'm going to propose a primitive that I think should deal with a huge subclass of such tasks.

    The code goes as follows:

    use Test::AsyncSeq; my $id = Test::AsyncSeq->get_sequence_id; my $id2 = Test::AsyncSeq->get_sequence_id( "frobnicate" ); # would be "frobnicate1" or smth # somewhere in threads/callbacks is_after( $id, "start" ); # elsewhere is_after( $id, "event2", "start" ); # more elsewhere is_after( $id, "event3", "start" ); # finally is_after( $id, "finish", "event2", "event3" );

    The is_after( $id, $event, @dependencies ); passes if and only if:

    • sequence named $id was created;
    • $event was not seen in the sequence yet;
    • all of the @dependencies have been seen at the moment of the call.

    The id is just a string, and is required since Perl is not very good at passing blessed references across threads. And multiple tests MAY be needed in the same script, say to catch a race condition.

    Does such interface make sense? Would it be of use to anyone?

[RFC] Building Regex Alternations Dynamically
5 direct replies — Read more / Contribute
by haukex
on Jan 18, 2017 at 07:57

    Dear Monks, this is a suggestion for a tutorial, any comments or suggestions are welcome. Update 1: Fixed up explanation of metacharacters a bit. Update 2: Implemented some things from kcott's comments. Update 3: Added TL;DR, inspired by LanX.

    TL;DR: The two code samples below are working pieces of code that can be copied into your Perl script and adapted for your purposes.

    I thought it might be useful to explain the technique of building regular expressions dynamically from a set of strings. Let's say you have a list of strings, like ("abc", "def", "ghi"), and you want to build a regex that matches any of them, like /(?:abc|def|ghi)/. This also works well with s/search/replacement/ if you have a hash where the keys are the search strings and the values are the replacements, as I'll show below. If you're uncertain on some of the regex concepts used here, like alternations a|b and non-capturing groups (?:...), I recommend perlretut.

    First, the basic code, which I explain below - note the numbering on the lines of code.

    my @values = qw/ a ab. d ef def g|h /; my $regex_str = join '|', # 4. map {quotemeta} # 3. sort { length $b <=> length $a } # 2. @values; # 1. my $regex = qr/$regex_str/; # 5. print "$regex\n"; # 6.
    1. We begin with the list of strings stored in the array @values. This could be any list, such as a literal qw/.../, or return values from functions, including keys or values.
    2. We sort the list so that the longer strings appear first. This is necessary because if our regular expression was /foo|foobar/, then applied to the string "foobarfoofoobar", it would only match "foo" three times, and never "foobar". But if the regex is /foobar|foo/, then it would correctly match "foobar", "foo", and again "foobar".
    3. Next, we apply the quotemeta function to each string, which escapes any metacharacters that might have special meaning in a regex, such as . (dot, matches anything) or | (alternation operator). In our example, we want the string "g|h" to be matched literally, and not to mean "match g or h". Unescaped metacharacters can also break the syntax of the regex, like stray opening parentheses or similar. Note that quotemeta is the same as using \Q...\E in a regex. As discussed here, you should only drop \Q...\E or quotemeta in the case that you explicitly want metacharacters in your input strings to be special, they come from a trusted source, and you are certain that your strings don't contain any characters that would break your regular expression or expose security holes!
    4. Then, we join the strings into one long string using the regex alternation operator |. If you want to use this string without the qr// of step 5, note this potential pitfall: For example, if your input is qw/a b c/, then at this point your string will look like $regex_str="a|b|c". Then, saying /^$regex_str$/ will be interpolated to /^a|b|c$/, which means "match a only at the beginning of the string, or b anywhere in the string, or c only at the end of the string", which is probably not what you meant, you probably meant /^(?:a|b|c)$/, that is /^(?:$regex_str)$/!
    5. Finally, we compile the regular expression using qr//. This is not strictly necessary, you could just interpolate the string you've just created into a regex, but I prefer to turn them into regex objects explicitly. It also has the advantages that you can apply modifiers such as /i to the regex in a (IMO) more natural way, and that qr// implicitly adds a non-capturing group (?:...) around the regex, which takes care of the problem described in step 4 above.
    6. When we print the regular expression, we see that it has become this:
      (?^:ab\.|def|g\|h|ef|a|d)
      You can now use this precompiled regular expression anywhere, as explained in Compiling and saving regular expressions and perlop, such as if ($input=~$regex) { ... } or while ($input=~/$regex/g) { ... }.

    Search and Replace Using a Hash

    my %map = ( a=>1, ab=>23, cd=>45 ); # 1. my $regex_str = join '|', # 2. map {quotemeta} sort { length $b <=> length $a or $a cmp $b } # 3. keys %map; my $regex = qr/$regex_str/; print "$regex\n"; # 4. # Now, use the regex my @strings = qw/ abcd aacd abaab /; # 5. for (@strings) { my $before = $_; s/($regex)/$map{$1}/g; # 6. print "$before -> $_\n"; # 7. }
    1. This is the hash in which the keys are the search strings, and the values are the replacements. As above, this can come from any source.
    2. This code to build the regex is mostly the same as the above, with differences noted here.
    3. Instead of only sorting by length, this sort first sorts by length, and sorts values with the same length with a stringwise sort. While not strictly necessary, I would recommend this because hashes are unordered by default, meaning that your regex would be in a different order across different runs of the program. Sorting the hash keys like this causes the regex to be in the same order in every run of the program.
    4. We print the regex for debugging, and see that it looks like this: (?^:ab|cd|a)
    5. These are the test strings we will apply the regular expression against.
    6. This is the search and replace operation that matches the keys of the hash, and as a replacement value gets the corresponding value from the hash. Note that the /g modifier is not strictly required (s///g will replace all matches in the string, not just the first), and you can adapt this regex any way you like. So for example, to only make one replacement anchored at the beginning of the string, you can say s/^($regex)/$map{$1}/;.
    7. The output of the code is:
      abcd -> 2345 aacd -> 1145 abaab -> 23123

    Hope this helps,
    -- Hauke D

URL encoding and decoding
No replies — Read more | Post response
by $h4X4_&#124;=73}{
on Jan 12, 2017 at 06:33

    While testing a module I found a bug in the way it encodes a URL. So I hit the web to find out why.
    The subroutines it uses for encoding and decoding where very old and had many more bugs then the one I found, so I installed URL::Encode and because the module complained I then installed URL::Encode::XS also.

    I used URL::Encode to test the two output and fix the broken code, because most of the time using a cpan module just slows the main project down a lot when the included modules are providing a very small chunk of code.

    So my fix for the broken URL encode and decode is below and outputs the same as URL::Encode.
    It looks like it would be a lot faster then including a module (URL::Encode) to do the same actions.

    sub url_encode { my $rv = shift; $rv =~ s/([^a-z\d\Q.-_~ \E])/sprintf("%%%2.2X", ord($1))/geix; $rv =~ tr/ /+/; return $rv; } sub url_decode { my $rv = shift; $rv =~ tr/+/ /; $rv =~ s/\%([a-f\d]{2})/ pack 'C', hex $1 /geix; return $rv; }
    But with URL::Encode::XS module installed the code above is very, very slow.
    This bench script can show the speed difference.
    #!/usr/bin/perl #################### # LOAD CORE MODULES #################### use strict; use warnings FATAL => 'all'; # Autoflush ON local $| = 1; use URL::Encode; use Benchmark qw(cmpthese); my $thing = '%&copy; © <> []"\'=?.-_^&*(){}@#!|,;:`~$/\\ 1 + 2 = 3 1 +s sd sds'; my $thing22 = '%25%26copy%3B+%A9+%3C%3E+%5B%5D%22%27%3D%3F.-_%5E%26%2A +%28%29%7B%7D%40%23%21%7C%2C%3B%3A%60~%24%2F%5C+1+%2B+2+%3D+3+++1s+sd+ +sds'; my $num_of_iters = '1000000'; #################### # RUN BENCH #################### print "\n\nBenchmarking $num_of_iters iterations on Perl $] ($^O)\n\n" +; cmpthese( $num_of_iters, { 'MY::Decoder' => sub { url_decode( $thing22 ); }, 'URL::Decode' => sub { URL::Encode::url_decode( $thing22 ); }, 'MY::Encoder' => sub { url_encode( $thing ); }, 'URL::Encode' => sub { URL::Encode::url_encode($thing); }, } ); print "\n"; my $thing2 = URL::Encode::url_encode($thing); print $thing2."\n"; $thing2 = URL::Encode::url_decode($thing2); print $thing2."\n"; print "\n\n"; my $thing3 = url_encode($thing); print $thing3."\n"; $thing3 = url_decode($thing3); print $thing3."\n"; sub url_encode { my $rv = shift; $rv =~ s/([^a-z\d\Q.-_~ \E])/sprintf("%%%2.2X", ord($1))/geix; $rv =~ tr/ /+/; return $rv; } sub url_decode { my $rv = shift; $rv =~ tr/+/ /; $rv =~ s/\%([a-f\d]{2})/ pack 'C', hex $1 /geix; return $rv; }

Win32::SerialPort finally fixed for 64 bit Perl
No replies — Read more | Post response
by kschwab
on Jan 07, 2017 at 19:01

    Some kind soul finally posted a patch that fixes Win32::SerialPort for 64 bit installations of Perl on Windows.

    The patch is here.

    Thought it might be worth noting here...I can't be the only person that's suffered 32 bit perl on Windows for this reason. This has been broken for quite some time.


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":


  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?
    Username:
    Password:

    What's my password?
    Create A New User
    Chatterbox?
    and all is quiet...

    How do I use this? | Other CB clients
    Other Users?
    Others browsing the Monastery: (5)
    As of 2017-04-29 02:06 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?
      I'm a fool:











      Results (531 votes). Check out past polls.