Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask


( #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
Opinion: where Perl5 wasn't attractive for me
14 direct replies — Read more / Contribute
by rsFalse
on Nov 19, 2014 at 05:59
    As a newbie, I was dissapointed of:
    1) Perl does not have integer division operator. It must call "use/no integer" to change type. Python has: / - normal division, // - integer division. Sugar.
    To use things such as "ceil/floor", I need to "use POSIX"... Aren't they basic?
    2) It is not problem for me to read dollars in single variables. But it is annoying to read them in some-dimensional arrays (it's noisy), e.g. $array[$i][$j] > $array[$i][$j-1].
    3) It is strongly recommended to "use strict" and make variables "my", then why it is not default? Whay all the code must have so much my my my my...?
    4) Doesn't work - "$_ = reverse"; If in subroutine I can write "$_ = shift", why can't I write so in main (I need to write "$_ = shift @_").
    5) It was strange that "cho(m)p" returns last symbol, not a string w/o last symbol. Ruby's cho(m)p I like more, because I can proceed on string: gets.cho(m)p.split.do_smth...
    6) Can't use blocks using "and/or":
    "$i > 5 or {print "No"; last}" (overcome - "$i > 5 or (print "No"), last"; comma is tighter than "or" but it is counter-intuitive for me)
    7) It was suprise for me that when I used "$hash{length}" it interpreted (length $_) as "length"; Surprise was that ++ has magic (I need to know exceptions) and -- has not; Surprise that "use bigint" doesn't DWIM in some cases.
    8) Difficult exception is that "print (1+1)*2" != "print 2*(1+1)" == "print STDOUT (1+1)*2". I think "print(..." should better wait until the end of block or ";".
Sub signatures, and a vexing parse
2 direct replies — Read more / Contribute
by davido
on Nov 18, 2014 at 16:53

    I was experimenting with the experimental subroutine signatures feature of Perl 5.20 today along with the much maligned prototypes feature of old, and encountered a most vexing parse that interested me. So I wanted to mention it here.

    First, something that is not a problem:

    *mysub = sub : prototype(\@\@) ($left,$right) { ... };

    This parses correctly, and will generate a subroutine named mysub with a prototype of \@\@, and with named parameters of $left and $right, which when called will contain array refs. But this doesn't do much. My real goal was generating several similar subroutines, and called upon map in a BEGIN{ ... } block to do the heavy lifting.

    Here is a contrived example that isn't terribly useful, but that works, and demonstrates the issue:

    use strict; use warnings; no warnings 'experimental::signatures'; use feature qw/say signatures/; use List::Util qw(all); BEGIN { ( *array_numeq,*array_streq ) = map { my $compare = $_; sub :prototype(\@\@) ($l,$r) { @$l == @$r && all { $compare->($l->[$_],$r->[$_]) } 0 .. $#$l } } sub { shift == shift }, sub { shift eq shift } } my @left = ( 1, 2, 3 ); my @right = ( 1, 2, 3 ); { local $" = ','; say "(@left) ", ( array_numeq @left, @right ) ? "matches" : "doesn't match", " (@right)"; }

    Do you see what the problem is? The compiler doesn't care for this at all, and will throw a pretty useless compiletime error:

    Array found where operator expected at line 14, at end of l +ine (Missing operator before ?) syntax error at line 14, near "@\@) " Global symbol "$l" requires explicit package name at line 1 +4. Global symbol "$r" requires explicit package name at line 1 +4. Global symbol "$l" requires explicit package name at line 1 +5. Global symbol "$r" requires explicit package name at line 1 +5. Global symbol "$l" requires explicit package name at line 1 +6. Global symbol "$r" requires explicit package name at line 1 +6. Global symbol "$l" requires explicit package name at line 1 +7. BEGIN not safe after errors--compilation aborted at line 17 +.

    Q: So what changed between the first example, that works, and the second example, that doesn't?

    A: Lacking other cues, the compiler parses  sub : as a label named sub, and thinks that I'm trying to call a subroutine named prototype... and from that point on things are totally out of whack.

    Solution: +. Anything that can remind the parser that it's not looking at a label will do the trick. Parenthesis around the sub : ... construct works, but + is easier, and probably more familiar to programmers who use + to get {....} to be treated as an anonymous hash ref constructor rather than as a lexical block.

    With that in mind, here's code that works:

    use strict; use warnings; no warnings 'experimental::signatures'; use feature qw/say signatures/; use List::Util qw(all); BEGIN { ( *array_numeq,*array_streq ) = map { my $compare = $_; + sub :prototype(\@\@) ($l,$r) { @$l == @$r && all { $compare->($l->[$_],$r->[$_]) } 0 .. $#$l } } sub { shift == shift }, sub { shift eq shift } } my @left = ( 1, 2, 3 ); my @right = ( 1, 2, 3 ); { local $" = ','; say "(@left) ", ( array_numeq @left, @right ) ? "matches" : "doesn't match", " (@right)"; }

    ...or how a single keystroke de-vexed the parse.

    A really simple example that breaks is this:

    my $subref = do{ sub : prototype($) ($s) { return $s; }; # Perl thinks sub: is a lab +el here. };

    I don't really see any way around the parsing confusion in the original version that doesn't work. That perl considers sub : to be a label in the absence of other cues is probably not something that can be fixed without making sub an illegal label. But if I were to file a bug report (which I haven't done yet), it would probably be related to the useless error message.

    This example is fairly contrived, but it's not impossible to think that subs with signatures and prototypes might be generated in some similar way as to fall prey to this mis-parse.

    Credit to mst and mauke on for deciphering why the compiler fails to DWIW.


The First Ten Perl Monks
6 direct replies — Read more / Contribute
by eyepopslikeamosquito
on Nov 16, 2014 at 08:31

    Perl Monks has become a big part of my life, so I thought it would be fun to discover how it come into existence in the first place. In particular, I was eager to learn about its earliest users.

    Please note that I only joined Perl Monks in 2002 and have not met any of the major players from the early days. The content of this node therefore is derived only from independent research and speculation, not first-hand knowledge. So, if any folks who actually witnessed these early historic events are listening, please respond away.

    Perl Monks Origins

    After some random googling on the history of Perl Monks, I hit upon this nugget from, the home page of nate: was my own creation after Slashdot was aquired by It and its sister site, PerlMonks were developed in a CMS I designed called The Everything Engine. The Everything Development Company ran from 1999-2001, and consisted of Ryan "dembones" Postma, Darrick Brown, Tim Vroom, Chromatic, and Robo.
    Apart from using the incorrect case of chromatic, it is possible nate may have forgotten some other Everything developers, or at least interlopers, who appear to be among the first ten registered Perl Monks users, as we shall see later.

    After finding that gem, googling for Slashdot uncovered Rob Malda:

    Rob Malda (born May 10, 1976), also known as CmdrTaco, is an American Internet content author, and former editor-in-chief of the website Slashdot. Malda is an alumnus of Hope College and Holland Christian High School. In 1997, Malda and Jeff Bates created Slashdot while undergraduates of Hope College. After running the site for two years "on a shoestring", they sold the site to, which was later acquired by VA Linux Systems. Malda ran the site out of the SourceForge, Inc. office in Dexter, Michigan.

    and Jeff Bates:

    Jeff Bates, also known as hemos, is the co-founder of Slashdot along with Rob Malda ("CmdrTaco"). Bates graduated from Holland Christian High School in 1994 and received a Bachelor's degree in History from Hope College in 1998.

    and more, including Jonathan "CowboyNeal" Pater.

    Holland Michigan

    Holland is a coastal city in the western region of the Lower Peninsula of the U.S. state of Michigan. It is situated near the eastern shore of Lake Michigan on Lake Macatawa. Holland was settled in 1847 by Dutch Calvinist separatists, under the leadership of Dr. Albertus van Raalte. Dire economic conditions in the Netherlands compelled them to emigrate, while their desire for religious freedom led them to unite and settle together as a group.

    -- Holland Michigan (wikipedia)

    It seems that most of the major players in the formation of Perl Monks hail from this picturesque and charming city, an outpost of Dutch culture and tradition in the American MidWest, with a population of just 33,000!

    Hope College is a private, residential liberal arts college located in downtown Holland, Michigan, United States, a few miles from Lake Michigan. It was opened in 1851 as the Pioneer School by Dutch immigrants four years after the community was first settled.

    -- Hope College (wikipedia)

    Slashdot, and the Everything Engine, were the brainchild of a bunch of creative Hope College students. In particular, Rob "Commander Taco" Malda, Jeff "Hemos" Bates, Nathan Oostendorp aka nate, Everything Engine architect Darrick Brown, and Tim Vroom all attended Hope College in the late 1990s. I'm pretty sure they also attended Holland Christian High School.

    I gleaned this information only from browsing the internet, so if anyone knows different -- or knows of other influential players from the early days who also hail from Holland Michigan -- please let us know.

    Blockstackers Inc

    In particular, I don't know where early Perl Monks developer chromatic resided in the late 1990s; though he lives in Hillsboro, Oregon nowadays, he may have lived in Holland Michigan back then while working for BlockStackers.

    BTW, nate refers to this company not as BlockStackers, but as "Blockstackers Intergalactic (BSI)". This node indicates that the domain was owned by "Blockstackers Inc, 116 E.18th Holland MI 49423". Curiously, Block Stackers Inc still seems to be in business in Holland today, doing Tax Returns. No idea if this is the same BlockStackers Inc that founded Perl Monks however.

    When I was moving to Amsterdam, pschoonveld advised me to demand a certain clause in my contract that translates to "pants not required"

    -- Ovid from (Ovid - be careful around pschoonveld!) Re(3): Favorite Slacking Activity

    Back in the heady Dot-com bubble era, Blockstackers Intergalactic (BSI) certainly seemed like a cool company to work for, located in a beautiful and historic city, with a name derived from Block Stacking Theory, and where wearing pants was optional.

    Top Ten Countdown

    For fun, and using the background information above, let's try to identify the first ten Perl Monks, counting down from ten to one.

    No 10: cinder_bdt

    Node id: 1336; user since: Dec 23 1999 at 22:49 UTC; last here: Jun 15 2005; Experience: 8; 1 post.

    I noticed a cinder_bdt account. This tenth PM user could be Bryan D Thomas based on this twitter account. If anyone knows more, please let us know.

    No 9: yiango

    Node id: 1335; user since: Dec 23 1999 at 22:29 UTC; last here: Mar 01 2000; Experience: 27; 6 posts.

    I suspect yiango is an early Slashdot or Holland Michigan person because in RE: The computer I use most runs... he says "Hey Tim" in response to vroom, indicating he may know vroom personally. Moreover, slasholic is a Perl script written by "yiango" to query slashdot for new articles. I found a circa 1999 yiango everything2 account, yiango sourceforge account and a yiango twitter account. The name "yiango" is obscure to me, but may be related to Cyprus, based on random googling.

    yiango is almost certainly the first "non-insider" Perl Monk, beating cinder_bdt to that honour by just twenty minutes.

    No 8: nate

    Node id: 1316; user since: Dec 23 1999 at 03:36 UTC; last here: Jan 24 2009; Experience: 572; 24 posts.

    Too easy. This is obviously the father of the Everything Engine, Holland Christian High School and Hope College alumnus, Nathan Oostendorp.

    No 7: pschoonveld

    Node id: 1027; user since: Dec 02 1999 at 11:56 UTC; last here: Oct 01 2010; Experience: 695; 29 posts.

    His home node says he is from "Utrecht, The Netherlands". This may well be Patrick Schoonveld, who's linked-in account spookily lists his education as Hope College, Holland Michigan. His CV further lists a stint at SourceForge/Slashdot and indicates he has worked in the Netherlands.

    No 6: sgtbaker

    Node id: 1012; user since: Nov 19 1999 at 02:42 UTC; last here: Feb 18 2000; Experience: 4; 1 post.

    This one is quite a mystery. I found this library link where user "sgtbaker" recommends a couple of Perl books. Apart from that, nothing, nada, zilch. If anyone knows, please let us know.

    Update: Found a sgtbaker user on where his school is listed as Hope College and his company as Everything Development Company.

    No 5: vroom

    Node id: 979; user since: Nov 12 1999 at 05:53 UTC; last here: Jul 04 2013; Experience: 1007430; 607 posts.

    This is obviously Tim Vroom, the primary founder of the Perl Monks web site. Kudos for that, but how on earth did he manage to accumulate over a million experience points?

    No 4: dbrown

    Node id: 859; user since: Oct 28 1999 at 07:37 UTC; last here: Oct 18 2001; Experience: 15; 2 posts.

    This is almost certainly Darrick Brown, Hope College alumnus, outed as an early Everything Developer above by nate.

    No 3: CmdrTaco

    Node id: 857; user since: Oct 27 1999 at 04:21 UTC; last here: Nov 03 1999; Experience: 9; 0 posts.

    Though hardly a prolific Perl Monks user, the nickname indicates this is probably the famous Rob "Commander Taco" Malda, co-founder of Slashdot.

    No 2: CowboyNeal

    Node id: 850; user since: Oct 27 1999 at 02:31 UTC; last here: Jun 28 2000; Experience: 8; 0 posts.

    The nickname suggests that this is Jonathan "CowboyNeal" Pater of Slashdot fame.

    No 1: paco

    Node id: 846; user since: Oct 27 1999 at 01:12 UTC; last here: Oct 27 1999 at 02:16 UTC; Experience: 754; 1 post.

    We have saved the best for last! 754 experience points from just one post! Amazing! The highest rated node of all time! (Update: oops, only 2nd highest after camel code, thanks tye).

    The mysterious paco spent a total of just sixty four minutes at this site, incomprehensibly vanishing fifteen minutes before the second user arrived. paco achieved more in sixty four minutes than most of us do in a lifetime. A living legend. Like many others, I patiently await his return. During my research, there were indications from some that paco may not be a real user. Don't listen to those heretics. paco will return!


    Everything2 References

    Updated Nov 17 2014: Minor corrections and wording changes; Nov 22 2014: Added Everything2 References plus minor update to "Blockstackers Inc" section (no pants required) and mystery sgtbaker user; Nov 23 2014: Added a bit more detail to top ten section, added more References.

The future of Perl?
25 direct replies — Read more / Contribute
by BrowserUk
on Nov 03, 2014 at 23:03

    Does it have one? Discuss.

    I express no opinion, because I'm not looking for an argument. No prompts, cribs or alternatives; because I don't want to influence what if any discussion ensues, one way or the other.

    I'm seeking, if not a consensus; then at least a census. A (possibly anonymous) expression of opinion from as many people who feel that they have a) a vested interest; b) an opinion worth expressing.

    No counter arguments; no condemnations; though I might have follow-up questions; which you are of course, perfectly entitled to ignore.

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
RFC: MooX::Role::Reconstruct (was MooX::Restore)
1 direct reply — Read more / Contribute
by boftx
on Nov 03, 2014 at 01:05

    After quite a bit of playing around I have what I think might be a viable approach:


    Of particular interest is test 05 and 06 in the t/subclasses directory.

    I would appreciate thoughts on how it is implemented, how to improve the documentation, and how to expand the tests. I want to see how it plays with MooX::StrictConstructor in particular, but am unsure just how to include tests for that.

    In the meanwhile, I hope someone finds this of interest. I expect to release it to CPAN within the week unless I receive a reason not to from my fellow monks or one of the Moo demi-gods.

    You must always remember that the primary goal is to drain the swamp even when you are hip-deep in alligators.
How to make a progress counter for parsing HTML with HTML::TreeBuilder
2 direct replies — Read more / Contribute
by ambrus
on Oct 30, 2014 at 12:33

    This is the true story of a trivial bug I made in a perl program yesterday.

    This program parses a 3 megabyte sized HTML file using the HTML::TreeBuilder module. The program takes less than 30 seconds to run, but that'ss still boring to wait and I'd like to see whether it hangs, so I decided to add a progress counter. Now, as I haven't written all of the program yet, much of the time is currently spent in just parsing the HTML file and building a tree representation in memory from it. Thus, I needed a progress counter in the HTML parsing itself (as well as one in the rest of the program).

    Before I added the progress counter, all of the HTML parsing happened in just one call of the HTML::TreeBuilder->parse_file method. If I kept that, if would be difficult to add a progress counter in it. Thus, I changed the code to instead read the HTML file in 64 kilobyte chunks, feed them each to the parser with the HTML::TreeBuilder->parse method, and print progress after each according to how much of the file is read.

    I thus wrote this.

    use HTML::TreeBuilder; my $filename = ...; my $tree = HTML::TreeBuilder->new; { open my $fileh, "<", $filename or die qq(error opening input h +tml file "$filename": $!); binmode $fileh; my $filesize = -s $fileh; while (read $fileh, my $buf, (1<<16)) { $tree->parse($buf); printf(STDERR "Parsing html, %2d%%;\r", int(100*tell($ +fileh)/($filesize+1))); } $tree->eof; print STDERR "Parsing html complete. \n"; }

    This worked fine. I got a comforting progress counter with percentages rolling quickly on the screen.

    Later, however, I wanted to work around a bug in the HTML, namely some missing open tags. This can be done mechanically, because this is a generated HTML file, but it was easier if I could modify the text of the HTML before parsing it to the tree, because otherwise the tree would have a wrong shape that would be difficult to fix.

    Thus, I chose to do some substitution on the text of the HTML before parsing it. This was easier by slurping the whole HTML file and doing substitutions on the whole thing. So I changed the code to slurp the file contents, substitute it, but then I still wanted to feed it to HTML::TreeBuilder in chunks to get a nice progress counter. No big deal, I wrote this.

    use HTML::TreeBuilder; my $filename = ...; my $tree = HTML::TreeBuilder->new; { printf STDERR "Reading html file.\n"; open my $fileh, "<", $filename or die qq(error opening input h +tml file "$filename": $!); binmode $fileh; local $/; my $filec = <$fileh>; eof($fileh) or die qq(error reading input html file); printf STDERR "Substing html file.\n"; $filec =~ ...; my $filesize = length $filec; printf STDERR "Substed html has length %d\n", $filesize; my $filetell = 0; while (my$buf = substr $filec, 0, (1<<16), "") { $filetell += length $filec; $tree->parse($buf); printf STDERR "Parsing html: %2d%%;\r", int(100*$filet +ell/($filesize+1)); } $tree->eof; print STDERR "Parsing html complete. \n"; }

    This didn't work. The progress counter started showing very high numbers, going up to tens of thousands of percents. I stopped the program because I was worried it got into an infinite loop repeatedly parsing the same part of the file over and over again, and will build an infinite tree.

    After a while, I found the problem. It turns out that the HTML was parsed correctly, only the progress was displayed wrong.

    Can you spot the bug? I'll reveal the solution under the fold.

RFC: MooX::Restore
1 direct reply — Read more / Contribute
by boftx
on Oct 28, 2014 at 23:01

    I saw this module come across recently: MooseX::Role::UnsafeConstructable

    I immediately thought of a few use-cases where I want to instantiate an object from, say, a database row but having init_arg => undef, in my Moo code would prevent that.

    As it turns out, it is fairly simple to create a Moo::Role that can provide a new method, possibly named restore that can ignore the init_arg directive and allow one to instantiate a Moo object from a hash or hashref that would otherwise be blocked. A side benefit is that such a method could still call builders and whatnot if needed for attributes that were not stored in the database row.

    My questions are these: a) does anyone else have a similar use-case where it would be handy to do something like my $obj = MyClass->restore( $db_rowref );, bypassing init_arg restrictions, and b) what would be the correct name for such a Role? (I really think "UnsafeConstructable" is a bad choice.)

    I realize there are a few (or more) warts on this, especially where init_arg is used to rename an attribute. I would love to hear thoughts on what one would expect to happen in those cases.

    You must always remember that the primary goal is to drain the swamp even when you are hip-deep in alligators.
RFC: QA Uploads
1 direct reply — Read more / Contribute
by mgv
on Oct 27, 2014 at 17:35

    Debian has a process called "QA uploads" if a package is orphaned1, any Debian Developer can upload a new version of the package without adopting it.

    When adopting a package/module, the adopter feels compelled to fix all bugs, add more tests, clean up everything, etc (otherwise they wouldn't be doing their job as maintainers). The amount of work discourages people from adopting modules.

    With QA Uploads, an interested user can fix that particularily annoying bug without the burden of having to maintain the module.

    Thus, I believe that adding QA uploads to PAUSE would increase the average quality of modules. I haven't thought about implementation details, but I think the PAUSE indexer could simply index any upload of an orphaned module.

    1 Debian / CPAN equivalence:
    O: / OrphanedADOPTME has f/m/c
    RFA: / Request for AdoptionHANDOFF has c
    RFH: / Request for HelpNEEDHELP has c
    QA Uploads are only possible for orphaned packages.
Reanimating regular issue: Indirect Object Notation
2 direct replies — Read more / Contribute
by McA
on Oct 27, 2014 at 06:22

    Hi all,

    as a regular reader of the Perlweekly newsletter I stumbled on this entry in Edition #170: Stop using indirect object notation.

    In the same moment I thought: Didn't I ask something related some time ago? Yes, I did. And I found it: Reference needed.

    So, I bring this to awareness once again.

    The reactions on twitter are interesting. IMHO the very first action that could be taken: Change all (changeable) documentation where new Class is used. Because most people don't care. They're copy&pasting the examples and synopsis of CPAN modules. And you can find this indirect notation on CPAN.


zentara is going bye-bye
8 direct replies — Read more / Contribute
by Anonymous Monk
on Oct 25, 2014 at 14:50
    Hello esteemed monks and nerds out there. I post this anonymously because my computer blew out yesterday, and instead of fixing it, or wasteing bucks on another, I decided to let the computer go. I take this cosmic ray hit on my computer, as a sign from God, that wasteing time on the illusion of programming, is just part of Maya, the Great Illusion. It was great fun and all, and taught me alot, but I'm not staying on this planet, and if the karma associated with computers is bad, then getting rid of my computer is good.

    So, I'm not dead, I'm not fading or slowly iterrating away, I just don't see value in wasting time on an illusion.

    So, as final advice, zentara says seek the Vaikunthas, and remember, I'm not ignoring posts, but if God takes your computer away, what can you do? :-)

Refactoring Perl5 with Lua
1 direct reply — Read more / Contribute
by rje
on Oct 21, 2014 at 14:31

    WARNING: It may be that I'm simply thinking about Parrot in a different way...

    If you've read my previous post on microperl, then you're sufficiently prepared to take this post with a grain of salt. As a brief summary, I'll re-quote something Chromatic wrote to start me thinking about this problem in general:

    "If I were to implement a language now, I'd write a very minimal core suitable for bootstrapping. ... Think of a handful of ops. Think very low level. (Think something a little higher than the universal Turing machine and the lambda calculus and maybe a little bit more VMmy than a good Forth implementation, and you have it.) If you've come up with something that can replace XS, stop. You're there. Do not continue. That's what you need." (Chromatic, January 2013)

    Warning: I've never written a VM or a bytecode interpreter. I have written interpreters and worked with bytecodes before (okay, a 6502 emulator, but that's basically a bytecode interpreter, right?) Just remember that I'm not posting from a position of strength.

    So I found the Lua opcode set, and it seems a good starting point for talking about a small, though perhaps not minimal, Turing machine that seems to do much of what Chromatic was thinking about... except for XS, which I still haven't wrapped my head around.

    Lua has a register-based 35 opcode VM with flat closures, threads, coroutines, incremental garbage collection... and manages to shoehorn in a tail call, a "for" loop, and a CLOSURE for goodness' sake. And some of those opcodes could be "macros" built on top of other opcodes, rather than atomic opcodes (only if speed were unimportant): SUB, MUL, DIV, POW, LE.

    Again, a disclaimer: I haven't been in a compiler construction class for 25 years, and my career has typically been enterprise coding, data analysis, and tool scripting. Regardless, a small opcode set seems to me to be important for portability. And... 35 codes... well, that's dinky.

    I don't assume that Lua's codes are sufficient for Perl... things are likely missing or just not quite right for Perl. But I have to start somewhere, right? And I figure some of you have the right Domain Knowledge to shed some light on the subject. Right?

    There's lots of neat notes in the aforementioned Lua design doc, written in a clear and concise manner. And now for a brief glance at Lua's opcodes:

On optimizing nested loops
3 direct replies — Read more / Contribute
by FloydATC
on Oct 19, 2014 at 06:05

    While working on a complex script doing lookups and searches on a dozen arrays of hashes (each array representing a relational database table) I stumbled across an extremely simple improvement that instantly gave almost twice the performance.

    The original loop looked like this:

    sub filter { my $where = shift; my @in = @_; # This class method is used to filter an array of hashrefs against a + set of criteria defined in $where. # Example: # @matching_hosts = filter( { site => 56, type => 4 }, @all_hosts) +; # In this example, @matching_hosts will only contain those hashrefs +that would return TRUE for the following code: # ($_->{'site'} eq '56' && $_->{'type'} eq '4') # Note that the "eq" and "&&" are implied; no other operators are su +pported. # The order of the array is not affected. my @out = (); foreach my $record (@in) { my $keep = 1; foreach my $field (keys %{$where}) { unless ($record->{$field} eq $where->{$field}) { $keep = 0; last; } push @out, $record if $keep; } } return @out; }

    The rewritten loop looks like this:

    sub filter { my $where = shift; my @in = @_; # This class method is used to filter an array of hashrefs against a + set of criteria defined in $where. # Example: # @matching_hosts = filter( { site => 56, type => 4 }, @all_hosts) +; # In this example, @matching_hosts will only contain those hashrefs +that would return TRUE for the following code: # ($_->{'site'} eq '56' && $_->{'type'} eq '4') # Note that the "eq" and "&&" are implied; no other operators are su +pported. # The order of the array is not affected. my @out = (); # Make one pass per match term foreach my $field (keys %{$where}) { my $value = $where->{$field}; @out = grep { $_->{$field} eq $value } @in; @in = @out; # Prepare for next pass (if any) } return @out; }

    The running times of actual reports dropped from over 4 seconds to less than 2 seconds. Some of that improvement obviously came from using the built-in grep{} function instead of manually checking each value and push()'ing hashrefs to the @out array, but I didn't expect that much of an improvement.

    There had to be a different explanation, and that got me thinking about the cost of setting up and executing a foreach() loop:

    $ cat foreach_inner #!/usr/bin/perl use strict; use warnings; foreach my $foo (1 .. 3) { foreach my $bar (1 .. 10000000) { my $pointless = "$foo.$bar"; } }
    $ time ./foreach_inner real 0m8.975s user 0m8.954s sys 0m0.013s
    $ cat foreach_outer #!/usr/bin/perl use strict; use warnings; foreach my $foo (1 .. 10000000) { foreach my $bar (1 .. 3) { my $pointless = "$foo.$bar"; } }
    $ time ./foreach_outer real 0m14.106s user 0m14.092s sys 0m0.003s

    Both test scripts do the exact same amount of (pointless) work, the difference between the two scripts is that 'foreach_inner' has to execute 9999997 more foreach() loops than 'foreach_outer'.

    Sometimes, even a seemingly pointless improvement can make a significant difference if made in the right place.

    Now, the way filters are specified in $where is pretty much nailed down because that hashref is built and used in a lot of different contexts. I am still looking for a way to express the whole thing as a single grep{} block to eliminate the looping altogether. Maybe tomorrow.

    -- FloydATC

    Time flies when you don't know what you're doing

RFC: Bi-directional multi-client non-blocking TCP server/client
No replies — Read more | Post response
by glenn
on Oct 17, 2014 at 11:45

    I created these two libraries to handle multiple clients connecting to multiple servers. It is designed where the client will send data to a specific server while the server sends updates to all clients. In my case the client is the Tk UI for our testing program which is running on the server and managing test systems. This allows not only remote control of the server but keeps all interested people up to date. The data is passed as XML as it gives nice control structures and the IPs for the sender and receiver can be added from the socket info.

    Perhaps someone can enlighten me, in my original design I used two threads one for RX the other for TX and blocked until action needed to be taken. To accomplish this I had to deconstruct the IO::Select lib so that the INET socket should be shared between the two threads; however, I was never able to successfully store and share the socket. This would further reduce CPU usage by allowing the TX queue and RX socket to block until there was data. I appreciate appreciate any insight.

    If this can be accomplished without threads...

    Update: When the socket is cleanly closed the client does not close the local socket. FIXED

    TESTED: 2 servers, 4 clients

Default Dropdown Value
3 direct replies — Read more / Contribute
by choroba
on Oct 17, 2014 at 03:35
    Recently, I was refactoring a CGI script at work. It contained a subroutine used to determine the default value for a dropdown list:
    sub DefaultHashValue { my %h = @_; my %r = reverse %h; my @k = sort values %h; return $r{ $k[0] } }

    Neat and short, I thought. But wait, what exactly does it do? We pick up the asciibetically first value and find the corresponding key. It took me some time to understand it (yes, I'm tough). Could this code be written in a more speaking way?

    I'd probably write it differently:

    sub sort_keys { my %h = @_; my @s = sort { $h{$a} cmp $h{$b} } keys %h; return $s[0] }

    Our dropdowns vary in size from 2 elements to several hundreds. For pure curiosity (there were no speed problems), I benchmarked the solutions (see below). Interestingly, for lists over 50 elements, the original solution was faster.

    It wasn't so hard to come with a winner. It's still readable, too:

    sub min { my %h = @_; my $min = (keys %h)[0]; $h{$_} lt $h{$min} and $min = $_ for keys %h; return $min }

    Which solution would you use and why? Or, would you use something else? Why? (I stayed with the original).

    For the interested, the full testing and benchmarking code:

    لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
How to Contribute to Perl+Science
4 direct replies — Read more / Contribute
by PerlSufi
on Oct 14, 2014 at 11:37
    Hello Monks,
    After only some minor experience solving Bio Informatics problems using perl, I was wondering how I could contribute to Bio Informatics or science in general with perl.
    Aside from giving a talk about perl and BioInformatics at my local perlmonger's, I am still eager to contribute. I have written small modules that export subs to do basic things like translate RNA strings to protein.
    However, I have not released these to CPAN because CPAN has BioPerl- which may do these things already. From the view of a new comer, BioPerl is a little difficult to work with. I do thoroughly enjoy solving BioInformatics problems with perl- I also have an interest in Astronomy.
    Any insight is greatly appreciated :)

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 contemplating the Monastery: (20)
    As of 2014-11-25 21:07 GMT
    Find Nodes?
      Voting Booth?

      My preferred Perl binaries come from:

      Results (158 votes), past polls