Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer


( #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
Nobody Expects the Agile Imposition (Part IX): Culture
3 direct replies — Read more / Contribute
by eyepopslikeamosquito
on Jun 20, 2015 at 03:40

    In 2008, we were pretty much a Scrum company ... however, a few years later, we had grown into a bunch of teams and we found that some of the standard Scrum practices were actually getting in the way. Rules are a good start, then break them when needed. We decided that Agile matters more than Scrum.

    Autonomy means the squad decides what to build, how to build it, and how to work together while doing it. One consequence of autonomy is that we have very little standardization. When people ask things like which code editor do you use or how do you plan, the answer is mostly depends on which squad. Some do Scrum sprints, others do Kanban ... it's really up to each squad. Instead of formal standards we have a strong culture of cross-pollination; when enough squads use a specific practice or tool, such as git, that becomes the path of least resistance, and other squads tend to pick the same tool.

    Why is autonomy so important? Well, because it's motivating and motivated people build better stuff.

    -- from Spotify Engineering Culture (Part 1) by Henrik Kniberg (0:30-4:40)

    Instead of blindly following Scrum dogma, I advise you to analyse the problems you and your company face daily. Reason about them. Consider applying Agile and Lean principles to them. Experiment to see what works for you and what doesn't.

    After feeling isolated and alone in resisting the Scrum imposition, reading Spotify's story has cheered me up. I've become more hopeful that things will change, that over time more folks will come to see the benefits of greater team autonomy.

    Autonomy and Alignment

    It's kind of like a jazz band, although each musician is autonomous and plays his own instrument, they listen to each other and focus on the whole song together. That's how great music is created. So our goal is loosely coupled but tightly aligned squads.

    Down here is low alignment and low autonomy, a micromanagement culture, no high level purpose, just shut up and follow orders. High alignment and high autonomy means leaders focus on what problem to solve but let the teams figure out how to solve it. Alignment enables autonomy.

    -- from Spotify Engineering Culture (Part 1) by Henrik Kniberg (3:20-3:50)

    For high autonomy to work, you need high alignment. With low alignment, teams simply do whatever they want, with each team going off in a different direction.

    Specialists vs Generalists

    Each system is owned by one squad. But we have an internal open source model and our culture is more about sharing than owning. Suppose squad one here needs something done in system B and squad two knows that code best, they'll typically ask squad two to do it. However, if squad two doesn't have time, then squad one doesn't necessarily need to wait. Instead they're welcome to go ahead and edit the code themselves and then ask squad two to review the changes. So anyone can edit code but we have a culture of peer code review. This improves quality and spreads knowledge. Over time we've evolved design guidelines, code standards, and other things to reduce engineering friction, but only when badly needed.

    -- from Spotify Engineering Culture (Part 1) by Henrik Kniberg (5:10-6:00)

    The basic unit of development is the squad. Because each squad sticks with one mission and one part of the product for a long time, they can really become experts in that area. A tribe is a collection of squads that work in related areas. The chapter is your small family of people having similar skills and working within the same general competency area (e.g. QA or Web Development), within the same tribe. As a squad member, my chapter lead is my formal line manager, a servant leader, focusing on coaching and mentoring me as an engineer, so I can switch squads without getting a new manager. A guild is a more organic and wide-reaching "community of interest", a group of people that want to share knowledge, tools, code, and practices. Chapters are always local to a tribe, while a guild usually cuts across the whole organization. Some examples are: the web technology guild, the tester guild, the agile coach guild. Anyone can join or leave a guild at any time. Most organizational charts are an illusion, so our main focus is community rather than hierarchical structure.

    -- from Scaling Agile @ Spotify (with Tribes, Squads, Chapters and Guilds) (pdf) by Henrik Kniberg & Anders Ivarsson and Spotify Engineering Culture (Part 1) by Henrik Kniberg (7:30-8:50)

    Alistair Cockburn (one of the founding fathers of agile software development) visited Spotify and said "Nice - I've been looking for someone to implement this matrix format since 1992 :) so it is really welcome to see"

    -- from Scaling Agile @ Spotify (with Tribes, Squads, Chapters and Guilds) (pdf) by Henrik Kniberg & Anders Ivarsson

    In learning more about Spotify, I was also glad to learn how they deal with specialization. You see, this tricky topic has been a chronic nuisance for us, for a number of reasons.

    First, code quality. New code written by a generalist, and reviewed by a generalist, is a long term code quality nightmare. Can you imagine what Perl code written by a ten-year Java veteran with a few days of Perl experience looks like? I can because I've seen it. There have been times when I've opened up a Perl file and rolled on the floor laughing because it was clear that whoever wrote it had no understanding of Perl at all.

    Second, employee engagement. Though many programmers are happy to become generalists, a significant minority (including me) are deeply dissatisfied with that role. I derive much more job satisfaction from doing an expert job in something I deeply understand than from "cargo-culting" some code that seems to kinda work even though I lack a deep understanding of why. I find that dissatisfying. I do not want to write Java code that causes my Java expert colleague to roll on the floor laughing.

    Another problem is that system architecture can be compromised if nobody focuses on the integrity of the system as a whole. To mitigate this risk, Spotify have a "System Owner" role. All systems have a system owner, or a pair of system owners (one with a developer perspective and one with an operations perspective is common). They further have a chief architect role, someone who coordinates work on high-level architectural issues that cut across multiple systems.

    Healthy Culture Heals Broken Process

    Trust is more important than control. Agile at scale requires trust at scale. And that means no politics. It also means no fear. Fear doesn't just kill trust, it kills innovation because if failure gets punished people won't dare try new things.

    -- from Spotify Engineering Culture (Part 1) by Henrik Kniberg (12:40-13:00)

    We focus on motivation, community and trust rather than structure and control. Healthy Culture Heals Broken Process.

    -- from Spotify Engineering Culture (Part 2) by Henrik Kniberg (0:40-0:50, 12:00-12:30)

    I've seen first hand how a healthy organisational culture of good communication and continuous improvement can effectively solve process problems.

    I've also seen first hand how a culture of fear and an over-emphasis on control and structure can harm innovation.

    Lean Startup

    We aim to make mistakes faster than anyone else. Continuous improvement, driven from below and supported from above. Failure must be non-lethal and with a "limited blast radius". Lean startup principles: think it, build it, ship it, tweak it. The biggest risk is building the wrong thing. Release first to a small percentage of users, then use A/B testing, then gradually roll out to the rest of the world. Impact is more important than velocity. Innovation more important than predictability.

    -- from Spotify Engineering Culture (Part 2) by Henrik Kniberg (2:00-)

    These are some of the ideas used by Spotify to build and release product. Since there is enough in this installment already, I'll postpone a discussion of Lean startup and related ideas to the next episode.

    Related PM Nodes

    External References

Nobody Expects the Agile Imposition (Part VIII): Software Craftsmanship
4 direct replies — Read more / Contribute
by eyepopslikeamosquito
on Jun 11, 2015 at 05:22

    Long long ago, at an Agile summit in Utah, a group of software industry veterans, frustrated by what they saw as overly heavyweight software processes, concocted the Manifesto for Agile Software Development:

    • Individuals and interactions over processes and tools
    • Working software over comprehensive documentation
    • Customer collaboration over contract negotiation
    • Responding to change over following a plan
    ... and so the "Agile Transformation era" began:

    The Agile Alliance formed, conferences were held, companies went mad wanting a bit of this, everyone was having standup meetings, burndown charts, product backlogs, Agile coaches all over the place, more Agile coaches than developers ... and Post-its, Post-its, Post-its everywhere. The more Post-its you have the more agile you are.

    We spent ten years talking about people, interactions, team building, eliminating waste ... and at some point agile took a detour ... process became more important than technical practices ... everyone went crazy at the Post-it party, three years later they woke up and realised that every two weeks we see the pile of s#?! getting bigger.

    -- from Software Craftsmanship talk by Sandro Mancuso (2:00-5:00)

    Uncle Bob proposed adding the assertion that we value "Craftsmanship over crap" to the manifesto

    -- Uncle Bob, craftsmen and the Agile Manifesto

    Around 2008, some of the original Agile Manifesto-istas, led by Robert C Martin (aka "Uncle Bob"), felt that Agile had gone off the rails, with too much emphasis on process rather than technical practices and code quality. This group felt that Agile projects, every two weeks, relentlessly, steadily, iteratively, were producing more and more crap code. Adding to technical debt. Slowing us down. Though Agile gave good feedback on many things, code quality was not one of them; it is not visible on burndown charts or the Scrum board.

    How does this happen? Well, there seems to be an unwritten law of the Daily Standup that every morning you have to move at least one Post-it note. To comply with this "law", I sometimes pick up the Post-it note I was working on yesterday and move it a few millimeters to the right on the Scrum board while explaining why it is not really done yet. I always feel bad when I do this though; I would much rather proudly proclaim that it is done, so as to publicly show-off how productive I am.

    Sadly, I've occasionally noticed folks succumb to this psychological pressure to proclaim something done when it is not ... resulting in an every increasing pile of poo, as illustrated by Sandro's next (pair programming) anecdote:

    "but what about these names, they don't make sense ... and there's lots of duplication ... and ..." yeah, well as it's almost done now let's just check it in and add that to the technical debt backlog. This was a brand new feature in an agile team! The guy (Sandro was pairing with) was writing brand new code already thinking to add stuff to the technical debt backlog!

    -- from Software Craftsmanship talk by Sandro Mancuso (5:30-6:20)

    How to fix this lamentable state of affairs? The new Software Craftsmanship group chose to add four new Software Craftsmanship principles to the original Agile manifesto, creating a Manifesto for Software Craftsmanship:

    • Not only working software but also well-crafted software. Code we can refactor confidently and without fear.
    • Not only responding to change but also steadily adding value. Not just bug-fixing, but improving code structure, relentlessly keeping it clean.
    • Not only individuals and interactions, but also a community of professionals. Mentoring, sharing, user groups, passion, professionalism.
    • Not only customer collaboration, but also productive partnerships. Not a "manager giving orders to a developer" relationship, rather a partnership of equals built on trust.

    Well-crafted Software

    God forbid that we have one day someone who is a Software Craftsmanship coach ... it is about lead by example, being a mentor ... not about beautiful code, just trying to provide value, not writing crap code for your customers. The lack of craftsmanship can be one of the main causes of failing projects.

    -- from Software Craftsmanship talk by Sandro Mancuso (30:00-31:00)

    Like Sandro, I disagree the view that "Software craftsmen just care about beautiful code". Today, for example, it took me quite a while to figure out why some code that "should" fail was in fact reporting "success". I almost fell off my chair when I finally realized that it was silently catching and throwing away all exceptions! No comment explaining why it would do such a bizarre thing. To me, this sort of sloppiness shows a basic lack of respect for your colleagues; lack of care and comments wastes their time. It is unprofessional. Nothing to do with beautiful code.

    Steadily Adding Value

    After five years, the software is so s#?! that in the beginning it took two days to add a feature a feature of the same size now takes two months ... so they write a brand new one that is as s#?! as the previous one that will also be decommissioned in five years time.

    -- from Software Craftsmanship talk by Sandro Mancuso (17:00-18:00)

    Now the two teams are in a race. The tiger team must build a new system that does everything that the old system does. Not only that, they have to keep up with the changes that are continuously being made to the old system. Management will not replace the old system until the new system can do everything that the old system does. This race can go on for a very long time. I've seen it take 10 years. And by the time it's done, the original members of the tiger team are long gone, and the current members are demanding that the new system be redesigned because it's such a mess.

    -- Robert C Martin in Clean Code (p.5)

    The only way I can see to avoid this sort of fiasco is to to have the discipline to always keep the code clean in the first place, relentlessly refactoring as required every time you add a new feature.

    Productive Partnerships

    As soon as the button was pressed to mute NASA from our meeting, the managers said "we have to make a management decision", said Boisjoly.

    The general manager of Thiokol turned to his three senior managers and asked what they wanted to do. Two agreed to go to a launch decision, one refused. So he (the general manager) turns to him and said "take off your engineering hat and put on your management hat" -- and thatís exactly what happened, said Boisjoly. He changed his hat and changed his vote, just thirty minutes after he was the one to give the recommendation not to launch. I didnít agree with one single statement made on the recommendations given by the managers.

    The teleconference resumed and NASA heard that Thiokol had changed their mind and gave a recommendation to launch. NASA did not ask why.

    I went home, opened the door and didnít say a word to my wife, added Boisjoly. She asked me what was wrong and I told her "oh nothing hunny, it was a great day, we just had a meeting to go launch tomorrow and kill the astronauts, but outside of that it was a great day".

    -- from Remembering the mistakes of Challenger

    As indicated by the appalling "management decision" to launch the Challenger Space Shuttle, the lack of a true partnership, built on trust, between technical folks and management can have truly tragic consequences.

    Under pressure we cut corners ... No one wakes up in the morning and says "today I'm going to screw up, today I am going to write the worst code I can possibly write, I'm going to f#?! up with this company" ... I met some people who did that, but normal people don't do that ... everyone is trying to do a good job.

    The business asks how long is it going to take? ... The pressure we keep talking about, the pressure we put on ourselves ... we think we don't have time, even when we have the power to go to the business and tell them how long something is going to take!

    -- from Software Craftsmanship talk by Sandro Mancuso (7:00-9:00)

    A Community of Professionals

    Researchers (Bloom (1985), Bryan & Harter (1899), Hayes (1989), Simmon & Chase (1973)) have shown it takes about ten years to develop expertise in any of a wide variety of areas, including chess playing, music composition, telegraph operation, painting, piano playing, swimming, tennis, and research in neuropsychology and topology. The key is deliberative practice: not just doing it again and again, but challenging yourself with a task that is just beyond your current ability, trying it, analyzing your performance while and after doing it, and correcting any mistakes. Then repeat. And repeat again. There appear to be no real shortcuts: even Mozart, who was a musical prodigy at age 4, took 13 more years before he began to produce world-class music.

    -- from Peter Norvig's Teach Yourself Programming in Ten Years

    As indicated by Norvig above, it takes time and effort to become an expert, a true software craftsman. There appear to be no real shortcuts. With the current trend towards generalists in agile teams, finding the time to become a craftsman can be problematic as you find yourself constantly switching from one domain to another, from one language to another. This also affects code quality in that most code is being written by generalists, i.e. non-experts. This will be the topic of the next installment in this series.

    Other Articles in This Series

    External References

    Perl Monks References

The sieve of Xuedong Luo (Algorithm3) for generating prime numbers
5 direct replies — Read more / Contribute
by marioroy
on Jun 11, 2015 at 00:34

    Update June 26, 2015: New results using Math::Prime::Util v0.51 at the end of the post.

    Some time ago traveled to an imaginary place filled with prime numbers. In one of the paintings was the following statement. With k initialized to 1, the value alternates from 2 to 1 repeatedly. It was this statement which inspired me to give Algorithm3 a try.

    k = 3 - k;

    There are various prime modules on CPAN. Thus, have no plans to create another. All I wanted to do was to compare the Sieve of Eratosthenes with Algorithm3. I created a local copy of Math::Prime::FastSieve by davido and replaced the primes function.

    Sieve of Eratosthenes

    /* Sieve of Eratosthenes. Return a reference to an array containing a +ll * prime numbers less than or equal to search_to. Uses an optimized s +ieve * that requires one bit per odd from 0 .. n. Evens aren't represente +d in the * sieve. 2 is just handled as a special case. */ SV* primes( long search_to ) { AV* av = newAV(); if( search_to < 2 ) return newRV_noinc( (SV*) av ); // Return an empty list ref. av_push( av, newSVuv( 2UL ) ); // Allocate space for odd numbers (15 bits per 30 values) sieve_type primes( search_to/2 + 1, 0 ); // Sieve over the odd numbers for( sieve_size_t i = 3; i * i <= search_to; i+=2 ) if( ! primes[i/2] ) for( sieve_size_t k = i*i; k <= search_to; k += 2*i) primes[k/2] = 1; // Add each prime to the list ref for( sieve_size_t i = 3; i <= search_to; i += 2 ) if( ! primes[i/2] ) av_push( av, newSVuv( static_cast<unsigned long>( i ) ) ); return newRV_noinc( (SV*) av ); }

    Sieve of Xuedong Luo (Algorithm3)

    /* Sieve of Xuedong Luo (Algorithm3). Return a reference to an array * containing all prime numbers less than or equal to search_to. * * A practical sieve algorithm for finding prime numbers. * ACM Volume 32 Issue 3, March 1989, Pages 344-346 * * * Avoid all composites that have 2 or 3 as one of their prime factors * where i is odd. * * { 0, 5, 7, 11, 13, ... 3i + 2, 3(i + 1) + 1, ..., N } * 0, 1, 2, 3, 4, ... list indices (0 is not used) */ SV* primes( long search_to ) { AV* av = newAV(); if( search_to < 2 ) return newRV_noinc( (SV*) av ); // Return an empty list ref. sieve_size_t i, j, q = (sieve_size_t) sqrt((double) search_to) / 3 +; sieve_size_t M = (sieve_size_t) search_to / 3; sieve_size_t c = 0, k = 1, t = 2, ij; // Allocate space. Set bits to 1. Unset bit 0. sieve_type primes( M + 2, 1 ); primes[0] = 0; // Unset bits greater than search_to. if ( 3 * M + 2 > search_to + ((sieve_size_t)search_to & 1) ) primes[M] = 0; if ( 3 * (M + 1) + 1 > search_to + ((sieve_size_t)search_to & 1) ) primes[M + 1] = 0; // Clear composites. for ( i = 1; i <= q; i++ ) { k = 3 - k, c = 4 * k * i + c, j = c; ij = 2 * i * (3 - k) + 1, t = 4 * k + t; if ( primes[i] ) { while ( j <= M ) { primes[j] = 0; j += ij, ij = t - ij; } } } // Gather primes. if( search_to >= 2 ) av_push( av, newSVuv( 2UL ) ); if( search_to >= 3 ) av_push( av, newSVuv( 3UL ) ); for ( i = 1; i <= M; i += 2 ) { if ( primes[i] ) av_push( av, newSVuv(static_cast<unsigned long>(3 * i + 2)) +); if ( primes[i + 1] ) av_push( av, newSVuv(static_cast<unsigned long>(3 * (i + 1) ++ 1)) ); } return newRV_noinc( (SV*) av ); }

    Below is the time taken to find all prime numbers smaller than 1 billion.

    my $primes = primes( 1_000_000_000 ); Sieve of Eratosthenes 4.879 seconds Sieve of Xuedong Luo 3.751 seconds There are 50,847,534 prime numbers between 1 and 1 billion.

    I was so fascinated by Algorithm3 that I decided to parallelize it. It took me 5 weekends just to get the math to work. But I wanted faster and placed it aside. Two years later tried again and created Sandboxing with Perl + MCE + Inline::C. Also, tried Math::Prime::Util by Dana Jacobsen and primesieve by Kim Walisch.

    Testing was done on a Haswell Core i7 Macbook Pro running at 2.6 GHz configured with 1600 MHz memory.

    # # Count primes # perl 1_000_000_000 Prime numbers : 50847534 Compute time : 0.146 sec perl 1_000_000_000 Prime numbers : 50847534 Compute time : 0.064 sec perl 1_000_000_000 Prime numbers : 50847534 Compute time : 0.024 sec # # Sum primes ( 203_280_221 prime numbers ) # perl 4_294_967_296 --sum Sum of primes : 425649736193687430 Compute time : 1.082 sec perl 4_294_967_296 --sum Sum of primes : 425649736193687430 Compute time : 0.369 sec perl 4_294_967_296 --sum Sum of primes : 425649736193687430 Compute time : 2.207 sec # # Print primes ( 2.0 GB, beware... ) # perl 4_294_967_296 --print >/dev/null Compute time : 2.071 sec perl 4_294_967_296 --print >/dev/null Compute time : 1.395 sec perl 4_294_967_296 --print >/dev/null Compute time : 13.470 sec

    Fast is possible in Perl. Thus, Perl is fun. One is not likely to print that many prime numbers. Math::Prime::Util is powerful with many features. Algorithm3 was mainly an exercise exploring Perl + MCE + Inline::C possibilities.

    Update June 26, 2015 using Math::Prime::Util v0.51

    The mce-sandbox was updated to call the new sum_primes/print_primes functions in Math::Prime::Util v0.51 for the example.

    Count primes $ perl 4294967296 Prime numbers : 203280221 Compute time : 0.623 sec $ perl 4294967296 Prime numbers : 203280221 Compute time : 0.252 sec $ perl 4294967296 Prime numbers : 203280221 Compute time : 0.210 sec Sum of primes $ perl 4294967296 --sum Sum of primes : 425649736193687430 Compute time : 1.090 sec $ perl 4294967296 --sum Sum of primes : 425649736193687430 Compute time : 0.367 sec $ perl 4294967296 --sum Sum of primes : 425649736193687430 Compute time : 0.768 sec Print primes ( outputs 2 GB containing 2032802221 prime numbers ) $ perl 4294967296 --print >/dev/null Compute time : 2.086 sec $ perl 4294967296 --print >/dev/null Compute time : 1.397 sec $ perl 4294967296 --print >/dev/null Compute time : 1.925 sec

    Kind regards, Mario

A "Fun"ctional Attempt
2 direct replies — Read more / Contribute
by withering
on Jun 04, 2015 at 04:14

    Perl is somewhat functional itself -- if the concept, "functional", which we're talking about, mainly means using functions as first-class objects instead of wiping almost all side effects out. However, lacking of sugar such as useful prototypes, pattern matching, or list comprehensions makes Perl less attractive in some functional situation (for fun, perhaps).

    There are a few attempts I made to achieve a better experience when programming perl for fun. For example:

    #!/usr/bin/env perl use HOI::Comprehensions; use HOI::Match; sub slowsort { HOI::Match::pmatch( 'nil' => sub { [] }, 'pivot :: unsorted' => sub { my $left = HOI::Comprehensions::comp( sub { $x }, x => $un +sorted )->( sub { $x <= $pivot } ); my $right = HOI::Comprehensions::comp( sub { $x }, x => $u +nsorted )->( sub { $x > $pivot } ); [ @{slowsort($left->force)}, $pivot, @{slowsort($right->fo +rce)} ] }, )->(@_) } my $res = slowsort [3, 4, 1, 2, 5, 6]; print @$res, "\n";

    where HOI::Match and HOI::Comprehensions are used to give a simple description of the whole computation. It should be noted that the code is not so strict since it assumes the existence of local variables. Scopes are dynamic, and bound variables are bound by names, as the ones in a typical lambda calculus theory.

    It is still not clear to me whether such sugar ideas are welcomed or not. Any suggestion or criticism is welcomed. I am looking forward for your replies.

Happy Monk day. (To me!)
12 direct replies — Read more / Contribute
by BrowserUk
on Jun 03, 2015 at 22:20

    I just realised that it's 13(*) years to the day since I posted this. We all start somewhere. I've been here almost every day since.

    *13. Is this the year it all goes wrong?

    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". I'm with torvalds on this
    In the absence of evidence, opinion is indistinguishable from prejudice. Agile (and TDD) debunked
Net::FTP fail workaround
1 direct reply — Read more / Contribute
by kurgan
on Jun 03, 2015 at 07:50

    I ran into an issue where Net::FTP was failing at random while connecting many times over the life of a script. I searched for a solution only to find that others were having similar issues. It seems that this excellent module does not actually check to see if the port that is used for connection is working correctly before forging on. The only way around it (that I have found) was to check for the error and reconnect on-the-fly until a working port has been found. It is not a perfect solution as it takes extra resources that could be used elsewhere if the error check was done at the module level, but it has worked well for me so far.

    I just thought others might find this of some help if they find themselves in the same situation. I was not really sure where to post this, so I asked on the CB and pointed here (thank you all for the help!). If you all find this helpful at all, please share it with others at your pleasure.

What's new in ECMAScript6, or: Oh no! Don't steal syntax from Perl!
4 direct replies — Read more / Contribute
by FreeBeerReekingMonk
on May 29, 2015 at 12:49

    Harmony... that's what the upcomming JS is called. It has some new syntax... and it's perl syntax... but does something totally different! So let me show you why I will be confused for the years to come:
    These 2 things are equivalent: (person) { return person.age; })); => person.age);
    Why? Why a fat arrow... why not the other way? <=

    Then there is let, which is similar to my but you seem to still be able to mix var in and create a scope mess...

    They also use modules, with named import's (just like in perl you can require certain things from a pm).
    And the templating... oh noes... the templating uses backtick/backquote...
    var name = 'John'; var age = 29; return `My name is ${ name }, in a year I will be ${ age + 1 } years o +ld`;

    Interested in reading more about JS6? Here is a link:

    Now leave me be... I'm drowning my pain in beer...

perl Data structure to XML
1 direct reply — Read more / Contribute
by Hosen1989
on May 27, 2015 at 07:50

    perl Data structure to XML

    Hi ALL.

    I like to share with you solution for issue I had face it and come with way to solve it.

    I was in need of some module that take any kind of hash or array or any combination of those two and convert them to xml file.

    will, yes there are other module that do this task but not as need it.

    so here my way to do this task:

    also please point to any error in my code or any other best way to do the same thing. ^_^

    use strict; use warnings; use XML::LibXML; my %TV = ( flintstones => { series => "flintstones", nights => [ "monday", "thursday", "friday" ], members => [ { name => "fred", role => "husband", age => 36, }, { name => "wilma", role => "wife", age => 31, }, { name => "pebbles", role => "kid", age => 4, }, ], }, jetsons => { series => "jetsons", nights => [ "wednesday", "saturday" ], members => [ { name => "george", role => "husband", age => 41, }, { name => "jane", role => "wife", age => 39, }, { name => "elroy", role => "kid", age => 9, }, ], }, simpsons => { series => "simpsons", nights => [ "monday" ], members => [ { name => "homer", role => "husband", age => 34, }, { name => "marge", role => "wife", age => 37, }, { name => "bart", role => "kid", age => 11, }, ], }, ); my $xmlString = HASH2XML(\%TV,'TV_SERIES'); print $xmlString; ###################################################################### +######################## sub HASH2XML{ my ($inHashRef) = $_[0]; my ($inName) = $_[1]; if(!defined $inName){$inName = 'rootNode';} my $doc = XML::LibXML::Document->new('1.0', 'utf-8'); # to + create XML doc my $rootNode = $doc->createElement("$inName"); # to create xml +root node $rootNode->setAttribute('Profile_id'=> "$inName"); # add some A +ttribute to the node _OBJ2XML_($doc,$rootNode,$inHashRef,$inName); $doc->setDocumentElement($rootNode); # print $doc->toString(); return $doc->toString(1); } sub _OBJ2XML_{ my ($doc) = $_[0]; my ($inNode) = $_[1]; my ($inRef) = $_[2]; my ($inName) = $_[3]; if(!defined $inName){$inName = 'Node';} if(ref($inRef) eq 'HASH'){ for my $key (sort keys %{$inRef}) { if(ref($inRef->{$key}) eq 'HASH'){ my $tag = $doc->createElement($key); # $tag->setAttribute('dataType'=> "HASH"); $inNode->appendChild($tag); _OBJ2XML_($doc,$tag,$inRef->{$key},$key); }else{ _OBJ2XML_($doc,$inNode,$inRef->{$key},$key); } } }elsif(ref($inRef) eq 'ARRAY'){ my $Len = @{$inRef}; for(my $i = 0; $i < $Len; $i++){ if(ref(@{$inRef}[$i]) eq 'HASH' or ref(@{$inRef}[$i]) eq ' +ARRAY'){ my $tag = $doc->createElement($inName); # $tag->setAttribute('dataType'=> "ARRAY"); $inNode->appendChild($tag); _OBJ2XML_($doc,$tag,@{$inRef}[$i],$inName); }else{ _OBJ2XML_($doc,$inNode,@{$inRef}[$i],$inName); } } }elsif(ref($inRef) eq 'CODE'){ print "--End to CODE ref @ LINE:".__LINE__."\n"; return 0; }elsif(ref($inRef) eq 'SCALAR'){ print "--End to SCALAR ref @ LINE:".__LINE__."\n"; return 0; }else{ my $tag = $doc->createElement($inName); # $tag->setAttribute('dataType'=> "data"); $tag->appendTextNode($inRef); $inNode->appendChild($tag); return 0; } return 0; }


    and below is the sample for the output:

    # ------------------------------------------# # the XML output after doing pretty print # # ------------------------------------------# <?xml version="1.0" encoding="utf-8"?> <TV_SERIES Profile_id="TV_SERIES"> <flintstones> <members> <age>36</age> <name>fred</name> <role>husband</role> </members> <members> <age>31</age> <name>wilma</name> <role>wife</role> </members> <members> <age>4</age> <name>pebbles</name> <role>kid</role> </members> <nights>monday</nights> <nights>thursday</nights> <nights>friday</nights> <series>flintstones</series> </flintstones> <jetsons> <members> <age>41</age> <name>george</name> <role>husband</role> </members> <members> <age>39</age> <name>jane</name> <role>wife</role> </members> <members> <age>9</age> <name>elroy</name> <role>kid</role> </members> <nights>wednesday</nights> <nights>saturday</nights> <series>jetsons</series> </jetsons> <simpsons> <members> <age>34</age> <name>homer</name> <role>husband</role> </members> <members> <age>37</age> <name>marge</name> <role>wife</role> </members> <members> <age>11</age> <name>bart</name> <role>kid</role> </members> <nights>monday</nights> <series>simpsons</series> </simpsons> </TV_SERIES>
Is dead?
5 direct replies — Read more / Contribute
by Anonymous Monk
on May 26, 2015 at 07:08

    Hello, I've found out that is no more in the core distribution of Perl. I've also read that there are many better ways to implement a web application, like use Plack, or use CGI::Application, CGI::Snapp, Dancer, Mojolicious... It is also suggested to use templating systems (ok fine, I've used them with

    However, with modern responsive websites I think that is still a great module, so simple to use it that I don't see a reason to move away or use anything else.

    You just write an API for the client javascript making an AJAX request and you're all done with something like:

    #!/usr/bin/perl use strict; use CGI; use JSON; my $query = new CGI; my $response = whatever(Query=>$query); my $json = JSON->new->utf8(1)->pretty(1)->allow_nonref->encode($respon +se); print $query->header('application/json').$json; sub whatever { # Here you can do REALLY anything, and send back an hash reference }

    Do I make it too easy? This is has a flat learning curve too.

Perl monks vs other sites
3 direct replies — Read more / Contribute
by f77coder
on May 23, 2015 at 23:09
    Hello All,

    I wasn't sure where to post this, so apologies if this is not the place.

    I wanted to say how great Perl Monks is at helping out noobs compared with knuckle dragging neanderthals at place like stack overflow. People here are generally orders of magnitude nicer.

    Cudos to the site.

RFC: Swagger-codegen for Perl
2 direct replies — Read more / Contribute
by wing328
on May 15, 2015 at 02:17
    Hi all, contains a template-driven engine to generate client code in different languages by parsing your Swagger Resource Declaration. Recently I've added the Perl template. To test the code generation, please perform the following (assuming you've the dependencies installed):

    git clone git checkout develop_2.0 git checkout mvn clean && ./bin/

    If you do not want to install the dependencies and just want to get a peek at the auto-generated Perl SDK, please go to the directory samples/client/petstore/perl to have a look at the Perl SDK for Petstore (please make sure you're in the develop_2.0 branch)

    The Perl SDK is not perfect and I would appreciate your time to test and review, and share with me your feedback.

    (ideally I would like to post this at "Meditations" but I couldn't find a way to post there)

OOP: How to (not) lose Encapsulation
3 direct replies — Read more / Contribute
by Arunbear
on May 12, 2015 at 08:25


    Moose and its smaller cousin Moo have become popular ways of creating Object Oriented code, but the existing tutorials do not have much to say about Information hiding (also known as Encapsulation), so this is an attempt to fill that gap.

    Alice and the Set

    Alice wants to use a Set (a collection of unique items) to keep track of data her program has already seen. She creates a Set class which initially looks like this (assume that she either hasn't learnt about hashes yet, or doesn't like the "fiddliness" of simulating a Set via a Hash):
    package Set; use Moo; has 'items' => (is => 'ro', default => sub { [ ] }); no Moo; sub has { my ($self, $e) = @_; scalar grep { $_ == $e } @{ $self->items }; } sub add { my ($self, $e) = @_; if ( ! $self->has($e) ) { push @{ $self->items }, $e; } } 1;
    It can be used like this:
    % reply 0> use Set 1> my $s = Set->new $res[0] = bless( { 'items' => [] }, 'Set' ) 2> $s->has(42) $res[1] = 0 3> $s->add(42) $res[2] = 1 4> $s->has(42) $res[3] = 1

    Bob, min and max

    Another programmer Bob, starts using this class. Bob finds it useful but misses the ability to find the min/max element of a set, so he creates some utilities:
    package BobUtil; use strict; use List::Util qw(min max); sub set_min { my ($set) = @_; min @{ $set->items }; } sub set_max { my ($set) = @_; max @{ $set->items }; } 1;
    which he can use like so:
    % reply 0> use Set 1> use BobUtil 2> my $s = Set->new $res[0] = bless( { 'items' => [] }, 'Set' ) 3> $s->add($_) for 1 .. 5 $res[1] = '' 4> BobUtil::set_min($s) $res[2] = 1 5> BobUtil::set_max($s) $res[3] = 5
    Bob eventually finds this usage too cumbersome and decides to make it simpler by using Inheritance to create his own set:
    package BobSet; use Moo; use List::Util qw(min max); extends 'Set'; no Moo; sub numeric_min { my ($self) = @_; min @{ $self->items }; } sub numeric_max { my ($self) = @_; max @{ $self->items }; } 1;
    And now he can do this:
    % reply 0> use BobSet 1> my $s = BobSet->new $res[0] = bless( { 'items' => [] }, 'BobSet' ) 2> $s->add($_) for 1 .. 5 $res[1] = '' 3> $s->numeric_min $res[2] = 1 4> $s->numeric_max $res[3] = 5

    Alice updates the Set

    Now realising that linear scans don't scale up as well as hash lookups, Alice decides to update her Set class to use a hash rather than an array:
    package Set; use Moo; has 'items' => (is => 'ro', default => sub { { } }); no Moo; sub has { my ($self, $e) = @_; exists $self->items->{ $e }; } sub add { my ($self, $e) = @_; if ( ! $self->has($e) ) { $self->items->{ $e } = 1; } } 1;
    News of the new improved Set reaches Bob, and he installs the new version, but alas:
    % reply 0> use BobSet 1> my $s = BobSet->new $res[0] = bless( { 'items' => {} }, 'BobSet' ) 2> $s->add($_) for 1 .. 5 $res[1] = '' 3> $s->numeric_min Not an ARRAY reference at line 11.
    And BobUtil is just as broken:
    % reply 0> use Set 1> use BobUtil 2> my $s = Set->new $res[0] = bless( { 'items' => {} }, 'Set' ) 3> $s->add($_) for 1 .. 5 $res[1] = '' 4> BobUtil::set_min($s) Not an ARRAY reference at line 8.

    Encapsulation lost via accessor

    By making the internal representation of the Set public, anyone depending on that representation will be in trouble if the representation changes. Alice updates the Set again to correct this design error:
    package Set; use Moo; has '_items' => (is => 'ro', default => sub { { } }); no Moo; sub items { my ($self) = @_; [ keys %{ $self->_items } ]; } sub has { my ($self, $e) = @_; exists $self->_items->{ $e }; } sub add { my ($self, $e) = @_; if ( ! $self->has($e) ) { $self->_items->{ $e } = 1; } } 1;
    Here the internal representation of the Set is made "private" via the "leading underscore" convention, and a public method is provided to access (a copy of) the set items (it would be better to not have an accessor for the set items, as there would be no need to rely on a convention for privacy, but this is beyond the power of Moo). And now BobSet works once again:
    % reply 0> use BobSet 1> my $s = BobSet->new $res[0] = bless( { '_items' => {} }, 'BobSet' ) 2> $s->add($_) for 1 .. 5 $res[1] = '' 3> $s->numeric_min $res[2] = '1' 4> $s->numeric_max $res[3] = '5'

    Encapsulation lost via constructor

    There's still another way in which Encapsulation is lost, consider:
    % reply 0> use Set 1> my $s = Set->new(_items => [1 .. 4]) $res[0] = bless( { '_items' => [ 1, 2, 3, 4 ] }, 'Set' ) 2> $s->add(5) Not a HASH reference at line 15.
    The constructor generated by Moo will by default allow any attribute to be set via an "init_arg", and clearly in this case it is not desirable. There are are few ways to fix this, such as constraining the value using an "isa" directive or by an "init_arg" => undef directive.

    Yet another way is to use BUILDARGS e.g.

    package Set; use Moo; has '_items' => (is => 'ro', default => sub { { } }); no Moo; sub BUILDARGS { shift; return { _items => { map { $_ => 1 } @_ } }; } sub items { my ($self) = @_; [ keys %{ $self->_items } ]; } sub has { my ($self, $e) = @_; exists $self->_items->{ $e }; } sub add { my ($self, $e) = @_; if ( ! $self->has($e) ) { $self->_items->{ $e } = 1; } } 1;
    Now any (explicit) constructor arguments will become elements of the Set:
    % reply 0> use Set 1> my $s = Set->new(1 .. 4) $res[0] = bless( { '_items' => { '1' => 1, '2' => 1, '3' => 1, '4' => 1 } }, 'Set' ) 2> $s->has(5) $res[1] = '' 3> $s->has(3) $res[2] = 1

    Encapsulation lost via Inheritance

    Yet another programmer Chuck, also starts using Alice's Set class but he finds that he wants the Set to be able to remember how many times it has encountered a given value e.g. Chuck wants to create a new type of set with this behaviour:
    % reply 0> use RememberingSet 1> $s = RememberingSet->new 3> $s->has(1) $res[1] = '' 4> $s->add(1) $res[2] = 1 5> $s->seen(1) $res[3] = 2 6> $s->seen(2) $res[4] = 0
    Here the set remembers that it has seen the value 1 twice, once via has() and once via add(), whereas it hasn't seen the value 2 via add() or has(). Chuck uses Inheritance to create this type of set
    package RememberingSet; use Moo; has '_count' => (is => 'ro', default => sub { { } }); extends 'Set'; no Moo; sub has { my ($self, $e) = @_; $self->_count->{ $e }++; $self->SUPER::has($e); } sub add { my ($self, $e) = @_; $self->_count->{ $e }++; $self->SUPER::add($e); } sub seen { my ($self, $e) = @_; exists $self->_count->{ $e } ? $self->_count->{ $e } : 0; } 1;
    The RememberingSet overrides the has() and add() methods in both cases updating a counter before calling the corresponding version in Alice's Set. But Chuck finds that this new set doesn't work as expected
    % reply 0> use RememberingSet 1> my $s = RememberingSet->new $res[0] = bless( { '_count' => {}, '_items' => {} }, 'RememberingSet' ) 2> $s->has(1) $res[1] = '' 3> $s->add(1) $res[2] = 1 4> $s->seen(1) $res[3] = 3
    This has happened because in the Set class, the add() method calls the has() method. Chuck could fix this by not updating the count in his add() method, but this is a fragile solution as seen() would yield the wrong answer if Alice decided to update add() so that it didn't call has().


    The problem with Inheritance is that it requires Chuck to know the internal workings of Alice's set class to use it correctly (thus the loss of Encapsulation). A safer form of reuse is Composition which looks like
    package RememberingSet; use Moo; use Set; has '_count' => (is => 'ro', default => sub { { } }); has '_set' => (is => 'ro', default => sub { Set->new }); no Moo; sub has { my ($self, $e) = @_; $self->_count->{ $e }++; $self->_set->has($e); } sub add { my ($self, $e) = @_; $self->_count->{ $e }++; $self->_set->add($e); } sub seen { my ($self, $e) = @_; exists $self->_count->{ $e } ? $self->_count->{ $e } : 0; } 1;
    This solution provides the expected behaviour. Composition works by wrapping the "derived" class around the original one and forwarding (or delegating) the appropriate methods to it. There are even Moosisms like "handles" and "around" that could be be used to simplify this solution e.g.
    package RememberingSet; use Moo; use Set; my $Delegated = [qw/add has/]; has '_count' => (is => 'ro', default => sub { { } }); has '_set' => (is => 'ro', default => sub { Set->new }, handles => $ +Delegated); around $Delegated => sub { my ($orig, $self, $e) = @_; $self->_count->{ $e }++; $self->$orig($e); }; no Moo; sub seen { my ($self, $e) = @_; exists $self->_count->{ $e } ? $self->_count->{ $e } : 0; } 1;
    The REPL used in the above examples is reply


    • Consider making all attributes private (if only via convention)
    • Consider turning off init_args
    • Consider using Composition instead of Inheritance
Never say never
2 direct replies — Read more / Contribute
by Lady_Aleena
on May 05, 2015 at 23:37

    A thud can be heard throughout the monastery as Lady Aleena's head hits her desk in the scriptorium. Shortly thereafter the sound of breaking glass filters through the monastery's halls as her preconceptions are shattered.

    Never say you will never do a thing because, one day, you will do the thing then feel foolish.

    Now here is some history and what happened tonight. I said I would never use pipes in my data fields. Tonight I did. Now I am feeling more than foolish. (And I've made more work for myself while trying to make less work for myself.) I just learned my lesson.

    If you feel you are about to say "I will never...", stop, think very hard, count to ten, whatever. Just do not say it! One day you will be writing a piece of code, humming a little tune stuck in your head, then you will crash into a wall because you did not take into consideration the exception you just wrote.

    Have a nice day!

    I started this thought in the CB and continued it here.

    No matter how hysterical I get, my problems are not time sensitive. So, relax, have a cookie, and a very nice day!
    Lady Aleena
perlnews item worth reading!
No replies — Read more | Post response
by ww
on May 05, 2015 at 16:12
10,000 days of Perl
2 direct replies — Read more / Contribute
by johnbio
on May 05, 2015 at 07:43
    Just a brief meditation on this landmark day for Perl. If the release of Perl 1.0 according to perlhist is taken as the date of birth, today Perl is 10,000 days old. As someone who has used Perl an awful lot for ... more than 7,000 days, and continues to do so, I would like to post a big Thank You and a 5-digit landmark congratulation to Perl, Larry Wall and the Community :-) I may post again in 2042.

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
  • 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?

    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 perusing the Monastery: (8)
    As of 2015-10-13 18:53 GMT
    Find Nodes?
      Voting Booth?

      Does Humor Belong in Programming?

      Results (313 votes), past polls