Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic


( #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
The 10**21 Problem (Part I)
4 direct replies — Read more / Contribute
by eyepopslikeamosquito
on Apr 21, 2014 at 13:01

    When I looked for magic formulae, etc., I would give up after 20 minutes!

    -- Jasper

    Unlike Jasper, I have spent more than 20 minutes searching for magic formulae. Especially ancient Roman ones. I first became aware of them back in 2006 during the Fonality Christmas Golf Challenge where I was astonished by Ton's ingenuity and deviousness in constructing his original HART (Hospelian Arabic to Roman Transform) magic formula.

    Shortly after the Fonality game, hosted an endless competition where you must convert the other way, from Roman to Decimal. By 2009, I had managed to take the lead in all four languages (Perl, Python, Ruby, PHP), as detailed in this series of nodes. And the winning solutions -- in all four languages -- all used (quite different) magic formulae!

    To refresh your memory, the codegolf game rules were essentially:

    Convert a Roman numeral to its integer value. The input numeral, provided on stdin followed by a single newline, is guaranteed to be in the range I to MMMCMXCIX (1 to 3999). For example, given IV on stdin, your program should print 4 to stdout.

    As you might expect, a key component of solutions to this game is mapping individual Roman letters to their decimal equivalents. To help us focus on that, let's define a simpler spec:

    Write a function to convert a single Roman Numeral letter to its decimal equivalent. The function assumes the Roman letter is in $_ and returns its decimal equivalent.

    To clarify, here's a sample (non-golfed) Perl solution:

    sub r { my %h = ( I=>1, V=>5, X=>10, L=>50, C=>100, D=>500, M=>1000 ); return $h{$_}; } print "$_: ", 0+r(), "\n" for (qw(I V X L C D M));
    Running this program produces:
    I: 1 V: 5 X: 10 L: 50 C: 100 D: 500 M: 1000

    Lookup Table vs Magic Formula

    In code golf, there is often a battle between a lookup table and a magic formula. So it proved here. When converting from Roman to Decimal, magic formula trumps lookup table.

    Here are three attempts to solve this problem using a lookup table:

    sub r {%h=(I,1,V,5,X,10,L,50,C,100,D,500,M,1000);$h{$_}} sub r {M1000D500C100L50X10V5I1=~$_;$'} sub r {M999D499C99L49X9V4I=~$_+$'}

    And here are some of my earliest magic formulae from 2007:

    sub r {5**y/VLD//.E.(3*/M/+2*/C|D/+/X|L/)} sub r {1 .E.~-ord()*41%52%5>>y/VLD//} sub r {5**y/VLD//.E.ord()x3%75%50%4} sub r {1 .E.(72^ord)*5/7%5>>y/VLD//} sub r {5**y/VLD//.E.(42^88*ord)%5} sub r {1 .E.(3^77%ord)%7>>y/VLD//}
    Back then, my magic formula searching skills were so poor that I erroneously concluded that the lookup table approach was better. :-)

    Later, when I tackled this problem in Python, I really needed to use each Roman letter once only in the formula, which forced me to explore alternative approaches ... which, in turn, led to still shorter Perl magic formulae, such as:

    sub r {10**(7&69303333/ord)%9995} sub r {10**(7&5045e8/ord)%2857} # needs 64-bit Perl sub r {IXCMVLD=~$_;"1E@-"%9995}
    Back in the good old days, the little search programs that uncovered these solutions took hours to run, not years. :-)

    The long numbers (such as 69303333 above) that began popping up in these formulae were an indication that the ord function didn't scale very well as the required solutions became less probable. Can we find a built-in function better suited to Roman magic formulae? In PHP and Python, yes. In Perl and Ruby, probably not. At least, I don't know of one.

    The PHP built-in md5 function is perfect for Roman magic formulae. Not only does it generate all required digits (0-9), it generates little else (just a-f). Moreover, you can use all 256 characters in a magic formula, compared to just ten (0-9) for ord. To illustrate, in an eight character magic string (for example 69303333), there are just 10**8 combinations available for ord, while there are a mind-boggling 256**8=1.8*10**19 combinations available for md5! This is a huge advantage when searching for highly improbable solutions, as we shall see later.

    The Python hash function is also superior to ord, though not as good as PHP's md5. This is because Python's Unicode and character escaping claptrap limits you to 125 characters (namely ord 1..9,11,12,14..127) that can be used as input to the hash function without special treatment. Still, 125 is a huge improvement over 10! One drawback of hash compared to md5 is that it generates huge numbers, forcing you to waste five strokes with %1001 to trim the generated numbers into the required Roman Numeral range (1-1000).

    In some cases, the Perl crypt built-in could be employed, though it is not well-suited to this specific problem because (unlike md5) it generates many other characters in addition to the desired 0-9.

    To recap, the shortest magic formulae found so far in all four languages (as detailed in this series of nodes) are:

    10**(205558%ord(r)%7)%9995 # Python hash(r+"magicstrng")%1001 # Python (finding magicstrng is the subjec +t of this node!) VLD=~$_*5+IXCM=~$_."E@-" # Perl 10**(7&5045e8/ord)%2857 # Perl (64-bit) IXCMVLD=~$_;"1E@-"%9995 # Perl XCMVLD=~$_;"1E@+"%9995 # Perl (update: Grimy improvement) uppp&md5_hex$_.PQcUv # Perl (needs Digest::MD5 module) 10**(494254%r/9)%4999 # Ruby (no need for explicit ord in this g +ame) md5($r.magicstrng) # PHP (finding magicstrng is an unsolved p +roblem) md5($r.PQcUv)&uppp # PHP wins due to superb mf properties of +md5

    The 10**21 Problem

    There's just no sane regularity in this thing. But in "random" mappings with a very small result set like this, the shortest solution is often to make up some magic formula that has no particular meaning, but just happens to give the wanted result.

    -- Ton Hospel explaining his original decimal-to-roman magic formula

    When Ton Hospel invented magic formulae in golf way back in 2004, he correctly noted that they work best "with a very small result set". Indeed, if there were only five Roman Numeral letters, rather than seven, we would have a straightforward 10**15 problem, rather than a (borderline intractable) 10**21 problem. Why 10**21?

    Suppose you have a magic formula that produces a random number between 1 and 1000. The probability of scoring a (lucky) hit for one numeral is therefore 1 in 1000. Since probabilities multiply, the probability of hitting five out of five numerals is 1 in 10**15, while the chance of hitting all seven Roman Numerals is a daunting 1 in 10**21. Though 1 in 10**21 sounds improbable in the extreme, if you could generate 10**21 combinations, you would not need luck, indeed you would expect to find such an improbable solution. Yet how long would it take to search 10**21 combinations for the elusive (lucky) one?

    Well, if you could perform 10,000 search operations per second, the time required to search 10**21 combinations is a mere 10**21/10000 seconds = 10**17 seconds = 3,170,979,198 years! By the way, this "brute force search infeasibility problem" is why you are asked to create longer and longer passwords, and with a wider range of characters in them, as computer speeds improve. Indeed, Password cracking and magic formula searching are closely related disciplines, the lack of a "codegolf magic formula" wikipedia page notwithstanding. :-)

    To make this theoretical argument more concrete, consider searching for a Roman to Decimal magic formula using the Python built-in hash function. Since this hash function produces very large values, we need to apply %1001 to it so as to produce an essentially random value in the desired 1..1000 range. We might try searching for such a magic formula using a simple Python brute-force search program, such as:

    import time print time.time(), time.clock() for q0 in range(1, 128): for q1 in range(1, 128): for q2 in range(1, 128): for q3 in range(1, 128): for q4 in range(1, 128): for q5 in range(1, 128): for q6 in range(1, 128): for q7 in range(1, 128): for q8 in range(1, 128): for q9 in range(1, 128): magic = chr(q0)+chr(q1)+chr(q2)+chr(q3)+chr(q4)+chr(q5)+chr( +q6)+chr(q7)+chr(q8)+chr(q9) m = hash("M" + magic) % 1001 if m != 1000: continue d = hash("D" + magic) % 1001 if d != 500: continue c = hash("C" + magic) % 1001 if c != 100: continue l = hash("L" + magic) % 1001 if l != 50: continue x = hash("X" + magic) % 1001 if x != 10: continue v = hash("V" + magic) % 1001 if v != 5: continue i = hash("I" + magic) % 1001 if i != 1: continue print "bingo!", q0, q1, q2, q3, q4, q5, q6, q7, q8, q9 print time.time(), time.clock()
    On my machine, this naive brute force search for a ten-character magic string is expected to find a solution in about 52,887,477 years! Note that, with 127 different values for each character in the string, we need a 10-character magic string to give us the required 127**10 = 1.1e21 = 10**21 combinations.

    Rather than give up at this point, I found this "impossible" 50 million year challenge strangely irresistible ... and was eager to learn about any high performance computing techniques required to solve it.

    I get it -- optimization is a fun game ... one can play all day with unrolling loops, peeling away layers of indirection, and so forth to gain cycles, while piddling away time and energy

    -- davido

    Or, as davido puts it, "optimization is a fun game". Well, I enjoy it. So I started by rewriting the above search program in C++, then kept on refining it until I was able to reduce the running time from fifty million years down to only several years and eventually find a solution. This new series of articles describes that endeavour.

    Please note that this series focuses more on High Performance Computing/Supercomputing/Parallel computing in C/C++/Intel assembler than code golf.

PerlBrew (perlbrew list-modules)
No replies — Read more | Post response
by wjw
on Apr 19, 2014 at 12:28
    has a bug(85493) noted in version 0.63 which has yet to be addressed. I spent a good 2.5 hours trying to figure out why 'perlbrew list-modules' didn't return anything. Finally found the the problem in the bug list at RT CPAN. The actual cause of the problem was pointed out Here on github.

    In simple terms: the command 'list-modules' will not work if you are use'ing or have switch'ed to an alias.

    You must use the full name of the Perl dist you are using as is shown in 'perlbrew list' or 'perlbrew available'. (See Update below for alternative)

    Perlbrew is fantastic! (minor rant) It is a bit disappointing that this ticket has been around for 11 months without being addressed. It is not an obvious(to me) issue to find or address. My searches(both here and google) rendered very little. The docs here don't make any mention of this either.
    My hope is that someone may save themselves some time finding this here when faced with this issue.


    Was unsure where to post this, but based on FAQ Re: Posting this seems the best place... please correct me if not.


    Found a workaround listed Stack Overflow which states that when installing a Perl via PerlBrew, one can use the '--as' install option to name the Perl install, accomplishing something like the alias command would. While it is good to know how to work around this problem, I would still rather have the 'alias' command work. I don't always know ahead of time what I might want to name a given install.

    Replaced the  <br> with  <p> for readability.

    ...the majority is always wrong, and always the last to know about it...
    Insanity: Doing the same thing over and over again and expecting different results...
Lotto checker...
3 direct replies — Read more / Contribute
by fishy
on Apr 15, 2014 at 10:41
    or nice map/grep exercise...
    #!/usr/bin/perl use strict; use warnings; my $draw = [ qw( 13 15 18 22 41 48 ) ]; my $bets = [ [ qw( 09 13 18 33 39 42 ) ], [ qw( 02 18 32 36 39 42 ) ], [ qw( 05 12 21 22 28 42 ) ], [ qw( 03 14 18 33 34 36 ) ], [ qw( 15 22 26 41 38 48 ) ], [ qw( 06 14 24 26 42 48 ) ], [ qw( 10 28 30 35 36 43 ) ], [ qw( 03 05 08 14 16 35 ) ], [ qw( 08 18 21 35 46 47 ) ], [ qw( 03 15 22 25 46 48 ) ], [ qw( 01 11 38 44 45 49 ) ], [ qw( 14 23 38 39 48 49 ) ], [ qw( 07 17 21 32 45 48 ) ], [ qw( 07 36 37 39 40 41 ) ], [ qw( 07 12 20 29 36 43 ) ] ]; map { my $bet = $_; my $hits = 0; map { my $one = $_; $hits += grep { $one eq $_ } @$bet; } @$draw; print join $", @$bet, "-->", $hits, $hits > 2 ? "*" : "", "\n"; } @$bets;
-Ofun times
4 direct replies — Read more / Contribute
by raiph
on Apr 12, 2014 at 00:35
    This post is about the immature Perl 6, not the rock solid Perl 5

    In the last few months jnthn has added optimizing stages to the Rakudo/NQP/backends compiler stack. In his latest blog post he outlines these stages and notes some early results from a few things he and timotimo have already done ("Array and hash access is more than 3 times faster, most multi-dispatches are now enormously cheaper").

    There's other news too, so even if you're not ready for -Ofun the linked blog post is still worth a read if you are interested in P6.

RFC: API for declarative parameterized web queries
3 direct replies — Read more / Contribute
by smls
on Apr 10, 2014 at 17:17

    Hello all!

    Since I'm doing web querying/scraping of tabular data in several of my scripts, I want to refactor this functionality into a convenient module, and I would appreciate some input/criticism/wisdom from the other resident monks on that topic... :)

    By "query", I mean a complete recipe for downloading a document from the web and extracting relevant pieces from it using XPath expressions and/or regexes.
    By "tabular data", I mean that when a query is executed, it returns a list of items where each item has the same set of pre-defined "fields".

    The module's API should allow query definitions to be:

    • encapsulated - Everything that defines a particular query, should appear together as one self-contained unit in the user's source code.
    • declarative - Don't make the user write unnecessary boilerplate code or worry about implementation details.
    • reusable - Once a query is defined, it should be very easy for the user to execute it many times with different parameters during the program's execution.
Carrying (mini)CPAN
1 direct reply — Read more / Contribute
by fishy
on Apr 05, 2014 at 10:47
    Thanks to minicpan, I keep a local copy of the latest versions hosted on CPAN.
    Running minicpan weekly, I keep it up to date.
    My .minicpanrc file:
    local: /home/netbook/minicpan/miniCPAN_20140405/ remote: http://your.favorite.cpan.mirror/ also_mirror: indices/ls-lR.gz
    Now, I want to carry my local minicpan keeping it on a memory stick.
    Changing .minicpanrc to:
    local: /media/USB16GB/miniCPAN_20140405/ remote: file://home/netbook/minicpan/miniCPAN_20140405/ also_mirror: indices/ls-lR.gz
    and running minicpan again, sweeps my minicpan onto my stick.
    Now, I can install any module offline (as long as specific version dependencies are satisfied).
    Just mount my stick and either, first time running cpan:
    ... Would you like to configure as much as possible automatically? [yes] ... sites for you? (This means connecting to the Internet) [yes] no ... Would you like to pick from the CPAN mirror list? [yes] no ... Please enter your CPAN site: [] file:///mnt/minicpan Enter another URL or ENTER to quit: [] New urllist file:///mnt/minicpan/ Autoconfiguration complete. commit: wrote '/home/userOne/.cpan/CPAN/' ...
    or by modifying manually ~/.cpan/CPAN/
    ... 'urllist' => [q[file:///mnt/minicpan]], ...
    So, it's easy installing modules on offline systems or installing apps on user (e.g. /home/user) Perls.

    Have fun!

    UPDATE: After discovering how to comment, my .minicpanrc looks like:
    ## web ---> local disk (computer A) #local: /home/netbook/minicpan/miniCPAN_20140414/ #remote: http://your.favorite.cpan.mirror/ #also_mirror: indices/ls-lR.gz ## local disk (computer A) ---> USB local: /media/USB16GB/miniCPAN_20140414/ remote: file://home/netbook/minicpan/miniCPAN_20140414/ also_mirror: indices/ls-lR.gz ## USB ---> local disk (computer B) #local: /home/dan/miniCPAN/miniCPAN_20140414/ #remote: file://media/usb/miniCPAN_20140414/ #also_mirror: indices/ls-lR.gz
Wrong + Right = Even Worse
8 direct replies — Read more / Contribute
by choroba
on Apr 03, 2014 at 09:39
    In a legacy project at work, we have lots of scripts that should in fact be modules. But they declare no package, use the .pl extension and call each other via require. Originally, the full paths were used in require, which constituted one of the obstacles to run the project locally. I replaced all the occurrences of
    require '/path/to/some/';


    use lib '/path/to/some'; require '';

    and I was able to run some of the scripts locally (I had to add some paths to @INC).

    After several days, we noticed some of the scripts failed. I inspected the code and discovered that there was one newer OO module that was written "correctly": it lived in a .pm file and declared a package. It used lib and only required the script names.

    Combining "right" and "wrong" led to "even worse": The OO module required several .pl files. All the subroutines they declared were therefore created in the namespace of the module. Later, when a calling script required the same .pl file, it already existed in %INC, so it was not read again. No import was called anywhere, so the subroutines did not appear in the main:: package.

    Here are sample files so you can try it yourself:

    package module; use warnings; use strict; require ''; subroutine(); warn 'module INC: ', $INC{''}; __PACKAGE__

    #!/usr/bin/perl use warnings; use strict; warn "Loading 1"; sub subroutine { my $file = (caller)[1]; $file =~ s=.*/==; warn 'subroutine defined in ', $file; } subroutine(); 1;

    #!/usr/bin/perl use warnings; use strict; use FindBin; use lib $FindBin::Bin; require ''; use module; warn 'script INC ', $INC{''}; subroutine();


    The Conclusion

    We now have 2 options:

    1. Revert to the original full-path style require with no possibility to run the project locally.
    2. Refactor everything to proper modules. 100,000+ lines.


    I just had an idea: there is a third option. In the OO module, store %INC at the beginning, do all you need, then set %INC back to what it was.

    my %_INC = %INC; # ... %INC = %_INC;
    لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Presenting for your enjoyment: Acme::Thoroughly::Modern::Perl
3 direct replies — Read more / Contribute
by boftx
on Mar 31, 2014 at 23:33

    Its mission: To boldly go where no Perl has gone before!

    Okay, I really wanted a Monty Python reference but I can't come up with a good one right now. :(

    Anyway, coming to a CPAN near you on or about April 1, I give you, Acme::Thoroughly::Modern::Perl!

    package Acme::Thoroughly::Modern::Perl; use strict; use warnings; our $VERSION = 'v0.4.1'; my @now = localtime(); my $yr = $now[5] - 100; # This actually calculates what might be the current minimum version # for years >= 2010. my $mver = ( ( $yr - 10 ) * 2 ) + 10; # just in case there is a boundary case, wrap the test in a do/while # and step it up as needed. my $req_str; do { $mver += 2; # skip over devel releases my $verstr = sprintf( "%0.3f", 5 + ( $mver * .001 ) ); $req_str = "require $verstr"; } while ( eval "$req_str" ); # we need to warn and exit, and NOT die, if we want to more closely em +ulate # what is actually printed for a real failue. we exit with 255 because # that is what perl does. (but override in a test environment since it + would # really suck to have 100% failures on the test matrix!) unless ( $ENV{ATMP_TEST} ) { warn "$@\n"; exit 255; } 1; __END__ =pod =head1 NAME Acme::Thoroughly::Modern::Perl - Go where no Perl has gone before! =head1 SYNOPSIS use Acme::Thoroughly::Modern::Perl; =head1 DESCRIPTION This module allows one to not only be on the bleeding edge of Perl, bu +t to go beyond! Unlike other modules that attempt to include advanced features, there +is no need to specify a given version or release year. Acme is committed +to making the user experience as simple and error-free as possible and automatically does all of this for you! =head1 BUGS ACME is perfection! (Time machine not included.) =head1 AUTHOR Jim Bacon, E<lt>jim@nortx.comE<gt> =head1 COPYRIGHT AND LICENSE Copyright (C) 2014 by Jim Bacon This library is free software; you can redistribute it and/or modify i +t under the same terms as Perl itself, either Perl version 5.010001 or, at your option, any later version of Perl 5 you may have available. =head1 DISCLAIMER Finding a way to use this module, and the consequences of doing so, is + the sole responsibility of the user! =head1 NOTE Acme employs the finest technology available to ensure the quality of +its products. There are no user-servicable parts inside. For your own safe +ty, DO NOT EXAMINE THE CONTENTS OF THIS PACKAGE! =cut
    It helps to remember that the primary goal is to drain the swamp even when you are hip-deep in alligators.
too much free time
3 direct replies — Read more / Contribute
by Anonymous Monk
on Mar 30, 2014 at 15:51
    #!/usr/bin/perl -w use strict; use Email::Send; use Email::Send::Gmail; use Email::Simple::Creator; my $to = $ARGV[0]; my $from = $ARGV[1]; my $pass = $ARGV[2]; my $prog = (split /\//, $0)[-1]; die "\n\tusage: $prog to from pass\n" if(!$to || !$from || !$pass); for(my $i=99; $i>0; $i--){ my $y = $i - 1; my $bottles = 'bottle'; $bottles .= 's' if(!($i == 1)); my $line = "$i $bottles of beer on the wall, " . "$i $bottles of beer, take one down " . "pass it around, $y bottles of beer " . " on the wall.\n"; my $email = Email::Simple->create( header => [ From => $from, To => $to, Subject => '', ], body => $line, ); my $sender = Email::Send->new( { mailer => 'Gmail', mailer_args => [ username => $from, password => $pass, ] } ); print $line, "\n"; eval { $sender->send($email) }; die "Error sending email: $@" if $@; }
"warn" is your best friend
4 direct replies — Read more / Contribute
by snax
on Mar 23, 2014 at 00:14
    It's been nearly ten years since I've said anything here. Somehow, this seems appropriate. I, as many perl hackers have, tend default to quick "print" statements for debugging, only to be shot down when throwing my code at, say, multiple input files at once, for example. No longer. Sure, your code works for *most* of the files, but something is twitchy somewhere. Unicode when you expected ASCII. A mix of LF/CRLF line endings. CR line endings (horrors!) even :) But: if you print where you think things are going wrong, that output goes in the STDOUT queue. The errors that pop when things go wrong happen in the STDERR queue. Hence, "warn" is your bestest friend evars! Trust me on this. You'll get all sorts of win using "warn" context points when you want to debug via print-ing.
Unexpected Python News
8 direct replies — Read more / Contribute
by McA
on Mar 18, 2014 at 04:11

    Hi all,

    just read Garbor's article at yesterday. Plus all the comments to that topic. Nothing really new.

    But today I opened my mailfolder finding the XING newsletter (something like LinkedIn for those who don't know) with the following head line: "Etliche Neuerungen in Python 3.4" (more or less: Several new features in python 3.4).

    The fact that this is actually the subject of the newsletter is really interesting. Besides the fact whether it is important or not to have focus on Perl I'm pretty sure they don't talk about perl when a new Perl release gets out.

    Best regards

    P.S.: It would be interesting to know if Python is a building block at XING.

local::lib - installed by default
3 direct replies — Read more / Contribute
by wmehl
on Mar 11, 2014 at 11:52


    I have a humble request - that the mod local::lib be installed by default at part of CPAN, and not as a separate install. FTP and HTTP are supported "out of the box", we are asking the same for local file. This would allow a local repo of CPAN to be used out of the box via filesystem. This may mean that local::lib no longer exists, it is rolled into the base CPAN code.

    It is a chicken/egg scenario, in order to install from fileshare, you have to have local::lib installed. This requires going to the net for CPAN install, which in our case is not allowed.

    There are work arounds (boot strap, rpm's, etc) but it would be nice to use a local repo native to CPAN out of the box.

    The use case, many servers (1000) in a commercial environment. We have no direct access to the internet, and we have to use a vetted source for CPAN on a local fileshare, not public repos via FTP or HTTP. We could bring up a local HTTP repo, but would prefer to use fileshare

    Thanks for your time an consideration.

Something to meditate on -- the need for a trendy perl?
10 direct replies — Read more / Contribute
by perl-diddler
on Mar 11, 2014 at 11:19
    New version of vim came out for windows... had x86 support -- went to look -- had support for running scripts in Lua, Ruby, Python 2 and Python 3 and no perl.

    I asked if it was an error, and 1 version of perl might not be needed vs. 2 for python.

    The reply I got:

    Dear Linda, It feels like Perl is not very trendy these days. Support for that man +y languages was added because certain popular plugins are written par +tly (or fully) in these languages rather than Vim Script. Python is p +robably the most popular language for extending Vim right now, perhap +s after Vim Script. Ruby goes next, then Lua. But I've never came acr +oss a single plugin which would rely on Perl to be honest. May I ask +why you think that Perl is so important for that Vim distribution? Regards, Alexander
    I doubt benchmarks on multiple thread execution would be considered trendy. Ideas? Thoughts? Examples or counterpoints?
Job With Fun meditation
2 direct replies — Read more / Contribute
by project129
on Mar 09, 2014 at 13:34

    Hello dear monks!

    to be clean in my speech: I just looking for my next telecommute contract with mojolicious and modern (sure depends on what you think modern perl are :)) perl.

    And can not find anything real during last 3 months...

    I am not too greedy (really my hourly rate are not huge),

    I am not (suppose) too lazy or (really suppose :) ) too stupid ... but all proposed projects was related to old cgi style or (not interested) catalist framework :(

    I just wanna my next project to be interesting and use tools that really interesting for me :( Am i dream too much? My wishes (work with fun) not real?

    Please share you experience:
    - are things are going really bad (for my expectations) in perl market? (support old/poor coded apps dominate)
    - any success story?
    - any mojo fans here? :)

    sorry for disturbing you
    with best regards
Announcing Data::DynamicValidator
1 direct reply — Read more / Contribute
by basiliscos
on Feb 20, 2014 at 14:50

    Hello dear monks!

    I regularly met the problem of arbitrary data structures validation, which comes in form either hierarchical config or JSON data. The substantial idea, I got from one of Perl books (I think, this is Hight Order Perl) is the following: the programming languages have tendency to be declarative (i.e. declaring/describing the result, but not the way, how to archive it) but they'll never completely be so, because it seems to be possible only in some local areas.

    When such a local area is been invented, then an extremely useful micro-language will appear. For example, well known regular expressions for the area of arbitrary text data matching/extraction. Another successful example I know is the XPath (or XPointer?) technology for nodes matching in XML documents.

    The last one seems to be very successful in addressing data nodes, that a lot modules appeared, that try to mimic XPath behaviour: Data::DPath, Data::SPath, Data::PathSimple, Class::XPath.

    Well, XML seems to be not too modern, too heavyweight, too enterprisish. So, the minor brother, not overcumbered with namespaces and processing instructions, appeared. It is JSON. The related data extractions/matching technology appeared a bit later; this is JSON pointer: JSON::Pointer, Mojo::JSON::Pointer.

    So, my intention was to develop module, which takes the best from the two worlds: declarative data path selection (a-la JSON Pointer and XPath, but not as simple as the first, and (yet) not as complex and feature-rich as the second), and from the perl (closures, flexibility, application agnosticism, DWIM and DRY principles).

    Here come a few snipplets, from which you can judge about the module

    use Data::DynamicValidator qw/validator/; my $data = { ports => [2222] }; my $errors = validator($data)->( on => '/ports/*', should => sub { @_ > 0 }, because => 'At least one port should be defined at "ports" section', )->errors; if(!@$errors){ say "all ok"; } else { say $_->reason for(@$errors); }

    So, it generally, it uses triplets: on (specifies data path), should (specifies testing perl closure for the results of data path selection), and because (defines human-readable string for administrator to say/describe him the errors in a config, or for HTTP client developer, that something is missing in JSON input data).

    A bit more complex example. Say, you want to check that all declared ports should be available for the application at startup. So, you should do the following:

    use Net::EmptyPort qw(check_port); my $errors = validator($data)->( on => '/ports/*', should => sub { @_ > 0 }, because => 'At least one port should be defined at "ports" section', each => sub { my $port = $_->value; shift->report_error("The port $port is not available for usage") if(!check_port($port)); } )->errors;

    The more complex examples are available in metacpan.

    Constructive critique and suggestions are more then welcome!

Add your 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!
  • 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
  • Outside of code tags, you may need to use entities for some characters:
            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?

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

    How do I use this? | Other CB clients
    Other Users?
    Others chilling in the Monastery: (11)
    As of 2014-07-29 10:48 GMT
    Find Nodes?
      Voting Booth?

      My favorite superfluous repetitious redundant duplicative phrase is:

      Results (214 votes), past polls