Perl Advent Calendar 2013http://perladvent.org/2013/2024-03-13T21:03:05ZRicardo SignesXML::Atom::SimpleFeedSo long and thanks for all the hits!http://perladvent.org/2013/2013-12-25.html<div class='pod'><p>Advent is over, and so this year's Perl Advent Calendar has come to an end. I hope everyone has enjoyed this year's articles and is looking forward to more in a mere 341 days! If you'd like to contribute an article for next year, you've got plenty of time to get started!</p>
<p>As always, the Perl Advent Calendar was a group effort, and I'd like to thank everyone who contributed this year: Arthur Axel "fREW" Schmidt, David Golden, Ingy Döt Net, John SJ Anderson, Karen Etheridge, Leon Timmermans, Mark Allen, Mark Fowler, Mark Jason Dominus, Matthew Horsfall, Neil Bowers, Ricardo Signes, Sawyer X, Toby Inkster, and Yanick Champoux.</p>
<p>If you want to help with the site or other things in the meantime, you can <a href="http://mail.pm.org/mailman/listinfo/perladvent">join our mailing list</a> where we'll be talking about work that needs to get done on things like the FAQ, the site generator, and all that sort of thing. You can find the <a href="https://github.com/perladvent/Perl-Advent">site's contents on GitHub</a>, which <i>should</i> contain the 2013 articles by the time you see this. It's not exactly how it should be, but it's there.</p>
<p>More importantly, you can find <a href="https://github.com/perladvent/Perl-Advent/issues">our wish list for fixes and features</a>. Help with these and you will earn fame forever (at least in the git logs)!</p>
<p>Whether or not we hear from you between now and then, we look forward to publishing again next year. Merry Christmas, Happy New Year, and Happy Hacking!</p>
<h2 id="See-Also">See Also</h2>
<ul>
<li><p><a href="https://github.com/perladvent/Perl-Advent/">the perladvent/Perl-Advent GitHub repo</a></p>
</li>
<li><p><a href="http://www.perladvent.org/FAQ.html">the someday-to-be-rewritten FAQ</a></p>
</li>
<li><p><a href="http://mail.pm.org/mailman/listinfo/perladvent">the mailing list</a> (historical archive)</p>
</li>
</ul>
</div>2013-12-25T00:00:00ZRicardo SignesThe Emergency Debuggerhttp://perladvent.org/2013/2013-12-24.html<div class='pod'><h2 id="Devel::cst-the-emergency-debugger">Devel::cst, the emergency debugger</h2>
<p>Imagine, some long running background job crashes with a segfault. What happens? Well, very little. It died without leaving the faintest explanation why. With a little bad luck, you're not even noticing it died, and a month later you see that your data is incomplete in some horrible way.</p>
<p>This is why you should run such programs with what I like to call an emergency debugger. This means that you will always get at least a stacktrace on any serious fault. Something like this:</p>
<pre><code> Segmentation fault (Address not mapped to object [0x1])
/lib/x86_64-linux-gnu/libc.so.6(+0x14e780)[0x7f944d90b780]
perl(Perl_sv_setpvn+0xb1)[0x511191]
perl(Perl_newSVpvn_flags+0x6c)[0x514b4c]
perl[0x5e8bec]
perl(Perl_unpackstring+0x112)[0x5f4012]
perl(Perl_pp_unpack+0x12a)[0x5f425a]
perl(Perl_runops_standard+0x48)[0x4b1688]
perl(perl_run+0x64e)[0x4423be]
perl(main+0x137)[0x41b207]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf5)[0x7f944d7deea5]
perl[0x41b241]</code></pre>
<p>Reading such a stack trace can be a bit of a black art, but even to the untrained eye it's obvious it crashed and burned. Importantly, this will end up in your error logs, so you can actually easily see that it crashed and burned.</p>
<p>To a more trained eye it will tell that you dereferenced a null pointer in <a href="http://perldoc.perl.org/functions/unpack.html">unpack</a>. I guess <a href="https://metacpan.org/pod/Acme::Boom">Acme::Boom</a> is a bit of a naughty module after all ;-). In other situations it could tell you for example that a specific XS module is being buggy. It's capable of handling tricky corner cases such as stack overflows (the signal handler needs a stack to run on, but during a stack overflow you really don't have any stack left…) and repeated faults (it won't go into an infinite recursion).</p>
<p>Now obviously this is usually only the start of fixing the bug, but you can't run your entire production platform under gdb. You can easily run this debugger on any production platform. Just add <code>-d:cst</code> to your perl invocation, e.g. <code>perl -d:cst -MAcme::Boom -e0</code>. It has no CPU overhead and minimal memory overhead. It's a tiny thing in the background that goes by unnoticed until the worst happens. It does not require any external tools, though it currently only works on Linux (I'm hoping to add support for BSD/darwin soon). If you're really adventurous you could even add <code>-d:cst</code> to your PERL5OPT environmental variable and have all your perl programs use this automatically (but be sure to have it installed properly first).</p>
<h2 id="See-Also">See Also</h2>
<ul>
<li><p><a href="https://metacpan.org/module/Devel::cst">Devel::cst</a></p>
</li>
</ul>
</div>2013-12-24T00:00:00ZLeon TimmermansDateTimeshttp://perladvent.org/2013/2013-12-23.html<div class='pod'><p>The <a href="https://metacpan.org/module/DateTime">DateTime</a> suite is an impressive tour de force, but I hate its interface. The methods it provides are usually not the ones you want, and the things it makes easy are often things that are not useful.</p>
<h3 id="Mutators">Mutators</h3>
<p>The most obvious example is that it has too many mutators. I believe that date-time values are a kind of number, and should be treated like numbers. In particular they should be immutable. Rik Signes has <a href="http://rjbs.manxome.org/rubric/entry/1929">a hair-raising story</a> about an accidental mutation that caused a hard to diagnose bug, because the <code>add_duration</code> method modifies the object on which it is called, instead of returning a new object.</p>
<h3 id="DateTime::Duration">DateTime::Duration</h3>
<p>But the most <i>severe</i> example, the one that drives me into a rage, is that the <code>subtract_datetime</code> method returns a <a href="https://metacpan.org/module/DateTime::Duration">DateTime::Duration</a> object, and this object is never what you want, because it is impossible to use it usefully.</p>
<p>For example, suppose you would like to know how much time elapses between 1969-04-02 02:38:17 EST and 2013-12-25 21:00:00 EST. You can set up the two DateTime objects for the time, and subtract them using the overloaded minus operator:</p>
<pre><code class="code-listing"><span class="keyword">my</span> <span class="structure">(</span><span class="symbol">$a</span><span class="structure">)</span> <span class="operator">=</span> <span class="word">DateTime</span><span class="operator">-></span><span class="word">new</span><span class="structure">(</span> <span class="word">year</span> <span class="operator">=></span> <span class="number">1969</span><span class="operator">,</span> <span class="word">month</span> <span class="operator">=></span> <span class="octal">04</span><span class="operator">,</span> <span class="word">day</span> <span class="operator">=></span> <span class="octal">02</span><span class="operator">,</span><br /> <span class="word">hour</span> <span class="operator">=></span> <span class="number">2</span><span class="operator">,</span> <span class="word">minute</span> <span class="operator">=></span> <span class="number">38</span><span class="operator">,</span> <span class="word">second</span> <span class="operator">=></span> <span class="number">17</span><span class="operator">,</span><br /> <span class="word">time_zone</span> <span class="operator">=></span> <span class="double">"America/New_York"</span> <span class="structure">)</span> <span class="structure">;</span><br /><br /><span class="keyword">my</span> <span class="structure">(</span><span class="symbol">$b</span><span class="structure">)</span> <span class="operator">=</span> <span class="word">DateTime</span><span class="operator">-></span><span class="word">new</span><span class="structure">(</span> <span class="word">year</span> <span class="operator">=></span> <span class="number">2013</span><span class="operator">,</span> <span class="word">month</span> <span class="operator">=></span> <span class="number">12</span><span class="operator">,</span> <span class="word">day</span> <span class="operator">=></span> <span class="number">25</span><span class="operator">,</span><br /> <span class="word">hour</span> <span class="operator">=></span> <span class="number">21</span><span class="operator">,</span> <span class="word">minute</span> <span class="operator">=></span> <span class="number">0</span><span class="operator">,</span> <span class="word">second</span> <span class="operator">=></span> <span class="number">0</span><span class="operator">,</span><br /> <span class="word">time_zone</span> <span class="operator">=></span> <span class="double">"America/New_York"</span> <span class="structure">)</span> <span class="structure">;</span><br /><br /><span class="keyword">my</span> <span class="symbol">$diff</span> <span class="operator">=</span> <span class="symbol">$b</span> <span class="operator">-</span> <span class="symbol">$a</span><span class="structure">;</span></code></pre>
<p>Internally this invokes <code>subtract_datetime</code> to yield a DateTime::Duration object for the difference. The DateTime::Duration object <code>$diff</code> will contain the information that this is a difference of 536 months, 23 days, 1101 minutes, and 43 seconds, a fact which seems to me to be of very limited usefulness.</p>
<p>You might want to know how long this interval is, so you can compare it to similar intervals. So you might want to know how many seconds this is. It happens that the two times are exactly 1,411,669,328 seconds apart, but there's no way to get the <code>$diff</code> object to tell you this.</p>
<p>It <i>seems</i> like there are methods that will get you the actual elapsed time in seconds, but none of them will do it. For example, <code>$diff->in_units('seconds')</code> looks promising, but will return 43, which is the 43 seconds left over after you've thrown away the 536 months, 23 days, and 1101 minutes. I don't know what the use case for this is supposed to be.</p>
<p>And indeed, no method can tell you how long the duration really is, because the subtraction has thrown away all the information about how long the days and months and years were—days, months and years vary in length—so it simply doesn't know how much time this object actually represents.</p>
<p>Similarly if you want to know how many days there are between the two dates, the DateTime::Duration object won't tell you because it can't tell you. If you had the elapsed seconds difference, you could convert it to the correct number of days simply by dividing by 86400 and rounding off. This works because, even though days vary in length, they don't vary by much, and the variations cancel out over the course of a year. If you do this you find that the elapsed number of days is approximately 16338.7653, which rounds off to 16338 or 16339 depending on how you want to treat the 18-hour time-of-day difference. This result is not <i>quite</i> exact, but the error is on the order of 0.000002%. So the elapsed seconds are useful, and you can compute other useful values with them, and get useful answers. In contrast, DateTime::Duration's answer of "536 months and 23 days" is <i>completely</i> useless because months vary in length by nearly 10% and DateTime has thrown away the information about how long the months were. The best you can do to guess the number of days from this is to multiply the 536 months by 30.4375, which is the average number of days in a month, and add 23. This is clumsy, and gets you 16337.5 days—which is close, but wrong.</p>
<p>To get what I consider a useful answer out of the DateTime objects you <i>must not</i> use the overloaded subtraction operator; instead you must do this:</p>
<pre><code class="code-listing"><span class="symbol">$b</span><span class="operator">-></span><span class="word">subtract_datetime_absolute</span><span class="structure">(</span><span class="symbol">$a</span><span class="structure">)</span><span class="operator">-></span><span class="word">in_units</span><span class="structure">(</span><span class="single">'seconds'</span><span class="structure">)</span></code></pre>
<h3 id="Whats-DateTime::Moonpig-for">What's DateTime::Moonpig for?</h3>
<p><a href="https://metacpan.org/module/DateTime::Moonpig">DateTime::Moonpig</a> attempts to get rid of the part of DateTime I don't like and keep the part I do like, by changing the interface and leaving the internals alone. I developed it for <a href="http://blog.plover.com/prog/Moonpig.html">the <i>Moonpig</i> billing system that Rik Signes and I did</a>; hence the name.</p>
<p>DateTime::Moonpig introduces five main changes to the interface of DateTime:</p>
<ol>
<li><p>Most of the mutators are gone. They throw fatal exceptions if you try to call them.</p>
</li>
<li><p>The overridden addition and subtraction operators have been changed to eliminate DateTime::Duration entirely. Subtracting two DateTime::Moonpig objects yields the difference in seconds, as an ordinary Perl number. This means that instead of</p>
<pre><code class="code-listing"><span class="symbol">$x</span> <span class="operator">=</span> <span class="symbol">$b</span><span class="operator">-></span><span class="word">subtract_datetime_absolute</span><span class="structure">(</span><span class="symbol">$a</span><span class="structure">)</span><span class="operator">-></span><span class="word">in_units</span><span class="structure">(</span><span class="single">'seconds'</span><span class="structure">)</span></code></pre>
<p>one can write</p>
<pre><code class="code-listing"><span class="symbol">$x</span> <span class="operator">=</span> <span class="symbol">$b</span> <span class="operator">-</span> <span class="symbol">$a</span></code></pre>
<p>From here it's easy to get the approximate number of days difference: just divide by 86400. Similarly, dividing this by 3600 gets the number of hours difference.</p>
<p>An integer number of seconds can be added to or subtracted from a DateTime::Moonpig object; this yields a new object representing a time that is that many seconds later or earlier. Writing <code>$date + 2</code> is much more convenient than writing <code>$date->clone->add( seconds => 2 )</code>.</p>
<p>If you are not concerned with perfect exactness, you can write</p>
<pre><code class="code-listing"><span class="keyword">sub</span> <span class="word">days</span> <span class="structure">{</span> <span class="magic">$_</span><span class="structure">[</span><span class="number">0</span><span class="structure">]</span> <span class="operator">*</span> <span class="number">86400</span> <span class="structure">}</span><br /><br /><span class="keyword">my</span> <span class="symbol">$tomorrow</span> <span class="operator">=</span> <span class="symbol">$now</span> <span class="operator">+</span> <span class="word">days</span><span class="structure">(</span><span class="number">1</span><span class="structure">);</span></code></pre>
<p>This might be off by an hour if there is an intervening DST change, or by a second if there is an intervening leap second, but in many cases one simply doesn't care.</p>
<p>There is nothing wrong with the way DateTime overloads <code><</code> and <code>></code>, so DateTime::Moonpig leaves those alone.</p>
</li>
<li><p>The constructor is extended to accept an epoch time such as is returned by Perl's built-in <code>time()</code> or <code>stat()</code> functions. This means that one can abbreviate this:</p>
<pre><code class="code-listing"><span class="word">DateTime</span><span class="operator">-></span><span class="word">from_epoch</span><span class="structure">(</span> <span class="word">epoch</span> <span class="operator">=></span> <span class="symbol">$epoch</span> <span class="structure">)</span></code></pre>
<p>to this:</p>
<pre><code class="code-listing"><span class="word">DateTime::Moonpig</span><span class="operator">-></span><span class="word">new</span><span class="structure">(</span> <span class="symbol">$epoch</span> <span class="structure">)</span></code></pre>
</li>
<li><p>The default time zone has been changed from DateTime's "floating" time zone to UTC. I think the "floating" time zone is a mistake, and best avoided. It has bad interactions with <code>set_time_zone</code>, which <code>DateTime::Moonpig</code> does <i>not</i> disable, because it is not actually a mutator—unless you use the "floating" time zone.</p>
</li>
<li><p>I added a few additional methods I found convenient. For example there is a <code>$date->st</code> that returns the date and time in the format <code> YYYY-MM-DD HH:MM::SS </code>, which is sometimes handy for quick debugging. (The <code>st</code> is for "string".)</p>
</li>
</ol>
<p>Under the covers, it is all just DateTime objects, which seem to do what one needs. Other than the mutators, all the many DateTime methods work just the same; you are even free to use <code>->subtract_datetime</code> to obtain a DateTime::Duration object if you enjoy being trapped in an absurdist theatre production.</p>
<p>When I first started this module, I thought it was likely to be a failed experiment. I expected that the Moonpig::DateTime objects would break once ina while, or that some operation on them would return a DateTime instead of a Moonpig::DateTime, which would cause some later method call to fail. But to my surprise, it worked well. It has been in regular use in <i>Moonpig</i> for several years.</p>
<p>I recently split it out of <i>Moonpig</i>, and released it to CPAN. I will be interested to find out if it works well in other contexts. I am worried that disabling the mutators has left a gap in functionality that needs to be filled by something else.</p>
<h2 id="See-Also">See Also</h2>
<ul>
<li><p><a href="https://metacpan.org/module/DateTime::Moonpig">DateTime::Moonpig</a></p>
</li>
<li><p><a href="https://metacpan.org/module/DateTime">DateTime</a></p>
</li>
<li><p><a href="https://metacpan.org/module/DateTime::Duration">DateTime::Duration</a></p>
</li>
</ul>
</div>2013-12-23T00:00:00ZMark Jason DominusThrow Now, Describe Laterhttp://perladvent.org/2013/2013-12-22.html<div class='pod'><p>A few years ago, I <a href="http://advent.rjbs.manxome.org/2010/2010-12-03.html">wrote about Throwable::X</a>, a set of tools for making exceptions easier to work with. Part of the goal was to make it easy for catching code to identify the exception. That meant that rather than saying:</p>
<pre><code class="code-listing"><span class="word">die</span> <span class="double">"you can't set $attr to $value prior to $ready_date"</span><span class="structure">;</span></code></pre>
<p>You say:</p>
<pre><code class="code-listing"><span class="word">OurException</span><span class="operator">-></span><span class="word">throw</span><span class="structure">(</span><span class="word">ident</span> <span class="operator">=></span> <span class="double">"tried to set attribute before ready"</span><span class="structure">);</span></code></pre>
<p>The big deal is that later, your code can be clearer about identifying the exception. Instead of saying:</p>
<pre><code class="code-listing"><span class="keyword">if</span> <span class="structure">(</span><span class="symbol">$error</span> <span class="operator">=~</span> <span class="match">/you can't set \S+ to \S+ prior to \S+/</span><span class="structure">)</span> <span class="structure">{</span> <span class="operator">...</span> <span class="structure">}</span></code></pre>
<p>You can say:</p>
<pre><code class="code-listing"><span class="keyword">if</span> <span class="structure">(</span><span class="symbol">$error</span><span class="operator">-></span><span class="symbol">$_isa</span><span class="structure">(</span><span class="single">'OurException'</span><span class="structure">)</span> <span class="operator">&&</span> <span class="symbol">$error</span><span class="operator">-></span><span class="word">ident</span> <span class="operator">eq</span> <span class="single">'tried to set attr before ready'</span><span class="structure">)</span> <span class="structure">{</span> <span class="operator">...</span> <span class="structure">}</span></code></pre>
<p>…or if you're thinking ahead…</p>
<pre><code class="code-listing"><span class="keyword">if</span> <span class="structure">(</span><span class="symbol">$error</span><span class="operator">-></span><span class="symbol">$_is_err</span><span class="structure">(</span><span class="single">'tried to set attr before ready'</span><span class="structure">))</span> <span class="structure">{</span> <span class="operator">...</span> <span class="structure">}</span></code></pre>
<p>This works because we give each kind of exception a unique enough name. There's an obvious cost, though. The exception, when a string, contained three useful pieces of information that are now lost. We had to ditch them to make the string unique, no matter when it happened. The article on Throwable::X glossed over the solution. The idea is that in addition to an unchanging <code>ident</code>, the exception has a <code>payload</code> and maybe a <code>message</code>.</p>
<pre><code class="code-listing"><span class="word">OurException</span><span class="operator">-></span><span class="word">throw</span><span class="structure">(</span><br /> <span class="word">ident</span> <span class="operator">=></span> <span class="double">"tried to set attribute before ready"</span><span class="operator">,</span><br /> <span class="word">message</span> <span class="operator">=></span> <span class="double">"you can't set %{attr}s to %{value}i before %{ready_date}t"</span><span class="operator">,</span><br /> <span class="word">payload</span> <span class="operator">=></span> <span class="structure">{</span> <span class="word">attr</span> <span class="operator">=></span> <span class="symbol">$attr</span><span class="operator">,</span> <span class="word">value</span> <span class="operator">=></span> <span class="symbol">$value</span><span class="operator">,</span> <span class="word">ready_date</span> <span class="operator">=></span> <span class="symbol">$ready_date</span> <span class="structure">}</span><span class="operator">,</span><br /><span class="structure">);</span></code></pre>
<p>The new parameters let us get the same data into the printed form of the exception that we had originally, without compromising its identifiability. What's up with that <code>message</code> string, though?</p>
<h2 id="Errf">Errf!</h2>
<p>That string is an <code>errf</code> string. It's like the kind of thing you pass to <code>sprintf</code>, but different. It's meant to be simple to implement and to cover just the basic data you might need to stick in an error description.</p>
<p>Like Python's <code>%</code> operator, it can format based on a set of named parameters. It takes a totally different set of parameters, though. Above you see a demonstration of <code>%s</code>, for strings, <code>%i</code>, for integers, and <code>%t</code> for timestamps.</p>
<p>There are other codes, of course, each with its own options. There's <code>%f</code> for floats:</p>
<pre><code class="code-listing"><span class="word">errf</span> <span class="double">"%{x;prefix=+;precision=.2}f"</span><span class="operator">,</span> <span class="structure">{</span> <span class="word">x</span> <span class="operator">=></span> <span class="float">10.1234</span> <span class="structure">};</span> <span class="comment"># returns "+10.12";</span></code></pre>
<p>…and there are a number of useful options not seen for <code>%t</code>:</p>
<pre><code class="code-listing"><span class="keyword">my</span> <span class="symbol">$t</span> <span class="operator">=</span> <span class="number">1280530906</span><span class="structure">;</span><br /><span class="word">errf</span> <span class="double">"%{x}t"</span><span class="operator">,</span> <span class="structure">{</span> <span class="word">x</span> <span class="operator">=></span> <span class="symbol">$t</span> <span class="structure">};</span> <span class="comment"># "2010-07-30 19:01:46"</span><br /><span class="word">errf</span> <span class="double">"%{x;type=date}t"</span><span class="operator">,</span> <span class="structure">{</span> <span class="word">x</span> <span class="operator">=></span> <span class="symbol">$t</span> <span class="structure">};</span> <span class="comment"># "2010-07-30"</span><br /><span class="word">errf</span> <span class="double">"%{x;type=time}t"</span><span class="operator">,</span> <span class="structure">{</span> <span class="word">x</span> <span class="operator">=></span> <span class="symbol">$t</span> <span class="structure">};</span> <span class="comment"># "19:01:46"</span><br /><span class="word">errf</span> <span class="double">"%{x;type=datetime}t"</span><span class="operator">,</span> <span class="structure">{</span> <span class="word">x</span> <span class="operator">=></span> <span class="symbol">$t</span> <span class="structure">};</span> <span class="comment"># "2010-07-30 19:01:46"</span><br /><br /><span class="word">errf</span> <span class="double">"%{x;tz=UTC}t"</span><span class="operator">,</span> <span class="structure">{</span> <span class="word">x</span> <span class="operator">=></span> <span class="symbol">$t</span> <span class="structure">};</span> <span class="comment"># "2010-07-30 23:01:46 UTC"</span><br /><span class="word">errf</span> <span class="double">"%{x;tz=UTC;type=date}t"</span><span class="operator">,</span> <span class="structure">{</span> <span class="word">x</span> <span class="operator">=></span> <span class="symbol">$t</span> <span class="structure">};</span> <span class="comment"># "2010-07-30 UTC"</span><br /><span class="word">errf</span> <span class="double">"%{x;tz=UTC;type=time}t"</span><span class="operator">,</span> <span class="structure">{</span> <span class="word">x</span> <span class="operator">=></span> <span class="symbol">$t</span> <span class="structure">};</span> <span class="comment"># "23:01:46 UTC"</span><br /><span class="word">errf</span> <span class="double">"%{x;tz=UTC;type=datetime}t"</span><span class="operator">,</span> <span class="structure">{</span> <span class="word">x</span> <span class="operator">=></span> <span class="symbol">$t</span> <span class="structure">};</span> <span class="comment"># "2010-07-30 23:01:46 UTC"</span></code></pre>
<p>The goal of errf strings isn't just to allow exceptions to be self-describing when caught and displayed, but to make their description easy to change in the presentation layer of code, which might not be handled by exactly the same team as the business logic. Presentation layer here might sound ominous, like these strings might be getting used to give reports to users — and they are! Many of our exceptions are flagged as user visible, and we show their description right to the user. That means it needs to be possible to make them look… well, not stupid.</p>
<pre><code> You can't add a new account. You have 1 accounts already.</code></pre>
<p>Ugh! Nobody likes an inflection bug. String::Errf has a fix for that:</p>
<pre><code class="code-listing"><span class="word">errf</span> <span class="double">"You can't add a new account. You have %{count;singular=account}n already."</span><span class="operator">,</span><br /> <span class="structure">{</span> <span class="word">count</span> <span class="operator">=></span> <span class="number">1</span> <span class="structure">};</span></code></pre>
<p>The <code>%n</code> code will let you inflect words based on a count, including the count. <code>%N</code> is the same, but omits the number.</p>
<p>A secondary goal of String::Errf was to produce a format simple enough that it could be implemented in other languages, especially JavaScript, so that API errors could be provided with errf-format errors, then formated at the client side. So far this hasn't been done, but possibly soon…</p>
<h2 id="See-Also">See Also</h2>
<ul>
<li><p><a href="https://metacpan.org/module/String::Errf">String::Errf</a></p>
</li>
<li><p><a href="https://metacpan.org/module/Role::HasPayload::Merged">Role::HasPayload::Merged</a></p>
</li>
<li><p><a href="http://advent.rjbs.manxome.org/2010/2010-12-03.html">RJBS Advent Article on Throwable-X</a></p>
</li>
</ul>
</div>2013-12-22T00:00:00ZRicardo SignesBashing Perl5http://perladvent.org/2013/2013-12-21.html<div class='pod'><p>In the past 6 months, I've worked on a lot of <a href="https://github.com/ingydotnet">things</a> in a lot of <a href="https://github.com/acmeism/RosettaCodeData">languages</a>. Being an <a href="http://acmeism.org">Acmeist</a>, this shouldn't seem suspect. What <i>may</i> come as a surprise, is that my main go-to programming language during this time has been <b>Bash</b>! <a href="http://en.wikipedia.org/wiki/Bash_%28Unix_shell%29">Bash</a>? Is that even a programming language?</p>
<h2 id="Bashing-Ingy">Bashing Ingy</h2>
<p>Let me introduce you to my favorite new tool: <a href="https://github.com/ingydotnet/git-hub">git-hub</a>. Install this tool and now you can do all your day-to-day <a href="https://github.com">GitHub</a> interaction using <code>git</code> commands.</p>
<p>Who is <a href="http://ingy.net">Ingy döt Net</a> anyway?</p>
<pre><code> $ git hub user ingydotnet</code></pre>
<p>Who cares?</p>
<pre><code> $ git hub followers ingydotnet</code></pre>
<p>What good is he?</p>
<pre><code> $ git hub repos ingydotnet</code></pre>
<p>I'm confused…</p>
<pre><code> $ git hub help</code></pre>
<p>OK, tell me about the git-hub repo?</p>
<pre><code> $ git hub repo ingydotnet/git-hub</code></pre>
<p>Fork that Bash stuff!</p>
<pre><code> $ git hub fork ingydotnet/git-hub</code></pre>
<p>Clone me down, Scotty!</p>
<pre><code> $ git hub clone git-hub # your fork</code></pre>
<p>Hmmm, I like git-hub!</p>
<pre><code> $ git hub star ingydotnet/git-hub</code></pre>
<p>The git-hub command is even chainable. Want to follow all the members of the <code>perl6</code> GitHub organization, and star all their repos?</p>
<pre><code> $ git hub members perl6 --all --raw | git hub follow -
$ git hub repos perl6 -ar | git hub star -</code></pre>
<p>With the <code>--raw</code> flag, git-hub prints just the userid or repo-spec, then the '-' flag tells the command to read each line of STDIN and replace the '-' with it. Voilà!</p>
<p>This is just a glimpse of the GitHub things you can do. Give it a spin.</p>
<h2 id="WTB-What-Why-The-Bash">WTB? (What/Why The Bash?)</h2>
<p>This amazingly simple/powerful git command is written in Bash. If you are familiar with how Git works, you know that it's basically a huge collection of subcommand plugins with names like <code>git-clone</code>. Try running this command:</p>
<pre><code> $ ls `git --exec-path`</code></pre>
<p>You should see well over 100 commands. They can be written in any language. In fact, in the early days they were mostly written in Perl5! As Git became more popular, much of the Perl was ported to C. You'll notice that most of those files are symlinks to the <code>git</code> executable. This means that while <code>git-clone</code> is written in C, you could simply replace that symlink with a Haskell program of your own crafting.</p>
<p>In May 2013, I became interested in a replacement for git-submodule, called <a href="https://github.com/apenwarr/git-subtree">git-subtree</a>, but soon noticed it had lots of problems too, so I started writing <a href="https://github.com/ingydotnet/git-subrepo">git-subrepo</a>. The subtree command was written in Bash, so I started writing the subrepo command in Bash. I put the subrepo command on hold and started working on the <code>git-hub</code> project. For fun, I decided to see if it was possible to write it in Bash (since I could easy revert to Perl5 if it wasn't).</p>
<p>Was it? It was!</p>
<p>When I try out a new programming language, I generally just think in terms of my favorite programming idioms, rather than language specific idioms. When I get stuck writing something, I google the idiom and read the (almost always StackOverflow) explanation. It starts off slow, but fairly soon I'm getting stuff working, and eventually I feel like a <a href="http://www.youtube.com/watch?v=dQw4w9WgXcQ">Rock Star</a>.</p>
<p>With Bash, every idiom I needed was there, albeit often in a ridiculous syntactic form, compared to Perl5 (or its hipster cousin Ruby).</p>
<h2 id="The-Good-The-Bad-and-the-WTF">The Good, The Bad, and the WTF!</h2>
<p>Let's look at some <a href="https://github.com/ingydotnet/git-hub/blob/perl5-advent-2013/lib/git-hub#L164">Modern Bash</a>. This is the part of the <code>git-hub</code> code where the subcommands are written. For example, here's the 2 functions for the <code>git hub user</code> command:</p>
<pre><code class="code-listing"><span class="synIdentifier">command:user() {</span><br /> get-args ?user:get-user<br /> api-get <span class="synStatement">"</span><span class="synConstant">/users/</span><span class="synPreProc">$user</span><span class="synStatement">"</span><br /> <span class="synIdentifier">msg_404</span>=<span class="synStatement">"</span><span class="synConstant">User '</span><span class="synPreProc">$user</span><span class="synConstant">' not found.</span><span class="synStatement">"</span><br /><span class="synIdentifier">}</span><br /><br /><span class="synIdentifier">ok:user() {</span><br /> <span class="synIdentifier">fields</span>=(<br /> login <span class="synStatement">type</span> name email blog location company bio<br /> followers following public_repos public_gists<br /> )<br /> report-data<br /><span class="synIdentifier">}</span></code></pre>
<p>Quite often when people see this code for the first time they don't believe it's plain old Bash. Well, it is! (And it isn't!). The code above has been heavily refactored, with some Ingy DSL sprinkled on top. Let's review this snippet:</p>
<p>This is the definition of 2 functions. The <code>:</code> is just part of the function name. Bash is quite liberal on function name characters, while quite strict on variable names. Since Bash lacks any concept of hierarchical namespacing, the <code>:</code> lets us fake it nicely. The <code>()</code> parens are required but useless (ie nothing ever goes inside them).</p>
<p>The <code>get-args</code> is just another internal function. I've been using '-' instead of '_' because, you know, it feels more modern. Note that the argument has no quotes. Being a lover of <a href="http://yaml.org">YAML</a>, I avoid quotes when I can. In Bash, commands go through a process called Parameter Expansion, in which whitespace is King. I only use quotes when a string has variable interpolation <i>and</i> the variable in question might have whitespace that would mess up the expansion.</p>
<p>The <code>fields=(…)</code> is how you initialize an array. It's so elegant, and yet this elegance is a Bash rarity. Here's another sexy idiom:</p>
<pre><code class="code-listing"><span class="synIdentifier">fields+</span>=<span class="synPreProc">(</span>foo bar<span class="synPreProc">)</span> <span class="synComment"># push 2 elements onto an array variable</span></code></pre>
<p>What if we wanted to print the contents of the array or its size?</p>
<pre><code class="code-listing"><span class="synStatement">echo</span><span class="synConstant"> </span><span class="synPreProc">$fields</span><span class="synConstant"> </span> <span class="synComment"># Nope. Only prints 'login'.</span><br /><span class="synStatement">echo</span><span class="synConstant"> </span><span class="synPreProc">${fields[</span>@<span class="synPreProc">]}</span><span class="synConstant"> </span> <span class="synComment"># Correct (and ugly)</span><br /><span class="synStatement">echo</span><span class="synConstant"> </span><span class="synPreProc">${#fields[</span>@<span class="synPreProc">]}</span> <span class="synComment"># Print the array size (so obvious, right?)</span></code></pre>
<p>As you can see, the Ugly is never far away. What if we want to join the array into a string where the elements are separated by a <code>:</code>?</p>
<pre><code class="code-listing"><span class="synStatement">printf</span> <span class="synSpecial">-v</span> string <span class="synStatement">"</span><span class="synPreProc">$(IFS</span><span class="synStatement">='</span><span class="synConstant">:</span><span class="synStatement">';</span><span class="synSpecial"> </span><span class="synStatement">eval</span><span class="synSpecial"> </span><span class="synStatement">echo</span><span class="synConstant"> </span><span class="synStatement">"</span><span class="synSpecial">\"</span><span class="synPreProc">${fields[</span>*<span class="synPreProc">]}</span><span class="synSpecial">\"</span><span class="synStatement">"</span><span class="synPreProc">)</span><span class="synStatement">"</span><br /><span class="synStatement">echo</span><span class="synConstant"> </span><span class="synPreProc">$string</span></code></pre>
<p>WTF?!</p>
<h2 id="Which-Advent-Calendar-is-this-anyway">Which Advent Calendar is this anyway?</h2>
<p>You ♥ Perl5. Why is Ingy Bashing you? (tis the season to be Merry!!!)</p>
<p>As I swam through the enigmatic waters of Bash, it became very apparent to me, where Perl got its roots. There was a consistent string of Aha! moments, where I would see where Larry got his inspirations and then cranked them each up to 11.</p>
<p>A friend pointed out to me that he read somewhere, that Perl was originally an attempt to do Shell programming in a single process. This was after I noticed that the simple <code>git hub user</code> command spawned ~200 subprocesses! I guess subprocesses are cheaper now than in the 80s.</p>
<p>Which reminds me, I only realized yesterday that Bash 1.0 was released 2 years <i>after</i> Perl 1.0. Bash is the <a href="http://www.fsf.org/">FSF's</a> <i>free</i> offering of the Bourne shell (from which all the great Unix shells descended). It turns out that Bash got more ideas from Perl than the reverse. Perl 1.0 only had sh, csh and ksh to start from.</p>
<p>I have a book's worth of interesting Perl5↔Bash stuff to tell you. Maybe I should write one.</p>
<h2 id="Bash-Into-the-Future">Bash Into the Future</h2>
<p>Why is Bash of interest as a programming language? Well for one, it's fairly ubiquitous. This lets you write things that will cause the least pain for the most general audience. But the same can be said of Perl5. It seems to be installed by default as much as Bash.</p>
<p>Well, there's a couple things that Shell is way better at than Perl/Ruby/Python etc: IPC and system interaction. These things are so naturally ingrained into Shell, that they often go unnoticed, and they make Shell a much more natural language for writing more Shell commands, UNTIL… you need a <b>module</b> like, say JSON or YAML.</p>
<p>The real problem with programming in Bash is there's no CPAN. Fortunately that's a solvable problem! Just a simple matter of programming. I realized early into git-hub development that I needed a complete JSON parser. Not only that, Bash has no data structures to parse JSON into. I solved both problems by writing <a href="https://github.com/ingydotnet/json-bash">json-bash</a>. I also needed to write tests. Check out <a href="https://github.com/ingydotnet/test-more-bash">test-more-bash</a>. All these obscure idioms could be packaged into a nice DSL, to make Bash hacking more accessible. Introducing <a href="https://github.com/ingydotnet/bashplus">Bash+</a>.</p>
<p>Hmm… This is turning into a nice little collection. Hmm… Where to host all these modules, and start the Bash revolution? I've owned the domain <a href="https://metacpan.org/module/bpan.org">bpan.org</a> for many years now. Hmm… stay tuned!!!</p>
<h2 id="Wrapping-it-Up">Wrapping it Up</h2>
<p>The range of influence that Perl5 has had on modern computing is vast. Bash is a great language to simultaneously see Perl's roots and its contributions in one place. I encourage you to dive into other programming languages, and swim around. If you're like me, it will grow your love for Perl. You'll have parts of Perl culture to grace on other communities, and you'll find things to bring back home. Because if you are really like me, you call Perl your family.</p>
<p>Merry Christmas :-♥</p>
</div>2013-12-21T00:00:00ZIngy Döt NetPretty Pretty Podhttp://perladvent.org/2013/2013-12-20.html<div class='pod'><h2 id="Why-is-the-Advent-calendars-code-so-good-looking">Why is the Advent calendar's code so good looking?</h2>
<p>I know some people don't like seeing their code in color. Someone once said to me, "I stopped needing color in my books when I was a child, and I certainly don't need it in my code." This, I thought, was nuts.</p>
<p>If I was going to write a bunch of articles about code (when I started publishing an <a href="http://advent.rjbs.manxome.org/2009/">Advent calendar in 2009</a>) I didn't want to see this:</p>
<pre><code class="code-listing">my @animals = ("camel", "llama", "owl");<br />my @numbers = (23, 42, 69);<br />my @mixed = ("camel", 42, 1.23);</code></pre>
<p>I wanted to see this:</p>
<pre><code class="code-listing"><span class="keyword">my</span> <span class="symbol">@animals</span> <span class="operator">=</span> <span class="structure">(</span><span class="double">"camel"</span><span class="operator">,</span> <span class="double">"llama"</span><span class="operator">,</span> <span class="double">"owl"</span><span class="structure">);</span><br /><span class="keyword">my</span> <span class="symbol">@numbers</span> <span class="operator">=</span> <span class="structure">(</span><span class="number">23</span><span class="operator">,</span> <span class="number">42</span><span class="operator">,</span> <span class="number">69</span><span class="structure">);</span><br /><span class="keyword">my</span> <span class="symbol">@mixed</span> <span class="operator">=</span> <span class="structure">(</span><span class="double">"camel"</span><span class="operator">,</span> <span class="number">42</span><span class="operator">,</span> <span class="float">1.23</span><span class="structure">);</span></code></pre>
<p>…and I really wanted writing article to be like writing normal Pod.</p>
<p>Oh, and sometimes I wanted to do something other than Perl:</p>
<pre><code class="code-listing"><span class="synIdentifier">dsn</span><span class="synSpecial">:</span> <span class="synConstant">"dbi:SQLite:/home/rjbs/.awesome-stuff.sqlite"</span><br /><span class="synIdentifier">lbj</span><span class="synSpecial">:</span> <span class="synSpecial">{</span> <span class="synIdentifier">guid</span><span class="synSpecial">:</span> 275dc6e0-6926-11e3-a944-0f63e4cda179 <span class="synSpecial">}</span><br /><span class="synIdentifier">alerts</span><span class="synSpecial">:</span><br /> <span class="synIdentifier">hdr_from</span><span class="synSpecial">:</span> <span class="synConstant">'Alerty <alerts@example.com>'</span><br /> <span class="synIdentifier">hdr_to</span><span class="synSpecial"> :</span> <span class="synConstant">'"Ricardo Signes" <rjbs@cpan.org>'</span></code></pre>
<p>Those two blocks above look, in the Pod, like this:</p>
<pre><code class="code-listing">#!perl<br />my @animals = ("camel", "llama", "owl");<br />my @numbers = (23, 42, 69);<br />my @mixed = ("camel", 42, 1.23);</code></pre>
<p>and</p>
<pre><code class="code-listing">#!vim yaml<br />dsn: "dbi:SQLite:/home/rjbs/.awesome-stuff.sqlite"<br />lbj: { guid: 275dc6e0-6926-11e3-a944-0f63e4cda179 }<br />alerts:<br /> hdr_from: 'Alerty <alerts@example.com>'<br /> hdr_to : '"Ricardo Signes" <rjbs@cpan.org>'</code></pre>
<p>Those <code>#!perl</code> and <code>#!vim</code> lines are to blame for the garish spread of color! What are they doing?</p>
<h2 id="PPI::HTML">PPI::HTML</h2>
<p>The <code>#!perl</code> marker is picked up by <a href="https://metacpan.org/module/Pod::Elemental::Transformer::PPIHTML">Pod::Elemental::Transformer::PPIHTML</a>, and passes the rest of the code block to <a href="https://metacpan.org/module/PPI::HTML">PPI::HTML</a>. PPI::HTML uses <a href="https://metacpan.org/module/PPI">PPI</a>, a library for mostly-parsing Perl without running it, and turns Perl documents into HTML documents. For example, the simple Perl snippet above becomes this HTML:</p>
<pre><code class="code-listing"><span class="synIdentifier"><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"keyword"</span><span class="synIdentifier">></span>my<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">></span> <span class="synIdentifier"><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"symbol"</span><span class="synIdentifier">></span>@animals<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">></span><br /><span class="synIdentifier"><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"operator"</span><span class="synIdentifier">></span>=<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">></span> <span class="synIdentifier"><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><br /><span class="synConstant">"structure"</span><span class="synIdentifier">></span>(<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"double"</span><span class="synIdentifier">></span>"camel"<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><br /><span class="synConstant">"operator"</span><span class="synIdentifier">></span>,<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">></span> <span class="synIdentifier"><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"double"</span><span class="synIdentifier">></span>"llama"<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><br /><span class="synConstant">"operator"</span><span class="synIdentifier">></span>,<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">></span> <span class="synIdentifier"><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"double"</span><span class="synIdentifier">></span>"owl"<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><br /><span class="synConstant">"structure"</span><span class="synIdentifier">></span>);<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">><</span><span class="synStatement">br</span><span class="synIdentifier">></span><br /><span class="synIdentifier"><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"keyword"</span><span class="synIdentifier">></span>my<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">></span> <span class="synIdentifier"><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"symbol"</span><span class="synIdentifier">></span>@numbers<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">></span><br /><span class="synIdentifier"><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"operator"</span><span class="synIdentifier">></span>=<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">></span> <span class="synIdentifier"><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><br /><span class="synConstant">"structure"</span><span class="synIdentifier">></span>(<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"number"</span><span class="synIdentifier">></span>23<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><br /><span class="synConstant">"operator"</span><span class="synIdentifier">></span>,<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">></span> <span class="synIdentifier"><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"number"</span><span class="synIdentifier">></span>42<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><br /><span class="synConstant">"operator"</span><span class="synIdentifier">></span>,<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">></span> <span class="synIdentifier"><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"number"</span><span class="synIdentifier">></span>69<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><br /><span class="synConstant">"structure"</span><span class="synIdentifier">></span>);<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">><</span><span class="synStatement">br</span><span class="synIdentifier">></span><br /><span class="synIdentifier"><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"keyword"</span><span class="synIdentifier">></span>my<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">></span> <span class="synIdentifier"><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"symbol"</span><span class="synIdentifier">></span>@mixed<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">></span><br /><span class="synIdentifier"><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"operator"</span><span class="synIdentifier">></span>=<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">></span> <span class="synIdentifier"><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><br /><span class="synConstant">"structure"</span><span class="synIdentifier">></span>(<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"double"</span><span class="synIdentifier">></span>"camel"<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><br /><span class="synConstant">"operator"</span><span class="synIdentifier">></span>,<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">></span> <span class="synIdentifier"><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"number"</span><span class="synIdentifier">></span>42<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><br /><span class="synConstant">"operator"</span><span class="synIdentifier">></span>,<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">></span> <span class="synIdentifier"><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"float"</span><span class="synIdentifier">></span>1.23<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><br /><span class="synConstant">"structure"</span><span class="synIdentifier">></span>);<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">><</span><span class="synStatement">br</span><span class="synIdentifier">></span></code></pre>
<p>It's a bit gross, but the key thing is that distinct bit of syntax gets its own <code><span></code> with a class indicating what it is. PPI::HTML plus a bit of CSS gives you easy syntax highlighting for Perl.</p>
<p>Getting that HTML is trivial, too:</p>
<pre><code class="code-listing"><span class="keyword">my</span> <span class="symbol">$ppi_doc</span> <span class="operator">=</span> <span class="word">PPI::Document</span><span class="operator">-></span><span class="word">new</span><span class="structure">(</span> <span class="cast">\</span><span class="symbol">$source_code</span> <span class="structure">);</span><br /><span class="keyword">my</span> <span class="symbol">$ppi_html</span> <span class="operator">=</span> <span class="word">PPI::HTML</span><span class="operator">-></span><span class="word">new</span><span class="structure">;</span><br /><span class="word">print</span> <span class="symbol">$ppi_html</span><span class="operator">-></span><span class="word">html</span><span class="structure">(</span> <span class="symbol">$ppi_doc</span> <span class="structure">);</span></code></pre>
<h2 id="Text::VimColor">Text::VimColor</h2>
<p>PPI, of course, only parses Perl documents. For almost everything else, there's Text::VimColor. I spent a lot of time looking for generic, pluggable syntax highlighting before finally realizing that the only thing that ever did a good job for me was my text editor. It turned out that I could get my text editor to do the work for me here, too!</p>
<p>The YAML above becomes roughly this HTML:</p>
<pre><code class="code-listing"><span class="synIdentifier"><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"synIdentifier"</span><span class="synIdentifier">></span>dsn<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"synSpecial"</span><span class="synIdentifier">></span>:<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">></span><br /><span class="synIdentifier"><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"synConstant"</span><span class="synIdentifier">></span><span class="synSpecial">&quot;</span>dbi:SQLite:/home/rjbs/.awesome-stuff.sqlite<span class="synSpecial">&quot;</span><span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">></span><br /><span class="synIdentifier"><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"synIdentifier"</span><span class="synIdentifier">></span>lbj<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"synSpecial"</span><span class="synIdentifier">></span>:<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">></span><br /><span class="synIdentifier"><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"synSpecial"</span><span class="synIdentifier">></span>{<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">></span><br /> <span class="synIdentifier"><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"synIdentifier"</span><span class="synIdentifier">></span>guid<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"synSpecial"</span><span class="synIdentifier">></span>:<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">></span><br /> 275dc6e0-6926-11e3-a944-0f63e4cda179 <span class="synIdentifier"><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"synSpecial"</span><span class="synIdentifier">></span>}<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">></span><br /><span class="synIdentifier"><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"synIdentifier"</span><span class="synIdentifier">></span>alerts<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"synSpecial"</span><span class="synIdentifier">></span>:<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">></span><br /><span class="synIdentifier"><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"synIdentifier"</span><span class="synIdentifier">></span>hdr_from<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"synSpecial"</span><span class="synIdentifier">></span>:<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">></span><br /><span class="synIdentifier"><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"synConstant"</span><span class="synIdentifier">></span>'Alerty <span class="synSpecial">&lt;</span>alerts@example.com<span class="synSpecial">&gt;</span>'<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">></span><br /><span class="synIdentifier"><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"synIdentifier"</span><span class="synIdentifier">></span>hdr_to<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"synSpecial"</span><span class="synIdentifier">></span> :<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">></span><br /><span class="synIdentifier"><</span><span class="synStatement">span</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"synConstant"</span><span class="synIdentifier">></span>'<span class="synSpecial">&quot;</span>Ricardo Signes<span class="synSpecial">&quot;</span> <span class="synSpecial">&lt;</span>rjbs@cpan.org<span class="synSpecial">&gt;</span>'<span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">></span></code></pre>
<p>…once again from a trivial program:</p>
<pre><code class="code-listing"><span class="keyword">use</span> <span class="word">Text::VimColor</span><span class="structure">;</span><br /><span class="keyword">my</span> <span class="symbol">$syntax</span> <span class="operator">=</span> <span class="word">Text::VimColor</span><span class="operator">-></span><span class="word">new</span><span class="structure">(</span><br /> <span class="word">string</span> <span class="operator">=></span> <span class="symbol">$yaml_octets</span><span class="operator">,</span><br /> <span class="word">filetype</span> <span class="operator">=></span> <span class="single">'yaml'</span><span class="operator">,</span><br /> <span class="word">vim_options</span> <span class="operator">=></span> <span class="structure">[</span><br /> <span class="words">qw( -RXZ -i NONE -u NONE -N -n )</span><span class="operator">,</span> <span class="double">"+set nomodeline"</span><span class="operator">,</span> <span class="single">'+set fenc=utf-8'</span><span class="operator">,</span><br /> <span class="structure">]</span><span class="operator">,</span><br /><span class="structure">);</span><br /><br /><span class="word">print</span> <span class="symbol">$syntax</span><span class="operator">-></span><span class="word">html</span><span class="structure">;</span></code></pre>
<p>The only cryptic thing here might be the Vim options:</p>
<pre><code> -R -- read only
-X -- no X11
-Z -- restricted mode; no running the shell!
-N -- not vi-compatible
-n -- no swapfile
-i NONE -- no viminfo
-u NONE -- no vimrc</code></pre>
<p>…and the fact that we need to provide the string of source as octets, not a character string, and provide the encoding to Vim. Otherwise, you may encounter some unwanted cleverness.</p>
<h2 id="The-CSS">The CSS</h2>
<p>The CSS used for this is also dead simple:</p>
<pre><code class="code-listing"><span class="synComment">/* PPI HTML Style */</span><br /><br /><span class="synIdentifier">.code-listing</span> <span class="synIdentifier">.keyword</span> <span class="synIdentifier">{</span> <span class="synType">color</span>: <span class="synConstant">#89f</span>; <span class="synIdentifier">}</span><br /><span class="synIdentifier">.code-listing</span> <span class="synIdentifier">.match</span> <span class="synIdentifier">{</span> <span class="synType">color</span>: <span class="synConstant">#ff0</span>; <span class="synIdentifier">}</span><br /><span class="synComment">/* ... */</span><br /><span class="synIdentifier">.code-listing</span> <span class="synIdentifier">.single</span><span class="synSpecial">,</span><br /><span class="synIdentifier">.code-listing</span> <span class="synIdentifier">.double</span> <span class="synIdentifier">{</span> <span class="synType">color</span>: <span class="synConstant">#0cf</span>; <span class="synIdentifier">}</span><br /><br /><span class="synComment">/* Vim Syntax Style */</span><br /><br /><span class="synIdentifier">.code-listing</span> <span class="synIdentifier">.synComment</span> <span class="synIdentifier">{</span> <span class="synType">color</span>: <span class="synConstant">#0f0</span>; <span class="synIdentifier">}</span><br /><span class="synIdentifier">.code-listing</span> <span class="synIdentifier">.synConstant</span> <span class="synIdentifier">{</span> <span class="synType">color</span>: <span class="synConstant">#0ff</span>; <span class="synIdentifier">}</span><br /><span class="synComment">/* ... */</span><br /><span class="synIdentifier">.code-listing</span> <span class="synIdentifier">.synError</span> <span class="synIdentifier">{</span> <span class="synType">color</span>: <span class="synConstant">#f00</span>; <span class="synIdentifier">}</span><br /><span class="synIdentifier">.code-listing</span> <span class="synIdentifier">.synTodo</span> <span class="synIdentifier">{</span> <span class="synType">color</span>: <span class="synConstant">#aa0</span>; <span class="synIdentifier">}</span></code></pre>
<p>It's generated, of course, by <a href="http://xn--8dbbfrx.rjbs.manxome.org/2011/2011-12-21.html">Color::Palette</a>.</p>
<h2 id="Highlight-everything">Highlight everything!</h2>
<p>Now that you see how easy it is to get nicely syntax highlighted HTML for any hunk of code you have lying around, <i>do it!</i> It can often help make bland documentation or other writing much easier to skim. Even better, since the output is pretty simple HTML, you can edit the output as needed to fix glitches or add further highlighting.</p>
<h2 id="See-Also">See Also</h2>
<ul>
<li><p><a href="https://metacpan.org/module/Text::VimColor">Text::VimColor</a></p>
</li>
<li><p><a href="https://metacpan.org/module/PPI::HTML">PPI::HTML</a></p>
</li>
<li><p><a href="https://metacpan.org/module/Pod::Elemental::Transformer::VimHTML">Pod::Elemental::Transformer::VimHTML</a></p>
</li>
<li><p><a href="https://metacpan.org/module/Pod::Elemental::Transformer::PPIHTML">Pod::Elemental::Transformer::PPIHTML</a></p>
</li>
<li><p><a href="https://metacpan.org/module/WWW::AdventCalendar">WWW::AdventCalendar</a></p>
</li>
</ul>
</div>2013-12-20T00:00:00ZRicardo SignesMore Moose, More Disciplinehttp://perladvent.org/2013/2013-12-19.html<div class='pod'><p>One of the things that makes Moose so convenient is that it makes it easy to validate data without much effort. Perl code tends to be <i>extremely</i> permissive. That is: it's quite common not to find much type checking code, so if bad data is passed in, it's not caught until it's used, at which point the error message can be pretty weird. I know <i>I</i> have seen "<code>not an ARRAY reference</code>" from weird places more times than I'd like to remember.</p>
<p>The reason, at least in part, is simple: type checking is a pain.</p>
<p>Moose makes it easy by associating type data with attributes. When your class includes:</p>
<pre><code class="code-listing"><span class="keyword">package</span> <span class="word">Thing</span><span class="structure">;</span><br /><span class="comment"># ⋮<br /></span><span class="word">has</span> <span class="word">weight</span> <span class="operator">=></span> <span class="structure">(</span><br /> <span class="word">is</span> <span class="operator">=></span> <span class="single">'ro'</span><span class="operator">,</span><br /> <span class="word">isa</span> <span class="operator">=></span> <span class="word">PositiveInt</span><span class="operator">,</span><br /> <span class="word">required</span> <span class="operator">=></span> <span class="number">1</span><span class="operator">,</span><br /><span class="structure">);</span></code></pre>
<p>...then you can feel confident at any point in your program that an object's <code>weight</code> is a positive integer. Either the constructor will have thrown a clear exception when the object was constructed or it got the right kind of data.</p>
<p>Types can even be re-used outside the context of attribute definition to keep making data validation really pervasive.</p>
<pre><code class="code-listing"><span class="keyword">sub</span> <span class="word">eat_pies</span> <span class="structure">{</span><br /> <span class="keyword">my</span> <span class="structure">(</span><span class="symbol">$self</span><span class="operator">,</span> <span class="symbol">$how_many</span><span class="structure">)</span> <span class="operator">=</span> <span class="magic">@_</span><span class="structure">;</span><br /> <span class="word">PositiveInt</span><span class="operator">-></span><span class="word">assert_valid</span><span class="structure">(</span><span class="symbol">$how_many</span><span class="structure">);</span><br /><span class="comment"> # ⋮<br /></span><span class="structure">}</span></code></pre>
<h3 id="Except">Except...</h3>
<p>Unfortunately, Moose has a gaping hole into which bad data can fall: the constructor.</p>
<pre><code class="code-listing"><span class="keyword">package</span> <span class="word">Gift</span> <span class="structure">{</span><br /> <span class="keyword">use</span> <span class="word">Moose</span><span class="structure">;</span><br /> <span class="keyword">use</span> <span class="word">Moose::Util::TypeConstraints</span><span class="structure">;</span><br /><br /> <span class="word">has</span> <span class="word">wrapping_paper</span> <span class="operator">=></span> <span class="structure">(</span><br /> <span class="word">is</span> <span class="operator">=></span> <span class="single">'ro'</span><span class="operator">,</span><br /> <span class="word">isa</span> <span class="operator">=></span> <span class="word">enum</span><span class="structure">([</span> <span class="words">qw( festive sombre amazon.com )</span> <span class="structure">])</span><span class="operator">,</span><br /> <span class="word">default</span> <span class="operator">=></span> <span class="single">'amazon.com'</span><span class="operator">,</span><br /> <span class="structure">);</span><br /><br /><span class="comment"> # ⋮<br /></span><span class="structure">}</span></code></pre>
<p>So, we've got code representing the gift we're carefully picking out and painstakingly wrapping, but we stupidly do this:</p>
<pre><code class="code-listing"><span class="keyword">my</span> <span class="symbol">$gift</span> <span class="operator">=</span> <span class="word">Gift</span><span class="operator">-></span><span class="word">new</span><span class="structure">(</span><span class="operator">...,</span> <span class="word">wrappingpaper</span> <span class="operator">=></span> <span class="single">'sombre'</span><span class="structure">);</span></code></pre>
<p>Not only do we get no error, but our friend gets a package wrapped in thoughtless-seeming Amazon wrapping paper. Argh!</p>
<p>Only one change is needed:</p>
<pre><code class="code-listing"><span class="keyword">package</span> <span class="word">Gift</span> <span class="structure">{</span><br /> <span class="keyword">use</span> <span class="word">Moose</span><span class="structure">;</span><br /> <span class="keyword">use</span> <span class="word">Moose::Util::TypeConstraints</span><span class="structure">;</span><br /> <span class="keyword">use</span> <span class="word">MooseX::StrictConstructor</span><span class="structure">;</span> <span class="comment"># ← just add this!</span><br /><br /> <span class="word">has</span> <span class="word">wrapping_paper</span> <span class="operator">=></span> <span class="structure">(</span><br /> <span class="word">is</span> <span class="operator">=></span> <span class="single">'ro'</span><span class="operator">,</span><br /> <span class="word">isa</span> <span class="operator">=></span> <span class="word">enum</span><span class="structure">([</span> <span class="words">qw( festive sombre amazon.com )</span> <span class="structure">])</span><span class="operator">,</span><br /> <span class="word">default</span> <span class="operator">=></span> <span class="single">'amazon.com'</span><span class="operator">,</span><br /> <span class="structure">);</span><br /><br /><span class="comment"> # ⋮<br /></span><span class="structure">}</span></code></pre>
<p><a href="https://metacpan.org/module/MooseX::StrictConstructor">MooseX::StrictConstructor</a> causes the constructor to throw an exception on unknown input. For example, our bogus <code>wrappingpaper</code> argument, above, would get us the exception:</p>
<pre><code> Found unknown attribute(s) init_arg passed to the constructor: wrappingpaper</code></pre>
<h3 id="Except1">Except...</h3>
<p>Sometimes, it's useful to accept an unknown set of extra arguments to your constructor. Maybe you do something like this:</p>
<pre><code class="code-listing"><span class="keyword">package</span> <span class="word">Gift</span> <span class="structure">{</span><br /><span class="comment"> # ⋮<br /></span><br /> <span class="word">has</span> <span class="word">shipping_cost</span> <span class="operator">=></span> <span class="structure">(</span><br /> <span class="word">is</span> <span class="operator">=></span> <span class="single">'rw'</span><span class="operator">,</span><br /> <span class="word">isa</span> <span class="operator">=></span> <span class="word">Money</span><span class="operator">,</span><br /> <span class="word">default</span> <span class="operator">=></span> <span class="keyword">sub</span> <span class="structure">{</span> <span class="operator">...</span><span class="word">something</span> <span class="word">with</span> <span class="word">size</span> <span class="operator">and</span> <span class="word">weight</span><span class="operator">...</span> <span class="structure">}</span><span class="operator">,</span><br /> <span class="word">init_arg</span> <span class="operator">=></span> <span class="core">undef</span><span class="operator">,</span><br /> <span class="structure">);</span><br /><br /> <span class="keyword">sub</span> <span class="word">BUILD</span> <span class="structure">{</span><br /> <span class="keyword">my</span> <span class="structure">(</span><span class="symbol">$self</span><span class="operator">,</span> <span class="symbol">$arg</span><span class="structure">)</span> <span class="operator">=</span> <span class="magic">@_</span><span class="structure">;</span><br /> <span class="symbol">$self</span><span class="operator">-></span><span class="word">carrier</span><span class="structure">(</span><span class="single">'UPS'</span><span class="structure">)</span><span class="operator">,</span> <span class="symbol">$self</span><span class="operator">-></span><span class="word">shipping_cost</span><span class="structure">(</span><span class="number">0</span><span class="structure">)</span> <span class="word">if</span> <span class="symbol">$arg</span><span class="operator">-></span><span class="structure">{</span><span class="word">free_shipping</span><span class="structure">};</span><br /> <span class="structure">}</span><br /><span class="structure">}</span></code></pre>
<p>Now you can pass <code>free_shipping => 1</code> to your constructor to clear out the otherwise-computed shipping cost… but it won't work with MooseX::StrictConstructor, because <code>free_shipping</code> isn't the <code>init_arg</code> of any attribute. Fortunately, there's a trivial fix. If you want to accept an argument for use in <code>BUILD</code> just delete it so that it's not there anymore when <code>BUILD</code> is done:</p>
<pre><code class="code-listing"><span class="keyword">sub</span> <span class="word">BUILD</span> <span class="structure">{</span><br /> <span class="keyword">my</span> <span class="structure">(</span><span class="symbol">$self</span><span class="operator">,</span> <span class="symbol">$arg</span><span class="structure">)</span> <span class="operator">=</span> <span class="magic">@_</span><span class="structure">;</span><br /> <span class="symbol">$self</span><span class="operator">-></span><span class="word">carrier</span><span class="structure">(</span><span class="single">'UPS'</span><span class="structure">)</span><span class="operator">,</span> <span class="symbol">$self</span><span class="operator">-></span><span class="word">shipping_cost</span><span class="structure">(</span><span class="number">0</span><span class="structure">)</span> <span class="word">if</span> <span class="word">delete</span> <span class="symbol">$arg</span><span class="operator">-></span><span class="structure">{</span><span class="word">free_shipping</span><span class="structure">};</span><br /><span class="comment"> # ^- no more exception!<br /></span><span class="structure">}</span></code></pre>
<h2 id="See-Also">See Also</h2>
<ul>
<li><p><a href="https://metacpan.org/module/MooseX::StrictConstructor">MooseX::StrictConstructor</a></p>
</li>
<li><p><a href="https://metacpan.org/module/Moose">Moose</a></p>
</li>
<li><p><a href="https://metacpan.org/module/fields">fields</a></p>
</li>
</ul>
</div>2013-12-19T00:00:00ZRicardo SignesThe little module that keeps on givinghttp://perladvent.org/2013/2013-12-18.html<div class='pod'><h2 id="Path::Tiny:-The-little-module-that-keeps-on-giving">Path::Tiny: The little module that keeps on giving</h2>
<p>Do you have difficulty remembering all of the core modules that help you work with path names and contents, their interfaces, and all the little edge cases that you have to watch out for? I sure do! But I have a new tool in my toolbox that lets me forget about <a href="https://metacpan.org/module/File::Spec">File::Spec</a>, <a href="https://metacpan.org/module/File::Copy">File::Copy</a>, <a href="https://metacpan.org/module/File::Path">File::Path</a>, <a href="https://metacpan.org/module/File::Temp">File::Temp</a> and the rest — <a href="https://metacpan.org/module/Path::Tiny">Path::Tiny</a>, by David Golden. It's amazingly full-featured for a module that can still rightfully claim the Tiny name.</p>
<p>For instance, you may be aware that it lets you deal with path strings in an architecture-agnostic way, and stringifies as needed:</p>
<pre><code class="code-listing"><span class="keyword">my</span> <span class="symbol">$path</span> <span class="operator">=</span> <span class="word">path</span><span class="structure">(</span><span class="words">qw(master_list 2013 North_America)</span><span class="structure">);</span><br /><br /><span class="comment"># prints 'master_list/2013/North_America';<br /></span><span class="word">say</span> <span class="symbol">$path</span><span class="structure">;</span><br /><br /><span class="comment"># prints 'master_list/2013/North_America' on unix,<br /># 'master_list\2013\North_America' on win32<br /></span><span class="word">say</span> <span class="symbol">$path</span><span class="operator">-></span><span class="word">canonpath</span><span class="structure">;</span><br /><br /><span class="comment"># prints /home/santa/master_list/2013/North_America when $CWD is /home/santa<br /></span><span class="word">say</span> <span class="symbol">$path</span><span class="operator">-></span><span class="word">absolute</span><span class="structure">;</span><br /><br /><span class="comment"># prints 'master_list/2013'<br /></span><span class="word">say</span> <span class="symbol">$path</span><span class="operator">-></span><span class="word">parent</span><span class="structure">;</span><br /><br /><span class="comment"># prints 'master_list/2013/North_America/Vancouver/ETHER'<br /></span><span class="word">say</span> <span class="symbol">$path</span><span class="operator">-></span><span class="word">child</span><span class="structure">(</span><span class="single">'Vancouver'</span><span class="operator">,</span> <span class="single">'ETHER'</span><span class="structure">);</span></code></pre>
<p>Did you also know it can help you with creating temporary directories and files, automatically respecting the <code>TMPDIR</code> environment variable?</p>
<pre><code class="code-listing"><span class="keyword">my</span> <span class="symbol">$tempdir</span> <span class="operator">=</span> <span class="word">Path::Tiny</span><span class="operator">-></span><span class="word">tempdir</span><span class="structure">(</span><span class="single">'delivery_list_XXXXXX'</span><span class="structure">);</span><br /><span class="keyword">my</span> <span class="symbol">$tempfile</span> <span class="operator">=</span> <span class="word">Path::Tiny</span><span class="operator">-></span><span class="word">tempfile</span><span class="structure">(</span><span class="word">TEMPLATE</span> <span class="operator">=></span> <span class="single">'delivery_list_XXXXXX'</span><span class="operator">,</span> <span class="word">suffix</span> <span class="operator">=></span> <span class="single">'.bin'</span><span class="structure">);</span></code></pre>
<p>Or that you can use it to easily process your files?</p>
<pre><code class="code-listing"><span class="keyword">foreach</span> <span class="keyword">my</span> <span class="symbol">$city_dir</span> <span class="structure">(</span><span class="word">path</span><span class="structure">(</span><span class="words">qw(master_list 2013 North_America)</span><span class="structure">)</span><span class="operator">-></span><span class="word">children</span><span class="structure">)</span><br /><span class="structure">{</span><br /> <span class="keyword">foreach</span> <span class="keyword">my</span> <span class="symbol">$gift_path</span> <span class="structure">(</span><span class="symbol">$city_dir</span><span class="operator">-></span><span class="word">children</span><span class="structure">)</span><br /> <span class="structure">{</span><br /><span class="comment"> # $gift_path will be the same as from path(qw(master_list 2013 North_America Vancouver ETHER))<br /></span> <span class="word">process_giftlist</span><span class="structure">(</span><span class="symbol">$gift_path</span><span class="structure">);</span><br /> <span class="structure">}</span><br /><span class="structure">}</span></code></pre>
<p>You can even traverse directories recursively:</p>
<pre><code class="code-listing"><span class="keyword">my</span> <span class="symbol">@naughty</span><span class="structure">;</span><br /><span class="keyword">my</span> <span class="symbol">$iter</span> <span class="operator">=</span> <span class="word">path</span><span class="structure">(</span><span class="words">qw(master_list 2013)</span><span class="structure">)</span><span class="operator">-></span><span class="word">iterator</span><span class="structure">({</span> <span class="word">recurse</span> <span class="operator">=></span> <span class="number">1</span> <span class="structure">});</span><br /><span class="keyword">while</span> <span class="structure">(</span><span class="keyword">my</span> <span class="symbol">$path</span> <span class="operator">=</span> <span class="symbol">$iter</span><span class="operator">-></span><span class="structure">())</span><br /><span class="structure">{</span><br /><span class="comment"> # skip over directories<br /></span> <span class="word">next</span> <span class="word">unless</span> <span class="symbol">$path</span><span class="operator">-></span><span class="word">is_file</span><span class="structure">;</span><br /><br /> <span class="word">push</span> <span class="symbol">@naughty</span><span class="operator">,</span> <span class="symbol">$path</span> <span class="operator">and</span> <span class="word">next</span> <span class="word">if</span> <span class="symbol">$path</span><span class="operator">-></span><span class="word">parent</span><span class="operator">-></span><span class="word">child</span><span class="structure">(</span><span class="single">'.naughty'</span><span class="structure">)</span><span class="operator">-></span><span class="word">is_file</span><span class="structure">;</span><br /><br /> <span class="word">plan_delivery</span><span class="structure">(</span><span class="symbol">$path</span><span class="structure">);</span><br /><span class="structure">}</span></code></pre>
<p>And remove entire trees:</p>
<pre><code class="code-listing"><span class="comment"># no gifts for you!<br /></span><span class="keyword">foreach</span> <span class="keyword">my</span> <span class="symbol">$naughty_path</span> <span class="structure">(</span><span class="symbol">@naughty</span><span class="structure">)</span><br /><span class="structure">{</span><br /> <span class="word">send_lump_of_coal_to</span><span class="structure">(</span><span class="symbol">$path</span><span class="operator">-></span><span class="word">basename</span><span class="structure">);</span><br /> <span class="symbol">$naughty_path</span><span class="operator">-></span><span class="word">remove_tree</span><span class="structure">;</span><br /><span class="structure">}</span></code></pre>
<p><a href="https://metacpan.org/module/Path::Tiny">Path::Tiny</a> also makes creating files and directories a breeze:</p>
<pre><code class="code-listing"><span class="keyword">my</span> <span class="symbol">$year</span> <span class="operator">=</span> <span class="structure">(</span><span class="word">localtime</span><span class="structure">)[</span><span class="number">5</span><span class="structure">]</span> <span class="operator">+</span> <span class="number">1900</span><span class="structure">;</span> <span class="comment"># or '2013'</span><br /><span class="keyword">foreach</span> <span class="keyword">my</span> <span class="symbol">$child</span> <span class="structure">(</span><span class="word">keys</span> <span class="symbol">%census</span><span class="structure">)</span><br /><span class="structure">{</span><br /> <span class="keyword">my</span> <span class="symbol">$gift_path</span> <span class="operator">=</span> <span class="word">path</span><span class="structure">(</span><span class="single">'master_list'</span><span class="operator">,</span> <span class="symbol">$year</span><span class="operator">,</span> <span class="symbol">$child</span><span class="operator">-></span><span class="structure">{</span><span class="word">region</span><span class="structure">}</span><span class="operator">,</span> <span class="symbol">$child</span><span class="operator">-></span><span class="structure">{</span><span class="word">city</span><span class="structure">}</span><span class="operator">,</span> <span class="symbol">$child</span><span class="operator">-></span><span class="structure">{</span><span class="word">name</span><span class="structure">});</span><br /><br /><span class="comment"> # creates full directory heirarchy if it does not already exist<br /></span> <span class="symbol">$gift_path</span><span class="operator">-></span><span class="word">mkpath</span><span class="structure">;</span><br /><br /><span class="comment"> # append to existing file, or create a new one as needed<br /></span> <span class="keyword">my</span> <span class="symbol">@gift_list</span> <span class="operator">=</span> <span class="word">consult_elves_regarding</span><span class="structure">(</span><span class="symbol">$child</span><span class="structure">);</span><br /> <span class="symbol">$gift_path</span><span class="operator">-></span><span class="word">append_utf8</span><span class="structure">({</span> <span class="word">locked</span> <span class="operator">=></span> <span class="number">1</span> <span class="structure">}</span><span class="operator">,</span> <span class="cast">\</span><span class="symbol">@gift_list</span><span class="structure">);</span><br /><span class="structure">}</span></code></pre>
<p>But what about processing file contents? That's also a joy:</p>
<pre><code class="code-listing"><span class="keyword">sub</span> <span class="word">process_giftlist</span><br /><span class="structure">{</span><br /> <span class="keyword">my</span> <span class="symbol">$gift_path</span> <span class="operator">=</span> <span class="core">shift</span><span class="structure">;</span><br /><br /> <span class="keyword">my</span> <span class="symbol">$fh</span> <span class="operator">=</span> <span class="symbol">$gift_path</span><span class="operator">-></span><span class="word">openr_utf8</span><span class="structure">;</span><br /> <span class="keyword">while</span> <span class="structure">(</span><span class="keyword">my</span> <span class="symbol">$line</span> <span class="operator">=</span> <span class="readline"><$fh></span><span class="structure">)</span> <span class="structure">{</span> <span class="operator">...</span> <span class="structure">}</span><br /><span class="structure">}</span></code></pre>
<p>What a about a few more stocking stuffers?</p>
<p>Keep your filesystem clean by ensuring that locally-created scratch files are in the tempdir:</p>
<pre><code class="code-listing"><span class="comment"># Don't chdir if we're already in a descendant of the tempdir!<br /></span><span class="word">chdir</span> <span class="symbol">$tempdir</span> <span class="word">unless</span> <span class="symbol">$tempdir</span><span class="operator">-></span><span class="word">subsumes</span><span class="structure">(</span><span class="word">Path::Tiny</span><span class="operator">-></span><span class="word">cwd</span><span class="structure">);</span></code></pre>
<p>Create a file anywhere in the system, without having to create intermediary files:</p>
<pre><code class="code-listing"><span class="keyword">my</span> <span class="symbol">$scratch_file</span> <span class="operator">=</span> <span class="symbol">$tempdir</span><span class="operator">-></span><span class="word">child</span><span class="structure">(</span><span class="single">'batch_01'</span><span class="operator">,</span> <span class="single">'scratchfile.txt'</span><span class="structure">)</span><span class="operator">-></span><span class="word">touchpath</span><span class="structure">;</span></code></pre>
<p>Move a file for safe-keeping into a directory that may not yet exist:</p>
<pre><code class="code-listing"><span class="symbol">$scratch_file</span><span class="operator">-></span><span class="word">move</span><span class="structure">(</span><span class="word">Path::Tiny</span><span class="operator">-></span><span class="word">rootdir</span><span class="structure">(</span><span class="single">'master_list'</span><span class="operator">,</span> <span class="single">'2013'</span><span class="operator">,</span> <span class="single">'extras'</span><span class="structure">)</span><span class="operator">-></span><span class="word">mkpath</span><span class="structure">));</span></code></pre>
<p>Create a digest of the file, for easily watching for other things changing the file:</p>
<pre><code class="code-listing"><span class="keyword">foreach</span> <span class="keyword">my</span> <span class="symbol">$path</span> <span class="structure">(</span><span class="operator">...</span><span class="structure">)</span><br /><span class="structure">{</span><br /> <span class="keyword">my</span> <span class="symbol">$digest</span> <span class="operator">=</span> <span class="symbol">$path</span><span class="operator">-></span><span class="word">digest</span><span class="structure">;</span><br /> <span class="word">reprocess_file</span><span class="structure">(</span><span class="symbol">$path</span><span class="structure">)</span> <span class="word">if</span> <span class="symbol">$digest</span> <span class="operator">ne</span> <span class="structure">(</span><span class="symbol">$digest</span><span class="structure">{</span><span class="symbol">$path</span><span class="structure">}</span> <span class="operator">//</span> <span class="single">''</span><span class="structure">);</span><br /> <span class="symbol">$digest</span><span class="structure">{</span><span class="symbol">$path</span><span class="structure">}</span> <span class="operator">=</span> <span class="symbol">$digest</span><span class="structure">;</span><br /><span class="structure">}</span></code></pre>
<p>But this is my favourite feature of all, because it rolls up so many concerns into one tidy little package... never again will you have to have to worry about error-checking, encoding, line endings or anything else that might distract us from gift preparation:</p>
<pre><code class="code-listing"><span class="keyword">my</span> <span class="symbol">$file_contents</span> <span class="operator">=</span> <span class="symbol">$gift_path</span><span class="operator">-></span><span class="word">slurp_utf8</span><span class="structure">;</span></code></pre>
<p>Mmm, tasty <a href="https://metacpan.org/module/Path::Tiny">Path::Tiny</a>!</p>
<h2 id="See-Also">See Also</h2>
<ul>
<li><p><a href="https://metacpan.org/module/Path::Tiny">Path::Tiny</a></p>
</li>
<li><p><a href="https://metacpan.org/module/Path::Iterator::Rule">Path::Iterator::Rule</a></p>
</li>
<li><p><a href="https://metacpan.org/module/File::Spec">File::Spec</a></p>
</li>
<li><p><a href="https://metacpan.org/module/File::Copy">File::Copy</a></p>
</li>
<li><p><a href="https://metacpan.org/module/File::Find">File::Find</a></p>
</li>
<li><p><a href="https://metacpan.org/module/File::Path">File::Path</a></p>
</li>
<li><p><a href="https://metacpan.org/module/File::stat">File::stat</a></p>
</li>
<li><p><a href="https://metacpan.org/module/File::Temp">File::Temp</a></p>
</li>
<li><p><a href="https://metacpan.org/module/File::Basename">File::Basename</a></p>
</li>
<li><p><a href="https://metacpan.org/module/Path::Class">Path::Class</a></p>
</li>
<li><p>ugh</p>
</li>
</ul>
</div>2013-12-18T00:00:00ZKaren EtheridgeHow many days until Christmas?http://perladvent.org/2013/2013-12-17.html<div class='pod'><p>I find myself writing a lot of code to measure time. How long until Christmas? How long since the last release of Perl? How far apart between my kid's birthday and my sister's kids birthday? How long did that program take to run? How long until this next program finishes?</p>
<p>Like almost any right-thinking programmer, I deal with time as epoch seconds. Every time value is a reference to a fixed moment in history, and it's easy to get a difference between the two. I don't mean a <a href="https://metacpan.org/module/DateTime::Duration">DateTime::Duration</a>, of course, I just mean a number. Christmas is at 1387947600. How long until then? Six hundred ninety-six thousand eighty-three seconds.</p>
<p>This is the kind of horrible answer that I used to get from my programs.</p>
<pre><code> Job entered queue 10201s ago. Completion in 9108s. 696083s to Christmas.</code></pre>
<p>Seconds are nice, sometimes. I like them up to, say, an hour's worth. After that, it gets fuzzy. Then maybe we'll switch to sexagesimal. To what? You know:</p>
<pre><code> Job entered queue 2:50:01s ago. Completion in 2:31:48s. 193:21:23s to Christmas.</code></pre>
<p>Well, that's okay, up until the end, there. What I really want is something that I can read and understand and move on. That's what <a href="https://metacpan.org/module/Time::Duration">Time::Duration</a> is for. It formats durations (by which I mean numbers of seconds) in a bunch of ways that are useful to humans.</p>
<pre><code class="code-listing"><span class="keyword">use</span> <span class="word">Time::Duration</span><span class="structure">;</span><br /><br /><span class="keyword">my</span> <span class="symbol">$now</span> <span class="operator">=</span> <span class="number">1387251517</span><span class="structure">;</span><br /><span class="keyword">my</span> <span class="symbol">$enqueued</span> <span class="operator">=</span> <span class="number">1387241316</span><span class="structure">;</span><br /><span class="keyword">my</span> <span class="symbol">$completion</span> <span class="operator">=</span> <span class="number">1387260625</span><span class="structure">;</span><br /><span class="keyword">my</span> <span class="symbol">$christmas</span> <span class="operator">=</span> <span class="number">1387947600</span><span class="structure">;</span><br /><br /><span class="word">printf</span> <span class="double">"Job entered queue %s. Completion %s. %s to Christmas.\n"</span><span class="operator">,</span><br /> <span class="word">ago</span><span class="structure">(</span> <span class="symbol">$now</span> <span class="operator">-</span> <span class="symbol">$enqueued</span> <span class="structure">)</span><span class="operator">,</span><br /> <span class="word">from_now</span><span class="structure">(</span> <span class="symbol">$completion</span> <span class="operator">-</span> <span class="symbol">$now</span> <span class="structure">)</span><span class="operator">,</span><br /> <span class="word">duration</span><span class="structure">(</span> <span class="symbol">$christmas</span> <span class="operator">-</span> <span class="symbol">$now</span> <span class="structure">);</span></code></pre>
<p>Prints:</p>
<pre><code> Job entered queue 2 hours and 50 minutes ago. Completion 2 hours and 32
minutes from now. 8 days and 1 hour to Christmas.</code></pre>
<p>Not only does it produce human-readable durations, but it rounds them, too. By default, it rounds to two units, so the fuzziness is on a scale appropriate to the magnitude of the value. We could've used the "exact" forms:</p>
<pre><code class="code-listing"><span class="word">printf</span> <span class="double">"Job entered queue %s. Completion %s. %s to Christmas.\n"</span><span class="operator">,</span><br /> <span class="word">ago_exact</span><span class="structure">(</span> <span class="symbol">$now</span> <span class="operator">-</span> <span class="symbol">$enqueued</span> <span class="structure">)</span><span class="operator">,</span><br /> <span class="word">from_now_exact</span><span class="structure">(</span> <span class="symbol">$completion</span> <span class="operator">-</span> <span class="symbol">$now</span> <span class="structure">)</span><span class="operator">,</span><br /> <span class="word">duration_exact</span><span class="structure">(</span> <span class="symbol">$christmas</span> <span class="operator">-</span> <span class="symbol">$now</span> <span class="structure">);</span></code></pre>
<p>…to get…</p>
<pre><code> Job entered queue 2 hours, 50 minutes, and 1 second ago. Completion 2 hours,
31 minutes, and 48 seconds from now. 8 days, 1 hour, 21 minutes, and 23
seconds to Christmas.</code></pre>
<p>Or we could ask for less precision by passing the extra "precision" argument:</p>
<pre><code class="code-listing"><span class="word">printf</span> <span class="double">"Job entered queue %s. Completion %s. %s to Christmas.\n"</span><span class="operator">,</span><br /> <span class="word">ago</span><span class="structure">(</span> <span class="symbol">$now</span> <span class="operator">-</span> <span class="symbol">$enqueued</span><span class="operator">,</span> <span class="number">1</span><span class="structure">)</span><span class="operator">,</span><br /> <span class="word">from_now</span><span class="structure">(</span> <span class="symbol">$completion</span> <span class="operator">-</span> <span class="symbol">$now</span><span class="operator">,</span> <span class="number">1</span><span class="structure">)</span><span class="operator">,</span><br /> <span class="word">duration</span><span class="structure">(</span> <span class="symbol">$christmas</span> <span class="operator">-</span> <span class="symbol">$now</span><span class="operator">,</span> <span class="number">3</span><span class="structure">);</span></code></pre>
<p>Prints:</p>
<pre><code> Job entered queue 3 hours ago. Completion 3 hours from now. 8 days, 1 hour,
and 21 minutes to Christmas.</code></pre>
<p>...and if we want to save space, you can pass the output of any of Time::Duration's functions to <code>concise</code> to pack it up into a shorter form that's still quite human-readable:</p>
<pre><code class="code-listing"><span class="word">printf</span> <span class="double">"Job entered queue %s. Completion %s. %s to Christmas.\n"</span><span class="operator">,</span><br /> <span class="word">concise</span><span class="structure">(</span><span class="word">ago_exact</span><span class="structure">(</span> <span class="symbol">$now</span> <span class="operator">-</span> <span class="symbol">$enqueued</span> <span class="structure">))</span><span class="operator">,</span><br /> <span class="word">concise</span><span class="structure">(</span><span class="word">from_now_exact</span><span class="structure">(</span> <span class="symbol">$completion</span> <span class="operator">-</span> <span class="symbol">$now</span> <span class="structure">))</span><span class="operator">,</span><br /> <span class="word">concise</span><span class="structure">(</span><span class="word">duration_exact</span><span class="structure">(</span> <span class="symbol">$christmas</span> <span class="operator">-</span> <span class="symbol">$now</span> <span class="structure">));</span></code></pre>
<p>…for…</p>
<pre><code> Job entered queue 2h50m1s ago. Completion 2h31m48s from now. 8d1h21m23s to
Christmas.</code></pre>
<p>Time::Duration isn't an amazing piece of software engineering, but it's really useful to make your software friendlier. I use it in very simple one-offs, because it's so easy to use and so helpful.</p>
<h3 id="Time::Durations-Little-Helpers">Time::Duration's Little Helpers</h3>
<p>There are two other related libraries that I use much less often, but they're still quite useful.</p>
<p><a href="https://metacpan.org/module/Time::Duration::Object">Time::Duration::Object</a> lets you turn a value (in seconds) into a duration object on which formatting methods can be called later.</p>
<pre><code class="code-listing"><span class="keyword">use</span> <span class="word">Time::Duration::Object</span><span class="structure">;</span><br /><span class="keyword">my</span> <span class="symbol">$dur</span> <span class="operator">=</span> <span class="word">Time::Duration::Object</span><span class="operator">-></span><span class="word">new</span><span class="structure">(</span> <span class="number">695012</span> <span class="structure">);</span><br /><br /><span class="word">say</span> <span class="symbol">$dur</span><span class="operator">-></span><span class="word">duration</span><span class="structure">;</span> <span class="comment"># 8 days and 1 hour</span><br /><span class="word">say</span> <span class="symbol">$dur</span><span class="operator">-></span><span class="word">duration_exact</span><span class="structure">;</span> <span class="comment"># 8 days, 1 hour, 3 minutes, and 32 seconds</span><br /><span class="word">say</span> <span class="symbol">$dur</span><span class="operator">-></span><span class="word">duration_exact</span><span class="operator">-></span><span class="word">concise</span><span class="structure">;</span> <span class="comment"># 8d1h3m32s</span></code></pre>
<p><a href="https://metacpan.org/module/Time::Duration::Parse">Time::Duration::Parse</a> takes the strings produced by Time::Duration and turns it into a count of seconds.</p>
<pre><code class="code-listing"><span class="keyword">use</span> <span class="word">Time::Duration::Parse</span><span class="structure">;</span><br /><span class="word">say</span> <span class="word">parse_duration</span><span class="structure">(</span><span class="single">'8 days and 1 hour'</span><span class="structure">);</span> <span class="comment"># 694800</span><br /><span class="word">say</span> <span class="word">parse_duration</span><span class="structure">(</span><span class="single">'8 days, 1 hour, 3 minutes, and 32 seconds'</span><span class="structure">);</span> <span class="comment"># 695012</span><br /><span class="word">say</span> <span class="word">parse_duration</span><span class="structure">(</span><span class="single">'8d1h3m32s'</span><span class="structure">);</span> <span class="comment"># 695012</span></code></pre>
<h2 id="See-Also">See Also</h2>
<ul>
<li><p><a href="https://metacpan.org/module/Time::Duration">Time::Duration</a></p>
</li>
<li><p><a href="https://metacpan.org/module/Time::Duration::Object">Time::Duration::Object</a></p>
</li>
<li><p><a href="https://metacpan.org/module/Time::Duration::Parse">Time::Duration::Parse</a></p>
</li>
</ul>
</div>2013-12-17T00:00:00ZRicardo SignesAdvent-based Programminghttp://perladvent.org/2013/2013-12-16.html<div class='pod'><p>Oh, sorry, seasonal slip of the tongue. I meant <i>Event</i>-based programming. A programming paradigm that is used quite exensively in some languages (hellooo JavaScript), but perhaps slightly less so in Perl. And while we see it used most often for asynchronous tasks — GUIs, server stuff — it also offers advantages for more typical settings.</p>
<p>For example, let's consider a Christmas supper. We can all agree that it's a task that involves a lot of details. If we were to tackle the task the conventional way, we'd create a master class that would organize everything, orchestrate the activities of everybody in the household, and probably go mad before the end of the evening from the sheer complexity of the affair. Not appealing. Alternatively, we could imitate what generations of families have done to get through such an operation: holler across the room each time something happens or is needed, and let everybody concerned in the crowd deal with it.</p>
<p>As you may suspect, many modules exist to deal with event-based programming. Here, I'll use <a href="https://metacpan.org/module/Beam::Emitter">Beam::Emitter</a>, a very light-weight <a href="https://metacpan.org/module/Moo">Moo</a>-based system.</p>
<p>As mentioned above, the goal here is to have a very simple core system, and have it broadcast everything that need to be acted upon. So we'll do just that and create our house, which will act like a (warm and cozy) echo chamber:</p>
<pre><code class="code-listing"><span class="keyword">package</span> <span class="word">XmasSupper</span><span class="structure">;</span><br /><br /><span class="keyword">use</span> <span class="version">5.10.0</span><span class="structure">;</span><br /><br /><span class="keyword">use</span> <span class="pragma">strict</span><span class="structure">;</span><br /><span class="keyword">use</span> <span class="pragma">warnings</span><span class="structure">;</span><br /><br /><span class="keyword">use</span> <span class="word">JSON</span> <span class="words">qw/ encode_json /</span><span class="structure">;</span><br /><br /><span class="keyword">use</span> <span class="word">Moose</span><span class="structure">;</span><br /><br /><span class="word">with</span> <span class="single">'Beam::Emitter'</span><span class="structure">;</span><br /><br /><span class="word">has</span> <span class="word">guests</span> <span class="operator">=></span> <span class="structure">(</span><br /> <span class="word">traits</span> <span class="operator">=></span> <span class="structure">[</span> <span class="single">'Array'</span> <span class="structure">]</span><span class="operator">,</span><br /> <span class="word">isa</span> <span class="operator">=></span> <span class="single">'ArrayRef[Peep]'</span><span class="operator">,</span><br /> <span class="word">is</span> <span class="operator">=></span> <span class="single">'ro'</span><span class="operator">,</span><br /> <span class="word">default</span> <span class="operator">=></span> <span class="keyword">sub</span> <span class="structure">{</span> <span class="structure">[]</span> <span class="structure">}</span><span class="operator">,</span><br /> <span class="word">handles</span> <span class="operator">=></span> <span class="structure">{</span><br /> <span class="word">add_guest</span> <span class="operator">=></span> <span class="single">'push'</span><span class="operator">,</span><br /> <span class="structure">}</span><span class="operator">,</span><br /><span class="structure">);</span><br /><br /><span class="word">has</span> <span class="double">"table"</span> <span class="operator">=></span> <span class="structure">(</span><br /> <span class="word">isa</span> <span class="operator">=></span> <span class="single">'HashRef'</span><span class="operator">,</span><br /> <span class="word">is</span> <span class="operator">=></span> <span class="single">'ro'</span><span class="operator">,</span><br /> <span class="word">default</span> <span class="operator">=></span> <span class="keyword">sub</span> <span class="structure">{</span> <span class="structure">{}</span> <span class="structure">}</span><span class="operator">,</span><br /><span class="structure">);</span><br /><br /><span class="comment"># method to invite our guests<br /></span><span class="keyword">sub</span> <span class="word">invite</span> <span class="structure">{</span><br /> <span class="keyword">my</span> <span class="symbol">$self</span> <span class="operator">=</span> <span class="core">shift</span><span class="structure">;</span><br /><br /> <span class="keyword">for</span> <span class="structure">(</span> <span class="magic">@_</span> <span class="structure">)</span> <span class="structure">{</span><br /> <span class="magic">$_</span><span class="operator">-></span><span class="word">supper</span><span class="structure">(</span><span class="symbol">$self</span><span class="structure">);</span><br /> <span class="symbol">$self</span><span class="operator">-></span><span class="word">add_guest</span><span class="structure">(</span><span class="magic">$_</span><span class="structure">);</span><br /> <span class="magic">$_</span><span class="operator">-></span><span class="word">register_events</span><span class="structure">;</span><br /> <span class="structure">}</span><br /><span class="structure">}</span><br /><br /><span class="comment"># the events of the evening<br /></span><br /><span class="keyword">sub</span> <span class="word">prepare</span> <span class="structure">{</span> <span class="magic">$_</span><span class="structure">[</span><span class="number">0</span><span class="structure">]</span><span class="operator">-></span><span class="word">emit</span><span class="structure">(</span><span class="single">'prepare'</span><span class="structure">)</span> <span class="structure">}</span><br /><br /><span class="keyword">sub</span> <span class="word">serve</span> <span class="structure">{</span> <span class="magic">$_</span><span class="structure">[</span><span class="number">0</span><span class="structure">]</span><span class="operator">-></span><span class="word">emit</span><span class="structure">(</span><span class="double">"supper's ready"</span><span class="structure">)</span> <span class="structure">}</span><br /><br /><span class="keyword">sub</span> <span class="word">eat</span> <span class="structure">{</span> <span class="magic">$_</span><span class="structure">[</span><span class="number">0</span><span class="structure">]</span><span class="operator">-></span><span class="word">emit</span><span class="structure">(</span><span class="double">"eat"</span><span class="structure">)</span> <span class="structure">}</span><br /><br /><span class="keyword">sub</span> <span class="word">done</span> <span class="structure">{</span><br /> <span class="keyword">my</span> <span class="symbol">$self</span> <span class="operator">=</span> <span class="core">shift</span><span class="structure">;</span><br /><br /> <span class="word">say</span> <span class="double">"leftovers: "</span><span class="operator">,</span> <span class="word">encode_json</span><span class="structure">(</span> <span class="symbol">$self</span><span class="operator">-></span><span class="word">table</span> <span class="structure">);</span><br /><br /> <span class="symbol">$self</span><span class="operator">-></span><span class="word">emit</span><span class="structure">(</span> <span class="single">'all done'</span> <span class="structure">);</span><br /><span class="structure">}</span><br /><br /><span class="number">1</span><span class="structure">;</span></code></pre>
<p>All the magic of the party will reside in its guests (but then, isn't that always the case?). Each person invited, via <code>$_->register_events</code> is invited to keep their ears open for things that pertain to them. So what we need to have their class implement is that listening, and of course whatever they have to do when the stuff happens.</p>
<pre><code class="code-listing"><span class="keyword">package</span> <span class="word">Peep</span><span class="structure">;</span><br /><br /><span class="keyword">use</span> <span class="version">5.10.0</span><span class="structure">;</span><br /><br /><span class="keyword">use</span> <span class="pragma">strict</span><span class="structure">;</span><br /><span class="keyword">use</span> <span class="pragma">warnings</span><span class="structure">;</span><br /><br /><span class="keyword">use</span> <span class="word">JSON</span> <span class="words">qw/ encode_json /</span><span class="structure">;</span><br /><br /><span class="keyword">use</span> <span class="word">Moose</span><span class="structure">;</span><br /><span class="keyword">use</span> <span class="word">Moose::Util</span> <span class="words">qw/ apply_all_roles /</span><span class="structure">;</span><br /><br /><span class="word">has</span> <span class="word">name</span> <span class="operator">=></span> <span class="structure">(</span><br /> <span class="word">isa</span> <span class="operator">=></span> <span class="single">'Str'</span><span class="operator">,</span><br /> <span class="word">is</span> <span class="operator">=></span> <span class="single">'ro'</span><span class="operator">,</span><br /><span class="structure">);</span><br /><br /><span class="word">has</span> <span class="double">"supper"</span> <span class="operator">=></span> <span class="structure">(</span><br /> <span class="word">isa</span> <span class="operator">=></span> <span class="single">'XmasSupper'</span><span class="operator">,</span><br /> <span class="word">is</span> <span class="operator">=></span> <span class="single">'rw'</span><span class="operator">,</span><br /> <span class="word">handles</span> <span class="operator">=></span> <span class="structure">[</span> <span class="single">'emit'</span><span class="operator">,</span> <span class="single">'on'</span><span class="operator">,</span> <span class="single">'table'</span> <span class="structure">]</span><span class="operator">,</span><br /><span class="structure">);</span><br /><br /><br /><span class="comment"># can be trusted with the turkey?<br /></span><span class="word">has</span> <span class="word">is_cook</span> <span class="operator">=></span> <span class="structure">(</span><br /> <span class="word">isa</span> <span class="operator">=></span> <span class="single">'Bool'</span><span class="operator">,</span><br /> <span class="word">is</span> <span class="operator">=></span> <span class="single">'ro'</span><span class="operator">,</span><br /> <span class="word">default</span> <span class="operator">=></span> <span class="number">0</span><span class="operator">,</span><br /> <span class="word">trigger</span> <span class="operator">=></span> <span class="keyword">sub</span> <span class="structure">{</span><br /> <span class="keyword">my</span> <span class="symbol">$self</span> <span class="operator">=</span> <span class="core">shift</span><span class="structure">;</span><br /> <span class="word">apply_all_roles</span><span class="structure">(</span> <span class="symbol">$self</span><span class="operator">,</span> <span class="single">'Cook'</span> <span class="structure">)</span> <span class="word">if</span> <span class="symbol">$self</span><span class="operator">-></span><span class="word">is_cook</span><span class="structure">;</span><br /> <span class="structure">}</span><span class="operator">,</span><br /><span class="structure">);</span><br /><br /><span class="comment"># prefer white or dark meat?<br /></span><span class="word">has</span> <span class="word">turkey_preference</span> <span class="operator">=></span> <span class="structure">(</span><br /> <span class="word">isa</span> <span class="operator">=></span> <span class="single">'Str'</span><span class="operator">,</span><br /> <span class="word">is</span> <span class="operator">=></span> <span class="single">'ro'</span><span class="operator">,</span><br /> <span class="word">predicate</span> <span class="operator">=></span> <span class="single">'has_turkey_preference'</span><span class="operator">,</span><br /><span class="structure">);</span><br /><br /><span class="comment"># prefered trimmings?<br /></span><span class="word">has</span> <span class="word">trimmings</span> <span class="operator">=></span> <span class="structure">(</span><br /> <span class="word">traits</span> <span class="operator">=></span> <span class="structure">[</span> <span class="single">'Array'</span> <span class="structure">]</span><span class="operator">,</span><br /> <span class="word">isa</span> <span class="operator">=></span> <span class="single">'ArrayRef[Str]'</span><span class="operator">,</span><br /> <span class="word">is</span> <span class="operator">=></span> <span class="single">'ro'</span><span class="operator">,</span><br /> <span class="word">default</span> <span class="operator">=></span> <span class="keyword">sub</span> <span class="structure">{</span> <span class="structure">[]</span> <span class="structure">}</span><span class="operator">,</span><br /> <span class="word">handles</span> <span class="operator">=></span> <span class="structure">{</span><br /> <span class="word">all_trimmings</span> <span class="operator">=></span> <span class="single">'elements'</span><span class="operator">,</span><br /> <span class="structure">}</span><span class="operator">,</span><br /><span class="structure">);</span><br /><br /><span class="comment"># helping or just chillin' in the living room?<br /></span><span class="word">has</span> <span class="word">is_busy</span> <span class="operator">=></span> <span class="structure">(</span><br /> <span class="word">isa</span> <span class="operator">=></span> <span class="single">'Bool'</span><span class="operator">,</span><br /> <span class="word">is</span> <span class="operator">=></span> <span class="single">'rw'</span><span class="operator">,</span><br /> <span class="word">default</span> <span class="operator">=></span> <span class="number">0</span><span class="operator">,</span><br /><span class="structure">);</span><br /><br /><span class="word">has</span> <span class="word">plate</span> <span class="operator">=></span> <span class="structure">(</span><br /> <span class="word">isa</span> <span class="operator">=></span> <span class="single">'HashRef'</span><span class="operator">,</span><br /> <span class="word">is</span> <span class="operator">=></span> <span class="single">'ro'</span><span class="operator">,</span><br /> <span class="word">default</span> <span class="operator">=></span> <span class="keyword">sub</span> <span class="structure">{</span> <span class="structure">{}</span> <span class="structure">}</span><span class="operator">,</span><br /><span class="structure">);</span><br /><br /><span class="comment"># keep an ear out for stuff we can do<br /></span><span class="keyword">sub</span> <span class="word">register_events</span> <span class="structure">{</span><br /> <span class="keyword">my</span> <span class="symbol">$self</span> <span class="operator">=</span> <span class="core">shift</span><span class="structure">;</span><br /><br /> <span class="symbol">$self</span><span class="operator">-></span><span class="word">supper</span><span class="operator">-></span><span class="word">on</span><span class="structure">(</span> <span class="single">'need fixing'</span> <span class="operator">=></span> <span class="keyword">sub</span> <span class="structure">{</span><br /> <span class="keyword">return</span> <span class="word">if</span> <span class="symbol">$self</span><span class="operator">-></span><span class="word">is_busy</span><span class="structure">;</span><br /> <span class="symbol">$self</span><span class="operator">-></span><span class="word">prepare_fixing</span><span class="structure">(</span><span class="core">shift</span><span class="structure">);</span><br /> <span class="structure">}</span> <span class="structure">);</span><br /><br /> <span class="symbol">$self</span><span class="operator">-></span><span class="word">supper</span><span class="operator">-></span><span class="word">on</span><span class="structure">(</span> <span class="double">"supper's ready"</span> <span class="operator">=></span> <span class="keyword">sub</span> <span class="structure">{</span><br /> <span class="symbol">$self</span><span class="operator">-></span><span class="word">fill_plate</span><span class="structure">;</span><br /> <span class="structure">});</span><br /><br /> <span class="symbol">$self</span><span class="operator">-></span><span class="word">supper</span><span class="operator">-></span><span class="word">on</span><span class="structure">(</span> <span class="double">"eat"</span> <span class="operator">=></span> <span class="keyword">sub</span> <span class="structure">{</span><br /> <span class="symbol">$self</span><span class="operator">-></span><span class="word">eat</span><span class="structure">;</span><br /> <span class="structure">});</span><br /><br /> <span class="symbol">$self</span><span class="operator">-></span><span class="word">supper</span><span class="operator">-></span><span class="word">on</span><span class="structure">(</span> <span class="single">'all done'</span><span class="operator">,</span> <span class="keyword">sub</span> <span class="structure">{</span> <br /> <span class="symbol">$self</span><span class="operator">-></span><span class="word">say</span><span class="structure">(</span> <span class="single">'God bless us, every one!'</span> <span class="structure">);</span><br /> <span class="structure">}</span> <span class="structure">)</span> <span class="word">if</span> <span class="symbol">$self</span><span class="operator">-></span><span class="word">name</span> <span class="operator">eq</span> <span class="single">'Timothy'</span><span class="structure">;</span><br /><br /><span class="structure">}</span><br /><br /><span class="comment"># ... and the stuff we can, and will, do<br /></span><br /><span class="keyword">sub</span> <span class="word">prepare_fixing</span> <span class="structure">{</span><br /> <span class="keyword">my</span><span class="structure">(</span> <span class="symbol">$self</span><span class="operator">,</span> <span class="symbol">$fixing</span> <span class="structure">)</span> <span class="operator">=</span> <span class="magic">@_</span><span class="structure">;</span><br /><br /> <span class="symbol">$self</span><span class="operator">-></span><span class="word">is_busy</span><span class="structure">(</span><span class="number">1</span><span class="structure">);</span><br /><br /> <span class="symbol">$self</span><span class="operator">-></span><span class="word">say</span><span class="structure">(</span> <span class="double">"preparing the "</span><span class="operator">,</span> <span class="symbol">$fixing</span><span class="operator">-></span><span class="word">type</span> <span class="structure">);</span><br /> <span class="symbol">$self</span><span class="operator">-></span><span class="word">table</span><span class="operator">-></span><span class="structure">{</span><span class="word">fixing</span><span class="structure">}{</span><span class="symbol">$fixing</span><span class="operator">-></span><span class="word">type</span><span class="structure">}</span> <span class="operator">=</span> <span class="number">2</span><span class="structure">;</span><br /><br /><span class="comment"> # somebody's on it, can stop calling for help<br /></span> <span class="symbol">$fixing</span><span class="operator">-></span><span class="word">stop</span><span class="structure">;</span><br /><span class="structure">}</span><br /><br /><span class="keyword">sub</span> <span class="word">fill_plate</span> <span class="structure">{</span><br /> <span class="keyword">my</span> <span class="symbol">$self</span> <span class="operator">=</span> <span class="core">shift</span><span class="structure">;</span><br /><br /> <span class="keyword">for</span> <span class="structure">(</span> <span class="symbol">$self</span><span class="operator">-></span><span class="word">all_trimmings</span> <span class="structure">)</span> <span class="structure">{</span><br /> <span class="keyword">if</span> <span class="structure">(</span> <span class="symbol">$self</span><span class="operator">-></span><span class="word">table</span><span class="operator">-></span><span class="structure">{</span><span class="word">fixing</span><span class="structure">}{</span><span class="magic">$_</span><span class="structure">}</span> <span class="structure">)</span> <span class="structure">{</span><br /> <span class="symbol">$self</span><span class="operator">-></span><span class="word">table</span><span class="operator">-></span><span class="structure">{</span><span class="word">fixing</span><span class="structure">}{</span><span class="magic">$_</span><span class="structure">}</span><span class="operator">--</span><span class="structure">;</span><br /> <span class="symbol">$self</span><span class="operator">-></span><span class="word">plate</span><span class="operator">-></span><span class="structure">{</span><span class="word">fixing</span><span class="structure">}{</span><span class="magic">$_</span><span class="structure">}</span><span class="operator">++</span><span class="structure">;</span><br /> <span class="structure">}</span><br /> <span class="keyword">else</span> <span class="structure">{</span><br /> <span class="symbol">$self</span><span class="operator">-></span><span class="word">say</span><span class="structure">(</span> <span class="double">"no more "</span><span class="operator">,</span> <span class="magic">$_</span> <span class="structure">);</span><br /> <span class="structure">}</span><br /> <span class="structure">}</span><br /><br /> <span class="symbol">$self</span><span class="operator">-></span><span class="word">plate</span><span class="operator">-></span><span class="structure">{</span><span class="word">turkey</span><span class="structure">}</span> <span class="operator">=</span> <span class="number">1</span><span class="structure">;</span><br /> <span class="symbol">$self</span><span class="operator">-></span><span class="word">table</span><span class="operator">-></span><span class="structure">{</span><span class="word">turkey</span><span class="structure">}{</span><span class="symbol">$self</span><span class="operator">-></span><span class="word">turkey_preference</span><span class="structure">}</span><span class="operator">--</span><span class="structure">;</span><br /><span class="structure">}</span><br /><br /><span class="keyword">sub</span> <span class="word">eat</span> <span class="structure">{</span> <br /> <span class="keyword">my</span> <span class="symbol">$self</span> <span class="operator">=</span> <span class="core">shift</span><span class="structure">;</span><br /> <span class="symbol">$self</span><span class="operator">-></span><span class="word">say</span><span class="structure">(</span> <span class="single">'O NOM NOM NOM'</span><span class="operator">,</span> <span class="double">"\n"</span><span class="operator">,</span> <span class="word">encode_json</span><span class="structure">(</span> <span class="symbol">$self</span><span class="operator">-></span><span class="word">plate</span> <span class="structure">)</span> <span class="structure">);</span><br /><span class="structure">}</span><br /><br /><span class="keyword">sub</span> <span class="word">say</span> <span class="structure">{</span><br /> <span class="keyword">my</span> <span class="symbol">$self</span> <span class="operator">=</span> <span class="core">shift</span><span class="structure">;</span><br /> <span class="word">say</span> <span class="symbol">$self</span><span class="operator">-></span><span class="word">name</span><span class="operator">,</span> <span class="double">": "</span><span class="operator">,</span> <span class="magic">@_</span><span class="structure">;</span><br /><span class="structure">}</span><br /><br /><span class="number">1</span><span class="structure">;</span></code></pre>
<p>The system is very flexible. Have some events only some people can act on? No problem, just have those special ones listen to the events. For example, only a bona fide cook should be trusted with taking control of the kitchen:</p>
<pre><code class="code-listing"><span class="keyword">package</span> <span class="word">Cook</span><span class="structure">;</span><br /><br /><span class="keyword">use</span> <span class="pragma">strict</span><span class="structure">;</span><br /><span class="keyword">use</span> <span class="pragma">warnings</span><span class="structure">;</span><br /><br /><span class="keyword">use</span> <span class="word">Trimming</span><span class="structure">;</span><br /><br /><span class="keyword">use</span> <span class="word">Moose::Role</span><span class="structure">;</span><br /><br /><span class="word">after</span> <span class="single">'register_events'</span> <span class="operator">=></span> <span class="keyword">sub</span> <span class="structure">{</span><br /> <span class="keyword">my</span> <span class="symbol">$self</span> <span class="operator">=</span> <span class="core">shift</span><span class="structure">;</span><br /><br /> <span class="symbol">$self</span><span class="operator">-></span><span class="word">on</span><span class="structure">(</span> <span class="single">'prepare'</span><span class="operator">,</span> <span class="keyword">sub</span> <span class="structure">{</span><br /> <span class="symbol">$self</span><span class="operator">-></span><span class="word">prepare_supper</span><span class="structure">;</span><br /> <span class="structure">});</span><br /><span class="structure">};</span><br /><br /><span class="keyword">sub</span> <span class="word">prepare_supper</span> <span class="structure">{</span><br /> <span class="keyword">my</span> <span class="symbol">$self</span> <span class="operator">=</span> <span class="core">shift</span><span class="structure">;</span><br /><br /> <span class="symbol">$self</span><span class="operator">-></span><span class="word">is_busy</span><span class="structure">(</span><span class="number">1</span><span class="structure">);</span><br /><br /><span class="comment"> # needs help with the fixings<br /></span> <span class="symbol">$self</span><span class="operator">-></span><span class="word">emit</span><span class="structure">(</span> <span class="single">'need fixing'</span><span class="operator">,</span> <br /> <span class="word">class</span> <span class="operator">=></span> <span class="single">'Trimming'</span><span class="operator">,</span><br /> <span class="word">type</span> <span class="operator">=></span> <span class="magic">$_</span><br /> <span class="structure">)</span> <span class="word">for</span> <span class="words">qw/ potatoes pickles gravy /</span><span class="structure">;</span><br /><br /><span class="comment"> # prepare the turkey<br /></span> <span class="symbol">$self</span><span class="operator">-></span><span class="word">table</span><span class="operator">-></span><span class="structure">{</span> <span class="word">turkey</span> <span class="structure">}</span> <span class="operator">=</span> <span class="structure">{</span> <span class="word">white</span> <span class="operator">=></span> <span class="single">'4'</span><span class="operator">,</span> <span class="word">dark</span> <span class="operator">=></span> <span class="single">'4'</span> <span class="structure">};</span> <br /><br /> <span class="symbol">$self</span><span class="operator">-></span><span class="word">say</span><span class="structure">(</span> <span class="double">"turkey's done"</span> <span class="structure">);</span><br /><span class="structure">}</span><br /><br /><span class="number">1</span><span class="structure">;</span></code></pre>
<p>Need to pass on some additional information with an event, like what type of trimming needs to be attended to? With <i>Beam::Emitter</i>, the events are passed objects, so you can create a a sub-class containing the data you want and it's all good:</p>
<pre><code class="code-listing"><span class="keyword">package</span> <span class="word">Trimming</span><span class="structure">;</span><br /><br /><span class="keyword">use</span> <span class="pragma">strict</span><span class="structure">;</span><br /><span class="keyword">use</span> <span class="pragma">warnings</span><span class="structure">;</span><br /><br /><span class="keyword">use</span> <span class="word">Moose</span><span class="structure">;</span><br /><br /><span class="word">extends</span> <span class="single">'Beam::Event'</span><span class="structure">;</span><br /><br /><span class="word">has</span> <span class="double">"type"</span> <span class="operator">=></span> <span class="structure">(</span><br /> <span class="word">isa</span> <span class="operator">=></span> <span class="single">'Str'</span><span class="operator">,</span><br /> <span class="word">is</span> <span class="operator">=></span> <span class="single">'ro'</span><span class="operator">,</span><br /> <span class="word">required</span> <span class="operator">=></span> <span class="number">1</span><span class="operator">,</span><br /><span class="structure">);</span><br /><br /><span class="number">1</span><span class="structure">;</span></code></pre>
<p>And with that... believe it or not, you're all set to go. Well, almost. We still have to send our invitations and launch the festivities:</p>
<pre><code class="code-listing"><span class="comment"># supper.pl<br /></span><br /><span class="keyword">use</span> <span class="pragma">strict</span><span class="structure">;</span><br /><span class="keyword">use</span> <span class="pragma">warnings</span><span class="structure">;</span><br /><br /><span class="keyword">use</span> <span class="word">XmasSupper</span><span class="structure">;</span><br /><span class="keyword">use</span> <span class="word">Peep</span><span class="structure">;</span><br /><br /><span class="keyword">my</span> <span class="symbol">$supper</span> <span class="operator">=</span> <span class="word">XmasSupper</span><span class="operator">-></span><span class="word">new</span><span class="structure">;</span><br /><br /><span class="symbol">$supper</span><span class="operator">-></span><span class="word">invite</span><span class="structure">(</span> <span class="magic">$_</span> <span class="structure">)</span> <span class="word">for</span> <br /> <span class="word">Peep</span><span class="operator">-></span><span class="word">new</span><span class="structure">(</span><br /> <span class="word">name</span> <span class="operator">=></span> <span class="single">'Mrs. Cratchit'</span><span class="operator">,</span><br /> <span class="word">is_cook</span> <span class="operator">=></span> <span class="number">1</span><span class="operator">,</span><br /> <span class="word">turkey_preference</span> <span class="operator">=></span> <span class="single">'white'</span><span class="operator">,</span><br /> <span class="word">trimmings</span> <span class="operator">=></span> <span class="structure">[</span> <span class="single">'gravy'</span><span class="operator">,</span> <span class="single">'potatoes'</span> <span class="structure">]</span><span class="operator">,</span><br /> <span class="structure">)</span><span class="operator">,</span><br /> <span class="word">Peep</span><span class="operator">-></span><span class="word">new</span><span class="structure">(</span><br /> <span class="word">name</span> <span class="operator">=></span> <span class="single">'Bob'</span><span class="operator">,</span><br /> <span class="word">turkey_preference</span> <span class="operator">=></span> <span class="single">'dark'</span><span class="operator">,</span><br /> <span class="word">trimmings</span> <span class="operator">=></span> <span class="structure">[</span> <span class="single">'gravy'</span><span class="operator">,</span> <span class="single">'potatoes'</span><span class="operator">,</span> <span class="single">'pickles'</span> <span class="structure">]</span><span class="operator">,</span><br /> <span class="structure">)</span><span class="operator">,</span><br /> <span class="word">Peep</span><span class="operator">-></span><span class="word">new</span><span class="structure">(</span><br /> <span class="word">name</span> <span class="operator">=></span> <span class="single">'Timothy'</span><span class="operator">,</span><br /> <span class="word">turkey_preference</span> <span class="operator">=></span> <span class="single">'dark'</span><span class="operator">,</span><br /> <span class="word">trimmings</span> <span class="operator">=></span> <span class="structure">[</span> <span class="single">'gravy'</span><span class="operator">,</span> <span class="single">'pickles'</span> <span class="structure">]</span><span class="operator">,</span><br /> <span class="structure">)</span><span class="operator">,</span><br /> <span class="word">Peep</span><span class="operator">-></span><span class="word">new</span><span class="structure">(</span><br /> <span class="word">name</span> <span class="operator">=></span> <span class="single">'Martha'</span><span class="operator">,</span><br /> <span class="word">turkey_preference</span> <span class="operator">=></span> <span class="single">'dark'</span><span class="operator">,</span><br /> <span class="word">trimmings</span> <span class="operator">=></span> <span class="structure">[</span> <span class="single">'potatoes'</span><span class="operator">,</span> <span class="single">'pickles'</span> <span class="structure">]</span><span class="operator">,</span><br /> <span class="structure">)</span><span class="operator">,</span><br /> <span class="word">Peep</span><span class="operator">-></span><span class="word">new</span><span class="structure">(</span><br /> <span class="word">name</span> <span class="operator">=></span> <span class="single">'Peter'</span><span class="operator">,</span><br /> <span class="word">turkey_preference</span> <span class="operator">=></span> <span class="single">'white'</span><span class="operator">,</span><br /> <span class="word">trimmings</span> <span class="operator">=></span> <span class="structure">[</span> <span class="single">'pickles'</span> <span class="structure">]</span><span class="operator">,</span><br /> <span class="structure">)</span><span class="operator">,</span><br /> <span class="word">Peep</span><span class="operator">-></span><span class="word">new</span><span class="structure">(</span><br /> <span class="word">name</span> <span class="operator">=></span> <span class="single">'Bilinda'</span><span class="operator">,</span><br /> <span class="word">turkey_preference</span> <span class="operator">=></span> <span class="single">'white'</span><span class="operator">,</span><br /> <span class="word">trimmings</span> <span class="operator">=></span> <span class="structure">[</span> <span class="single">'gravy'</span> <span class="structure">]</span><span class="operator">,</span><br /> <span class="structure">);</span><br /><br /><span class="symbol">$supper</span><span class="operator">-></span><span class="word">prepare</span><span class="structure">;</span><br /><br /><span class="symbol">$supper</span><span class="operator">-></span><span class="word">serve</span><span class="structure">;</span><br /><br /><span class="symbol">$supper</span><span class="operator">-></span><span class="word">eat</span><span class="structure">;</span><br /><br /><span class="symbol">$supper</span><span class="operator">-></span><span class="word">done</span><span class="structure">;</span></code></pre>
<p>And then... lo and behold:</p>
<pre><code> $ perl supper.pl
Bob: preparing the potatoes
Timothy: preparing the pickles
Martha: preparing the gravy
Mrs. Cratchit: turkey's done
Timothy: no more gravy
Martha: no more potatoes
Martha: no more pickles
Peter: no more pickles
Bilinda: no more gravy
Mrs. Cratchit: O NOM NOM NOM
{"turkey":1,"fixing":{"gravy":1,"potatoes":1}}
Bob: O NOM NOM NOM
{"turkey":1,"fixing":{"pickles":1,"gravy":1,"potatoes":1}}
Timothy: O NOM NOM NOM
{"turkey":1,"fixing":{"pickles":1}}
Martha: O NOM NOM NOM
{"turkey":1}
Peter: O NOM NOM NOM
{"turkey":1}
Bilinda: O NOM NOM NOM
{"turkey":1}
leftovers: {"turkey":{"white":1,"dark":1},"fixing":{"gravy":0,"pickles":0,"potatoes":0}}
Timothy: God bless us, every one!</code></pre>
<h2 id="See-Also">See Also</h2>
<ul>
<li><p><a href="https://metacpan.org/module/Beam::Emitter">Beam::Emitter</a></p>
</li>
</ul>
</div>2013-12-16T00:00:00ZYanick ChampouxGot Git? Ask Santa to get Got!http://perladvent.org/2013/2013-12-15.html<div class='pod'><h3 id="Many-Git-Repos-Can-Get-Messy">Many Git Repos Can Get Messy</h3>
<p>Like most developers, I've got a <i>lot</i> of source code in Git repositories, scattered and duplicated across the four-odd machines I use on a regular basis (the laptop, the server, the other laptop, the VPS...) It's actually worse than that, because it's not just source code — I've got various configuration files in different repositories, a couple repositories that just contain documents, and so on. I keep everything in sync and configured the same across all my machines by depending on these repositories to be reasonably up-to-date with the master copy (which is some times at Github, some times on $WORK's repo server, some times on one of my servers...)</p>
<p>In order to effectively manage the all these git repositories, from all those different locations, across all those machines, I use <a href="https://metacpan.org/pod/App::GitGot">got</a>. <code>got</code> is a utility that makes it trivial to run various <code>git</code> commands across some or all of the repositories that <code>got</code> knows about.</p>
<h3 id="Get-GitGot">Get GitGot</h3>
<p>Before you can use <code>got</code>, you need to install it. Luckily, it's on CPAN, in the <a href="https://metacpan.org/module/App::GitGot">App::GitGot</a> dist. Fire up your favorite CPAN client and install that, and once all the dependencies install, you should have a shiny new <code>got</code> command available to you. Much like <code>git</code>, <code>got</code> works via a series of sub-commands — if you just run <code>got</code>, you'll get a list of all the available sub-commands.</p>
<h3 id="Gotta-tell-got-where-your-git-repos-are">Gotta tell got where your git repos are</h3>
<p>In order for <code>got</code> to manage your repositories, you'll have to add them to the configuration file. (By default, this lives at <code>~/.gitgot</code>.) One way to add a repo is the <code>got add</code> command — <code>cd</code> into the repo you want to add, and run <code>got add</code>. You'll be prompted for a few pieces of info — the defaults are generally correct — and then the repository will be added to the config file.</p>
<pre><code> % got add
Name: etc
URL: git@github.com:genehack/etc.git
Path: /Users/genehack/etc
Tags: config</code></pre>
<p>Note the "Tags" entry — as we'll see shortly, tags are one way you can select repositories to operate on.</p>
<p>If you want to just accept the defaults without having a chance to edit them, you can run <code>got add -D</code>, which will just accept the default options. Currently, there isn't any command to edit a repository after it has been added (to add or change tags, for example), but the configuration file is a very simple YAML file which is trivial to hand-edit.</p>
<p>There are a couple of other sub-commands that add repositories to your config file. <code>got clone $CLONE_URL</code> will run <code>git clone</code> on the given URL, and then add the resulting repository checkout to your <code>got</code> config. Similarly, <code>got fork $GITHUB_URL</code> will fork the given Github repo, then clone the resulting fork, and finally add it to your <code>got</code> config. The <code>got fork</code> sub-command depends on having a properly configured <code>~/.github-identity</code> file with your Github authentication information.</p>
<h3 id="Got-Gets-Your-Git-Repos-In-Line">Got Gets Your Git Repos In Line</h3>
<p>Once you've added some git repositories to your <code>got</code> config file, you can use <code>got</code> to carry out various batch operations. For example, you can show all the repositories <code>got</code> is aware of with the <code>got list</code> (aka <code>got ls</code>) sub-command. You can also specify a subset of repositories to operate on by providing additional arguments. For example, given this output:</p>
<pre><code> % got ls
1) Perl-Build git git://github.com/tokuhirom/Perl-Build
2) STAMPS git git@github.com:genehack/STAMPS.git
3) app-gitgitr git git@github.com:genehack/app-gitgitr.git
4) app-gitgot git git@github.com:genehack/app-gitgot.git
5) app-miseenplace git git@github.com:genehack/app-miseenplace.git
6) build-color git git@github.com:genehack/build-color.git
7) dosetool git genehack.net:/var/git/private/dosetool
8) emacs git git@github.com:genehack/emacs.git
9) etc git git@github.com:genehack/etc.git</code></pre>
<p>You can specify one or more repository index numbers, or number ranges, to only select certain repos. For example:</p>
<pre><code> % got ls 2 4-6 7 9
2) STAMPS git git@github.com:genehack/STAMPSOB.git
4) app-gitgot git git@github.com:genehack/app-gitgot.git
5) app-miseenplace git git@github.com:genehack/app-miseenplace.git
6) build-color git git@github.com:genehack/build-color.git
7) dosetool git genehack.net:/var/git/private/dosetool
9) etc git git@github.com:genehack/etc.git</code></pre>
<p>You can also specify tags with the <code>-t</code> flag:</p>
<pre><code> % got ls -t config
5) app-miseenplace git git@github.com:genehack/app-miseenplace.git
8) emacs git git@github.com:genehack/emacs.git
9) etc git git@github.com:genehack/etc.git</code></pre>
<p>Multiple <code>-t</code> options may be given, in which case they are combined in a "logical OR" fashion.</p>
<p>Finally, you can specify repos by name:</p>
<pre><code> % got ls emacs
8) emacs git git@github.com:genehack/emacs.git</code></pre>
<p>This ability to select a subset of repositories to operate on applies not just to the <code>got ls</code> subcommand, but to any <code>got</code> subcommand that operates on multiple repositories, such as <code>got gc</code>, <code>got status</code>, or <code>got update</code>.</p>
<h3 id="Gotta-Get-It-Together-Now">Gotta Get It Together Now</h3>
<p>As I mentioned above, I depend on a number of git repositories being kept up to date with the master copy in order to propagate configuration changes across machines and to maintain consistency in how things are configured. I do this by frequently (at least once a week, if not more often), using a combination of <code>got update_status</code> and <code>got status</code> to first update all the repositories on a given machine, then display repositories that have either uncommitted changes or changes that have been locally committed but not pushed up to the master. By using these two commands and iterating across all my active machines, it becomes trivial to make sure everything is up to date.</p>
<p><b>Note:</b> The <code>update_status</code>, <code>update</code>, and <code>status</code> commands all take an optional <code>-q</code> (for quiet) flag. This hides the output from repositories that don't have anything "interesting" to show — all the unchanged repos, all the clean repos that are in sync with the remote, etc. Also worth noting is that the <code>update</code> command does a <code>git pull</code>. There's an outstanding request for a <code>git fetch</code> command, which is waiting on me to have a spare tuit, or some brave volunteer to send in a pull request.</p>
<h3 id="But-Wait-We-Got-More">But Wait, We Got More</h3>
<p><code>got</code> also has a number of commands that are designed to make it easier to work with individual repositories without needing to know exactly where they live on disk. The <code>got chdir REPO</code> command spawns a new subshell inside the given repository, and the <code>got tmux REPO</code> subcommand (contributed by Yanick Champoux) spawns a new <code>tmux</code> window with the working directory inside the given repository. The repository's name will be used as the name of the <code>tmux</code> window. If the window has already been created by a previous invocation of <code>got tmux</code>, instead of creating a new window, the existing window will be selected.</p>
<p>If you're curious whether a given repository is being managed by <code>got</code>, you can use the <code>got this</code> command (contributed by Yanick Champoux) while inside the repository. If it is managed by <code>got</code>, you'll get back the listing output for the repo. If it is not managed by <code>got</code>, you'll see a message to that effect.</p>
<h3 id="What-You-Got">What You Got?</h3>
<p>At this point, <code>got</code> is a very good fit for my personal workflow around git repositories across multiple machines. I realize, however, that my workflow is not everybody's workflow, and I'm very open to additional commands or command flags being added to make <code>got</code> more generically useful to more people. <code>got</code> was also originally intended to be a VCS-agnostic tool; it just so happened that around the time I got the first usable version of it completed, my need to use anything other than <code>git</code> for revision control evaporated. The extension hooks for other VCSen are still in place, however, and I would love to merge code that adds SVN, Hg, or even CVS support.</p>
<p>Please fork the <a href="http://github.com/genehack/app-gitgot/">repository</a> on Github, add your own contribution, and send in a pull request!</p>
<h3 id="Acknowledgments">Acknowledgments</h3>
<p><code>got</code> was originally very heavily inspired by a similar tool, developed by Ingy döt Net, called <a href="https://metacpan.org/pod/App::AYCABTU">App::AYCABTU</a>. In particular, the repository selection interface and large chunks of the config file were shamelessly pilfered. <code>got</code> has also been greatly improved by the efforts of Yanick Champoux, Mike Greb, and Chris Prather, as well as everybody who has reported a bug or wishlist feature.</p>
<h2 id="See-Also">See Also</h2>
<ul>
<li><p><a href="https://metacpan.org/module/App::GitGot">App::GitGot</a></p>
</li>
</ul>
</div>2013-12-15T00:00:00ZJohn SJ AndersonShake those gifts and figure out what's inside!http://perladvent.org/2013/2013-12-14.html<div class='pod'><h3 id="How-does-my-database-do-this-thing">How does my database do this thing?</h3>
<p>Okay, so you write a library that talks to a database, but you don't control what kind. You only got the DSN and the connection at runtime, and you want it to work all over the place. That's hard! What if you need to do something that's done differently on different database systems, like concatenate two strings?</p>
<p>You can use DBIx::Introspector.</p>
<pre><code class="code-listing"><span class="keyword">my</span> <span class="symbol">$d</span> <span class="operator">=</span> <span class="word">DBIx::Introspector</span><span class="operator">-></span><span class="word">new</span><span class="structure">(</span><span class="word">drivers</span> <span class="operator">=></span> <span class="single">'2013-12.01'</span><span class="structure">);</span><br /><br /><span class="word">setup_standard_dialects</span><span class="structure">(</span><span class="symbol">$d</span><span class="structure">);</span> <span class="comment"># we'll come back to this!</span><br /><br /><span class="comment"># This will tell us how to concatenate two strings!<br /></span><span class="keyword">my</span> <span class="symbol">$concat</span> <span class="operator">=</span> <span class="symbol">$d</span><span class="operator">-></span><span class="word">get</span><span class="structure">(</span><span class="symbol">$dbh</span><span class="operator">,</span> <span class="symbol">$dsn</span><span class="operator">,</span> <span class="single">'concat_sql'</span><span class="structure">);</span><br /><br /><span class="symbol">$concat</span> <span class="operator">=</span> <span class="word">sprintf</span><span class="structure">(</span><span class="symbol">$concat</span><span class="operator">,</span> <span class="single">'first_name'</span><span class="operator">,</span> <span class="single">'last_name'</span><span class="structure">);</span><br /><span class="keyword">my</span> <span class="symbol">$sth</span> <span class="operator">=</span> <span class="symbol">$dbh</span><span class="operator">-></span><span class="word">prepare</span><span class="structure">(</span><span class="double">"SELECT $concat AS name FROM people"</span><span class="structure">);</span></code></pre>
<p>If we were already using DBIx::Class, we could get the database handle from that:</p>
<pre><code class="code-listing"><span class="symbol">$d</span><span class="operator">-></span><span class="word">get</span><span class="structure">(</span><br /> <span class="keyword">sub</span> <span class="structure">{</span> <span class="symbol">$schema</span><span class="operator">-></span><span class="word">storage</span><span class="operator">-></span><span class="word">dbh</span> <span class="structure">}</span><span class="operator">,</span><br /> <span class="symbol">$dsn</span><span class="operator">,</span><br /> <span class="single">'concat_sql'</span><span class="operator">,</span><br /> <span class="structure">{</span> <span class="word">dbh_fallback_connect</span> <span class="operator">=></span> <span class="keyword">sub</span> <span class="structure">{</span> <span class="symbol">$schema</span><span class="operator">-></span><span class="word">storage</span><span class="operator">-></span><span class="word">ensure_connected</span> <span class="structure">}</span> <span class="structure">}</span><span class="operator">,</span><br /><span class="structure">);</span><br /><br /><span class="symbol">$concat</span> <span class="operator">=</span> <span class="word">sprintf</span><span class="structure">(</span><span class="symbol">$concat</span><span class="operator">,</span> <span class="single">'first_name'</span><span class="operator">,</span> <span class="single">'last_name'</span><span class="structure">);</span><br /><span class="symbol">$rs</span><span class="operator">-></span><span class="word">search</span><span class="structure">(</span><span class="core">undef</span><span class="operator">,</span> <span class="structure">{</span><br /> <span class="single">'+columns'</span> <span class="operator">=></span> <span class="structure">{</span><br /> <span class="word">name</span> <span class="operator">=></span> <span class="cast">\</span><span class="symbol">$concat</span><span class="operator">,</span><br /> <span class="structure">}</span><span class="operator">,</span><br /><span class="structure">});</span></code></pre>
<h3 id="Why-DBIx::Introspector">Why DBIx::Introspector?</h3>
<p>A common (but rarely acknowledged) problem when writing portable SQL is accurately detecting what kind of database you are connected to and, sometimes, how you have connected. The typical solution is to assume that your database driver has a one-to-one mapping to your database. This works for many cases, for example many people only use <a href="https://metacpan.org/module/DBD::mysql">DBD::mysql</a> to connect to mysql, <a href="https://metacpan.org/module/DBD::Pg">DBD::Pg</a> to connect to Postgres, and <a href="https://metacpan.org/module/DBD::SQLite">DBD::SQLite</a> to connect to SQLite.</p>
<p>The problem comes when you use a more generic driver. For example <a href="https://metacpan.org/module/DBD::ODBC">DBD::ODBC</a> can connect to any database that supports ODBC (which includes mysql, Postgres, Oracle, and probably most importantly SQL Server.) Often users assume that ODBC means SQL Server but, that's clearly not correct.</p>
<p><a href="https://metacpan.org/module/DBIx::Introspector">DBIx::Introspector</a> solves this problem (as well as one other). It has a basic but mostly complete set of detection methods. If, after it is released, there are problems discovered in the detection methods, the user can easily swap in new detection methods. The other feature that DBIx::Introspector gives the user is a way to query database handles (or DSNs) for various pieces of information.</p>
<h3 id="How-can-I-use-it">How can I use it?</h3>
<p>For starters, you need to define a new DBIx::Introspector. Let's pretend we are writing some program that needs to concatenate stuff in the database, and should support some major databases. This code is probably sufficient, and is what we'd do in the imaginary <code>setup_standard_dialects</code> mentioned in the code above:</p>
<pre><code class="code-listing"><span class="keyword">my</span> <span class="symbol">$d</span> <span class="operator">=</span> <span class="word">DBIx::Introspector</span><span class="operator">-></span><span class="word">new</span><span class="structure">(</span><span class="word">drivers</span> <span class="operator">=></span> <span class="single">'2013-12.01'</span><span class="structure">);</span><br /><br /><span class="comment"># standard dialects<br /></span><span class="symbol">$d</span><span class="operator">-></span><span class="word">decorate_driver_unconnected</span><span class="structure">(</span><span class="word">Pg</span> <span class="operator">=></span> <span class="word">concat_sql</span> <span class="operator">=></span> <span class="single">'%s || %s'</span><span class="structure">);</span><br /><span class="symbol">$d</span><span class="operator">-></span><span class="word">decorate_driver_unconnected</span><span class="structure">(</span><span class="word">SQLite</span> <span class="operator">=></span> <span class="word">concat_sql</span> <span class="operator">=></span> <span class="single">'%s || %s'</span><span class="structure">);</span><br /><br /><span class="comment"># non-standard<br /></span><span class="symbol">$d</span><span class="operator">-></span><span class="word">decorate_driver_unconnected</span><span class="structure">(</span><span class="word">MSSQL</span> <span class="operator">=></span> <span class="word">concat_sql</span> <span class="operator">=></span> <span class="single">'%s + %s'</span><span class="structure">);</span><br /><span class="symbol">$d</span><span class="operator">-></span><span class="word">decorate_driver_unconnected</span><span class="structure">(</span><span class="word">mysql</span> <span class="operator">=></span> <span class="word">concat_sql</span> <span class="operator">=></span> <span class="single">'CONCAT( %s, %s )'</span><span class="structure">);</span></code></pre>
<p>First, note that we specify a string (<code>2013-12.01</code>) for drivers. In order to maintain backwards compatibility DBIx::Introspector forces the user to request a driver set. Currently just one set exists, which attempts to match what <a href="https://metacpan.org/module/DBIx::Class">DBIx::Class</a> does internally at the time of release.</p>
<p>Next, the <code>decorate_driver_unconnected</code> call; "unconnected" is because these facts could be determined whether we were connected to the database or not. An example of a connected fact might be the following:</p>
<pre><code class="code-listing"><span class="symbol">$d</span><span class="operator">-></span><span class="word">decorate_driver_connected</span><span class="structure">(</span><br /> <span class="word">MSSQL</span> <span class="operator">=></span> <span class="word">full_version</span> <span class="operator">=></span> <span class="keyword">sub</span> <span class="structure">{</span><br /> <span class="keyword">my</span> <span class="structure">(</span><span class="core">undef</span><span class="operator">,</span> <span class="symbol">$dbh</span><span class="structure">)</span> <span class="operator">=</span> <span class="magic">@_</span><span class="structure">;</span><br /> <span class="keyword">my</span> <span class="structure">(</span><span class="symbol">$ret</span><span class="structure">)</span> <span class="operator">=</span> <span class="symbol">$dbh</span><span class="operator">-></span><span class="word">selectcol_arrayref</span><span class="structure">(</span><span class="single">'SELECT @@VERSION'</span><span class="structure">);</span><br /> <span class="keyword">return</span> <span class="symbol">$ret</span><br /> <span class="structure">}</span><span class="operator">,</span><br /><span class="structure">);</span></code></pre>
<p>The above code uses a connected <code>$dbh</code> to ask SQL Server what the versions are of the database, OS, patchlevel, etc.</p>
<p>Because this is basically a prototype object system you can easily add and replace drivers:</p>
<pre><code class="code-listing"><span class="symbol">$d</span><span class="operator">-></span><span class="word">replace_driver</span><span class="structure">({</span><br /> <span class="word">name</span> <span class="operator">=></span> <span class="single">'MSSQL'</span><span class="operator">,</span><br /> <span class="word">connected_determination_strategy</span> <span class="operator">=></span> <span class="keyword">sub</span> <span class="structure">{</span><br /> <span class="keyword">my</span> <span class="symbol">%to</span> <span class="operator">=</span> <span class="structure">(</span><br /> <span class="number">11</span> <span class="operator">=></span> <span class="single">'2012'</span><span class="operator">,</span><br /> <span class="number">10</span> <span class="operator">=></span> <span class="single">'2008'</span><span class="operator">,</span><br /> <span class="number">9</span> <span class="operator">=></span> <span class="single">'2005'</span><span class="operator">,</span><br /> <span class="structure">);</span><br /> <span class="keyword">my</span> <span class="structure">(</span><span class="symbol">$ver</span><span class="structure">)</span> <span class="operator">=</span><br /> <span class="magic">$_</span><span class="structure">[</span><span class="number">1</span><span class="structure">]</span><span class="operator">-></span><span class="word">selectcol_arrayref</span><span class="structure">(</span><span class="literal">q(SELECT SERVERPROPERTY('ProductVersion'))</span><span class="structure">);</span><br /> <span class="keyword">my</span> <span class="structure">(</span><span class="symbol">$major</span><span class="structure">)</span> <span class="operator">=</span> <span class="symbol">$ver</span> <span class="operator">=~</span> <span class="match">m/^(\d+)\./</span><span class="structure">;</span><br /> <span class="keyword">my</span> <span class="symbol">$to</span> <span class="operator">=</span> <span class="symbol">$to</span><span class="structure">{</span><span class="symbol">$ver</span><span class="structure">}</span> <span class="operator">||</span> <span class="single">'-OlderThanDirt'</span><span class="operator">,</span> <span class="comment"># or newer, but it's a demo</span><br /> <span class="keyword">return</span> <span class="double">"MSSQL$to"</span><br /> <span class="structure">}</span><span class="operator">,</span><br /><span class="structure">});</span><br /><br /><span class="symbol">$d</span><span class="operator">-></span><span class="word">add_driver</span><span class="structure">(</span><span class="magic">$_</span><span class="structure">)</span> <span class="word">for</span> <span class="words">qw({<br /> name => 'MSSQL2000',<br /> unconnected_options => { pagination_method => 'top' },<br />},{<br /> name => 'MSSQL2005',<br /> unconnected_options => { pagination_method => 'rno' },<br />},{<br /> name => 'MSSQL2008',<br /> unconnected_options => { pagination_method => 'rno' },<br />},{<br /> name => 'MSSQL2012',<br /> unconnected_options => { pagination_method => 'sql2012' },<br />},{<br /> name => 'MSSQL-OlderThanDirt',<br /> # documentation doesn't get this old, so who knows!<br />})</span><span class="structure">;</span></code></pre>
<p>This code replaces the MSSQL driver with one that has another layer of detection based on version, and then adds drivers for each (sensible) version. The <code>unconnected_options</code> define a known pagination methods for reasonably recent versions of SQL Server.</p>
<h3 id="Whats-next">What's next?</h3>
<p>For DBIx::Introspector, there are probably more drivers that could be defined. Additionally a standard set of facts would be very handy. Caching the detection might be worthwhile, but I'd rather wait until someone notices a speed issue before doing that.</p>
<p>On top of that, a number of doors are opened by DBIx::Introspector. For example, the long dormant <a href="https://github.com/frioux/DBIx-Exceptions">DBIx::Exceptions</a> has been blocking on exactly this problem. Furthermore a number of already existing modules could be improved by the use of DBIx::Introspector, most notably <a href="https://metacpan.org/module/DBIx::Connector">DBIx::Connector</a>, which doesn't work for anything using ODBC, ADO, and other non-one-to-one drives.</p>
<h2 id="See-Also">See Also</h2>
<ul>
<li><p><a href="https://metacpan.org/module/DBIx::Introspector">DBIx::Introspector</a></p>
</li>
<li><p><a href="https://metacpan.org/module/DBIx::Connector">DBIx::Connector</a></p>
</li>
<li><p><a href="https://github.com/frioux/DBIx-Exceptions">DBIx::Exceptions</a></p>
</li>
<li><p><a href="https://metacpan.org/module/DBIx::Class">DBIx::Class</a></p>
</li>
</ul>
</div>2013-12-14T00:00:00ZArthur Axel "fREW" SchmidtBisecting Perl to find when something broke (or was fixed!)http://perladvent.org/2013/2013-12-13.html<div class='pod'><p>So, it's Christmas Eve and you've decided now's the time to update production to the latest and greatest version of Perl. But since you don't want to spend your holidays fixing production, you decide to build Perl on your dev machine and run your ample test suite against it first.</p>
<p>One of your tests looks like this: (Why it has your production code in it I have no idea):</p>
<pre><code class="code-listing"><span class="comment"># t/a_test.t<br /></span><span class="keyword">use</span> <span class="pragma">strict</span><span class="structure">;</span><br /><span class="keyword">use</span> <span class="pragma">warnings</span><span class="structure">;</span><br /><br /><span class="keyword">use</span> <span class="word">Test::More</span><span class="structure">;</span><br /><span class="word">plan</span> <span class="word">tests</span> <span class="operator">=></span> <span class="number">4</span><span class="structure">;</span><br /><br /><span class="keyword">sub</span> <span class="word">terrible</span> <span class="structure">{</span><br /> <span class="keyword">my</span> <span class="symbol">$gift</span> <span class="operator">=</span> <span class="core">shift</span><span class="structure">;</span><br /><br /> <span class="keyword">return</span> <span class="number">1</span> <span class="word">if</span> <span class="symbol">$gift</span> <span class="operator">=~</span> <span class="match">/(charcoal|sweater)/</span><span class="structure">;</span><br /><span class="structure">}</span><br /><br /><span class="keyword">for</span> <span class="keyword">my</span> <span class="symbol">$gift</span> <span class="words">qw(charcoal sweater)</span> <span class="structure">{</span><br /> <span class="word">ok</span><span class="structure">(</span><span class="word">terrible</span><span class="structure">(</span><span class="symbol">$gift</span><span class="structure">)</span><span class="operator">,</span> <span class="double">"Gift $gift is terrible!"</span><span class="structure">);</span><br /><span class="structure">}</span><br /><br /><span class="keyword">for</span> <span class="keyword">my</span> <span class="symbol">$gift</span> <span class="words">qw(car motorcycle)</span> <span class="structure">{</span><br /> <span class="word">ok</span><span class="structure">(</span><span class="operator">!</span><span class="word">terrible</span><span class="structure">(</span><span class="symbol">$gift</span><span class="structure">)</span><span class="operator">,</span> <span class="double">"Gift $gift is awesome!"</span><span class="structure">);</span><br /><span class="structure">}</span></code></pre>
<p>After upgrading Perl from 5.8.8 to 5.18.1, you find this test breaks:</p>
<pre><code> $ perl-5.18.1 ~/t/a_test.t
"my" variable $gift masks earlier declaration in same statement at ~/t/a_test.t line 18.
"my" variable $gift masks earlier declaration in same statement at ~/t/a_test.t line 19.
syntax error at ~/t/a_test.t line 14, near "$gift qw(charcoal sweater)"
Global symbol "$gift" requires explicit package name at ~/t/a_test.t line 15.
Execution of ~/t/a_test.t aborted due to compilation errors.</code></pre>
<p>But why?! That's perfectly valid Perl!</p>
<h2 id="Bisecting-to-the-rescue">Bisecting to the rescue!</h2>
<p>Thankfully, with a clone of the Perl git repository, we can answer this question. So first we grab a copy:</p>
<pre><code> $ git clone git://perl5.git.perl.org/perl.git perl</code></pre>
<p>In <i>Porting/</i> you'll find a tool called <i>bisect.pl</i>. This is a nice wrapper around <a href="http://man.he.net/man1/git-bisect">git-bisect(1)</a> that will build Perl for each revision being tested and run your tests, telling you when your test first broke.</p>
<p>However, this script cannot be run from the Perl repository it is testing, so first we must make a copy of a clean checkout of blead:</p>
<pre><code> $ git clone perl perl-2</code></pre>
<p>And now we can bisect Perl from 5.8.8 (when everything worked) to 5.18.1 (when our world collapsed) and wait a very long time to get our results:</p>
<pre><code> $ cd perl-2
$ ../perl/Porting/bisect.pl --start=perl-5.8.8 --end=v5.18.1 \
-- ./perl -Ilib ~/t/a_test.t</code></pre>
<p>Grab an eggnog, wrap some presents, write your memoirs, this will take awhile.</p>
<p>Optionally, we can make this go a <i>little</i> faster, because we have an awesome computer that we got last Christmas, and it can do many things in parallel. We just add a <code>-j</code> option which gets passed to <a href="http://man.he.net/man1/make">make(1)</a>:</p>
<pre><code> $ ../perl/Porting/bisect.pl --start=perl-5.8.8 --end=v5.18.1 \
-j 8 -- ./perl -Ilib ~/t/a_test.t</code></pre>
<p>Note that while above <code>--start</code> and <code>--end</code> are git tags, instead they could even be commit IDs.</p>
<p>Anyways, after waiting a long while the bisect finally finishes and tells us this:</p>
<pre><code> [...]
Use of qw(...) as parentheses is deprecated at ~/t/a_test.t line 14.
Use of qw(...) as parentheses is deprecated at ~/t/a_test.t line 18.
1..4
ok 1 - Gift charcoal is terrible!
ok 2 - Gift sweater is terrible!
ok 3 - Git car is awesome!
ok 4 - Git motorcycle is awesome!
HEAD is now at eb3d0a5 Block signals during fork (fixes RT#82580)
good - zero exit from ./perl -Ilib ~/t/a_test.t
417a992d4dc78be79e44d19e029d9742d0334128 is the first bad commit
commit 417a992d4dc78be79e44d19e029d9742d0334128
Author: Zefram <zefram@fysh.org>
Date: Fri May 25 22:25:21 2012 +0100
remove deprecated qw-as-parens behaviour
⋮
bisect run success
That took 2019 seconds</code></pre>
<p>Voila! And knowing that, we can fix our test by changing:</p>
<pre><code class="code-listing"><span class="keyword">for</span> <span class="keyword">my</span> <span class="symbol">$gift</span> <span class="words">qw(charcoal sweater)</span> <span class="structure">{</span></code></pre>
<p>To</p>
<pre><code class="code-listing"><span class="keyword">for</span> <span class="keyword">my</span> <span class="symbol">$gift</span> <span class="structure">(</span><span class="words">qw(charcoal sweater)</span><span class="structure">)</span> <span class="structure">{</span></code></pre>
<p>And</p>
<pre><code class="code-listing"><span class="keyword">for</span> <span class="keyword">my</span> <span class="symbol">$gift</span> <span class="words">qw(car motorcycle)</span> <span class="structure">{</span></code></pre>
<p>To</p>
<pre><code class="code-listing"><span class="keyword">for</span> <span class="keyword">my</span> <span class="symbol">$gift</span> <span class="structure">(</span><span class="words">qw(car motorcycle)</span><span class="structure">)</span> <span class="structure">{</span></code></pre>
<p>And upgrade our servers and go home and enjoy the holidays!</p>
<h2 id="A-few-more-tricks">A few more tricks…</h2>
<p>There are a few more neat things that <i>bisect.pl</i> can also do for us, and its documentation includes examples of many of them.</p>
<p>For instance, you don't need to provide a start and end, that just speeds things up:</p>
<pre><code> # When did this become an error?
../perl/Porting/bisect.pl -e 'my $a := 2;'</code></pre>
<p>Or you can search for the reverse:</p>
<pre><code> # When did this start working?
../perl/Porting/bisect.pl --expect-fail -e '1 // 2'</code></pre>
<p>Check out <code>perldoc Porting/pod/bisect-runner.pl</code> for more information.</p>
<h2 id="In-closing">In closing</h2>
<p><i>bisect.pl</i> is an incredibly useful tool. Here, we used it to find why some external Perl program failed, but it's most often used to figure out when something broke in Perl itself.</p>
<p>If you hack on the Perl language, keep this in your toolbelt. It will save you time and frustration.</p>
</div>2013-12-13T00:00:00ZMatthew HorsfallPresent Confusionhttp://perladvent.org/2013/2013-12-12.html<div class='pod'><p>"I was born in 270", proclaimed St Nick, "and I thought I'd seen everything. Until now that was."</p>
<p>Santa was staring into the source code for creating the naughty or nice list. The very definition of legacy system, the codebase hadn't faired well when the latest round of refactoring had been outsourced to the tooth fairies.</p>
<p>"This just shows we should never again go with the lowest bidder…" the Wise Old Elf sagely commented. "…even if they do only want payment in an excessive number of candy canes for unspecified purposes."</p>
<p>"Ho ho ho! The problem is we've now got two functions called 'present'. One that renders out part of the list, and one that refers to if the child should get a gift or coal. I suppose you've got a plan that's better than working out by hand which is which during the big search and replace?"</p>
<p>"Of course, your Jollyness, I'm going to use Perl to print out which one is used where", the Wise Old Elf explained.</p>
<p>"Ah the old 'caller' technique where you alter the functions to say where they're being called from"</p>
<pre><code class="code-listing"><span class="comment"># in Santa::NaughtyOrNice::Gift<br /></span><span class="keyword">sub</span> <span class="word">present</span> <span class="structure">{</span><br /> <span class="structure">{</span><br /> <span class="keyword">my</span> <span class="structure">(</span><span class="symbol">$package</span><span class="operator">,</span> <span class="symbol">$filename</span><span class="operator">,</span> <span class="symbol">$line</span><span class="structure">)</span> <span class="operator">=</span> <span class="word">caller</span><span class="structure">;</span><br /> <span class="word">say</span> <span class="word">STDERR</span> <span class="double">"present (as in gift) called at $filename line $line"</span><span class="structure">;</span><br /> <span class="structure">}</span><br /> <span class="operator">...</span><br /><span class="structure">}</span><br /><br /><span class="comment"># in Santa::NaughtyOrNice::Render<br /></span><span class="keyword">sub</span> <span class="word">present</span> <span class="structure">{</span><br /> <span class="structure">{</span><br /> <span class="keyword">my</span> <span class="structure">(</span><span class="symbol">$package</span><span class="operator">,</span> <span class="symbol">$filename</span><span class="operator">,</span> <span class="symbol">$line</span><span class="structure">)</span> <span class="operator">=</span> <span class="word">caller</span><span class="structure">;</span><br /> <span class="word">say</span> <span class="word">STDERR</span> <span class="double">"present (as in render) called at $filename line $line"</span><span class="structure">;</span><br /> <span class="structure">}</span><br /> <span class="operator">...</span><br /><span class="structure">}</span></code></pre>
<p>"No, your Festiveness", the Wise Old Elf replied, "That'd only print out when the functions in question are executed. But there's functions that aren't called every run of the program — why, here's some code that declares someone as naughty if they troll on MySpace. I bet that doesn't come up every day anymore".</p>
<p>"My intention", the Wise Old Elf continued, "is to instead hook the compilation stage of Perl to print out when the subroutine is used as soon it's compiled. There's a module for that you know…</p>
<pre><code> perl -c \
-MDevel::CompiledCalls=Santa::NaughtyOrNice::Render::present \
-MDevel::CompiledCalls=Santa::NaughtyOrNice::Gift::present \
naughty_or_nice.pl
Santa::NaughtyOrNice::Render::Gift::present call at /santa/lib/Santa/NaughtyOrNice/HairPulling.pm line 13
Santa::NaughtyOrNice::Render::Gift::present call at /santa/lib/Santa/NaughtyOrNice/HairPulling.pm line 49
Santa::NaughtyOrNice::Render::Render::present call at /santa/lib/Santa/NaughtyOrNice/Report.pm line 41
Santa::NaughtyOrNice::Render::Gift::present call at /santa/lib/Santa/NaughtyOrNice/SignificantWhitespace.pm line 134
Santa::NaughtyOrNice::Render::Gift::present call at /santa/lib/Santa/NaughtyOrNice/BadOrGood.pm line 1041
...</code></pre>
<h2 id="See-Also">See Also</h2>
<ul>
<li><p><a href="https://metacpan.org/module/Devel::CompiledCalls">Devel::CompiledCalls</a></p>
</li>
</ul>
</div>2013-12-12T00:00:00ZMark FowlerToystore Storyhttp://perladvent.org/2013/2013-12-11.html<div class='pod'><p>This year, Gluggagægir has been assigned to the <i>Trendy Toy Assembly Line</i>. His mission? To set up a system to track the inventory of each type of toy. His parameters? Make it light on infrastructure, make it such that every change is auditable, and make it as easy as possible to interact with by the main Elf IT division.</p>
<p>Knowing that his old IT division buddies are all command line junkies, Glugg decided to try something different: <a href="https://metacpan.org/module/GitStore">GitStore</a>. <i>GitStore</i> is a module that turns a Git repository into a datastore, and it comes with a <a href="https://metacpan.org/module/MooseX::Storage">MooseX::Storage</a> driver that turns it into a persistent object repository. Glugg rationalized that Git repositories are as light on the infrastructure as anything would ever be, are a pretty much the ultimate tool to keep track of change history, and could make his IT friends real happy if he was to choose the right object serialization format.</p>
<p>So Glugg went to work. Meaning: he poured himself a stiff egg nog mug and created a <i>Toy</i> class:</p>
<pre><code class="code-listing"><span class="keyword">package</span> <span class="word">Toy</span><span class="structure">;</span><br /><br /><span class="keyword">use</span> <span class="pragma">strict</span><span class="structure">;</span><br /><span class="keyword">use</span> <span class="pragma">warnings</span><span class="structure">;</span><br /><br /><span class="keyword">use</span> <span class="word">Moose</span><span class="structure">;</span><br /><span class="keyword">use</span> <span class="word">MooseX::Storage</span><span class="structure">;</span><br /><br /><span class="word">with</span> <span class="word">Storage</span><span class="structure">(</span> <span class="word">format</span> <span class="operator">=></span> <span class="single">'JSON'</span><span class="operator">,</span> <span class="word">io</span> <span class="operator">=></span> <span class="single">'GitStore'</span><span class="structure">);</span><br /><br /><span class="word">has</span> <span class="word">name</span> <span class="operator">=></span> <span class="structure">(</span><br /> <span class="word">isa</span> <span class="operator">=></span> <span class="single">'Str'</span><span class="operator">,</span><br /> <span class="word">is</span> <span class="operator">=></span> <span class="single">'ro'</span><span class="operator">,</span><br /> <span class="word">required</span> <span class="operator">=></span> <span class="number">1</span><span class="operator">,</span><br /><span class="structure">);</span><br /><br /><span class="word">has</span> <span class="word">quantity</span> <span class="operator">=></span> <span class="structure">(</span><br /> <span class="word">traits</span> <span class="operator">=></span> <span class="structure">[</span> <span class="single">'Counter'</span> <span class="structure">]</span><span class="operator">,</span><br /> <span class="word">isa</span> <span class="operator">=></span> <span class="single">'Int'</span><span class="operator">,</span><br /> <span class="word">is</span> <span class="operator">=></span> <span class="single">'rw'</span><span class="operator">,</span><br /> <span class="word">default</span> <span class="operator">=></span> <span class="number">0</span><span class="operator">,</span><br /> <span class="word">handles</span> <span class="operator">=></span> <span class="structure">{</span> <span class="word">built</span> <span class="operator">=></span> <span class="single">'inc'</span> <span class="structure">}</span><span class="operator">,</span><br /><span class="structure">);</span><br /><br /><span class="word">has</span> <span class="word">wishlist</span> <span class="operator">=></span> <span class="structure">(</span><br /> <span class="word">traits</span> <span class="operator">=></span> <span class="structure">[</span> <span class="single">'Array'</span> <span class="structure">]</span><span class="operator">,</span><br /> <span class="word">isa</span> <span class="operator">=></span> <span class="single">'ArrayRef[Str]'</span><span class="operator">,</span><br /> <span class="word">default</span> <span class="operator">=></span> <span class="keyword">sub</span> <span class="structure">{</span> <span class="structure">[]</span> <span class="structure">}</span><span class="operator">,</span><br /> <span class="word">handles</span> <span class="operator">=></span> <span class="structure">{</span><br /> <span class="word">add_wishlist</span> <span class="operator">=></span> <span class="single">'push'</span><span class="operator">,</span><br /> <span class="word">all_children</span> <span class="operator">=></span> <span class="single">'elements'</span><span class="operator">,</span><br /> <span class="word">nbr_children</span> <span class="operator">=></span> <span class="single">'count'</span><span class="operator">,</span><br /> <span class="structure">}</span><span class="operator">,</span><br /><span class="structure">);</span><br /><br /><span class="keyword">sub</span> <span class="word">status</span> <span class="structure">{</span><br /> <span class="keyword">my</span> <span class="symbol">$self</span> <span class="operator">=</span> <span class="core">shift</span><span class="structure">;</span><br /><br /> <span class="word">print</span> <span class="symbol">$self</span><span class="operator">-></span><span class="word">name</span><span class="operator">,</span> <span class="double">": "</span><span class="structure">;</span><br /><br /> <span class="keyword">my</span> <span class="symbol">$surplus</span> <span class="operator">=</span> <span class="symbol">$self</span><span class="operator">-></span><span class="word">quantity</span> <span class="operator">-</span> <span class="symbol">$self</span><span class="operator">-></span><span class="word">nbr_children</span><span class="structure">;</span><br /><br /> <span class="keyword">if</span> <span class="structure">(</span> <span class="symbol">$surplus</span> <span class="operator">>=</span> <span class="number">0</span> <span class="structure">)</span> <span class="structure">{</span><br /> <span class="word">print</span> <span class="double">"all is good, surplus of $surplus toys.\n"</span><br /> <span class="structure">}</span><br /> <span class="keyword">else</span> <span class="structure">{</span><br /> <span class="symbol">$surplus</span> <span class="operator">*=</span> <span class="number">-1</span><span class="structure">;</span><br /> <span class="word">print</span> <span class="double">"ALERT, $surplus children in danger to be disappointed\n"</span><span class="structure">;</span><br /> <span class="structure">}</span><br /><span class="structure">}</span><br /><br /><span class="comment"># always save before going out of context<br /></span><span class="keyword">sub</span> <span class="word">DEMOLISH</span> <span class="structure">{</span> <span class="magic">$_</span><span class="structure">[</span><span class="number">0</span><span class="structure">]</span><span class="operator">-></span><span class="word">store</span><span class="structure">(</span> <span class="magic">$_</span><span class="structure">[</span><span class="number">0</span><span class="structure">]</span><span class="operator">-></span><span class="word">name</span> <span class="structure">)</span> <span class="structure">}</span><br /><br /><span class="number">1</span><span class="structure">;</span></code></pre>
<p>Once this was done, he created an empty git repository in <i>~ttal/toystore</i>, and asked the department team lead to fill it with the trendy toys of this year:</p>
<pre><code class="code-listing"><span class="keyword">use</span> <span class="word">Toy</span><span class="structure">;</span><br /><br /><span class="keyword">my</span> <span class="symbol">$toystore</span> <span class="operator">=</span> <span class="single">'/users/ttal/toystore'</span><span class="structure">;</span><br /><br /><span class="word">Toy</span><span class="operator">-></span><span class="word">new</span><span class="structure">(</span> <span class="word">name</span> <span class="operator">=></span> <span class="magic">$_</span><span class="operator">,</span> <span class="word">git_repo</span> <span class="operator">=></span> <span class="symbol">$toystore</span> <span class="structure">)</span> <span class="word">for</span> <span class="words">qw/<br /> my_pretty_platypus<br /> heckle_me_groucho<br /> star_peace_inaction_figure<br />/</span><span class="structure">;</span></code></pre>
<p>With the toys created, the rest of the department could now get busy. Half the elves would update the inventory, and the other half would keep track of which children requested those particular toys. All of this done by a fairly complex process, but fortunately using a very simple API to the store:</p>
<pre><code class="code-listing"><span class="comment"># increase the inventories<br /></span><span class="word">Toy</span><span class="operator">-></span><span class="word">load</span><span class="structure">(</span> <span class="single">'my_pretty_platypus'</span><span class="operator">,</span> <span class="word">git_repo</span> <span class="operator">=></span> <span class="symbol">$toystore</span> <span class="structure">)</span><span class="operator">-></span><span class="word">built</span><span class="structure">(</span><span class="number">2</span><span class="structure">);</span><br /><span class="word">Toy</span><span class="operator">-></span><span class="word">load</span><span class="structure">(</span> <span class="single">'heckle_me_groucho'</span><span class="operator">,</span> <span class="word">git_repo</span> <span class="operator">=></span> <span class="symbol">$toystore</span> <span class="structure">)</span><span class="operator">-></span><span class="word">built</span><span class="structure">(</span><span class="number">3</span><span class="structure">);</span><br /><span class="word">Toy</span><span class="operator">-></span><span class="word">load</span><span class="structure">(</span> <span class="single">'star_peace_inaction_figure'</span><span class="operator">,</span> <br /> <span class="word">git_repo</span> <span class="operator">=></span> <span class="symbol">$toystore</span> <span class="structure">)</span><span class="operator">-></span><span class="word">built</span><span class="structure">(</span><span class="number">1</span><span class="structure">);</span><br /><br /><span class="comment"># update the wishlists<br /></span><span class="word">Toy</span><span class="operator">-></span><span class="word">load</span><span class="structure">(</span> <span class="single">'my_pretty_platypus'</span><span class="operator">,</span> <span class="word">git_repo</span> <span class="operator">=></span> <span class="symbol">$toystore</span><span class="structure">)</span><br /> <span class="operator">-></span><span class="word">add_wishlist</span><span class="structure">(</span><span class="single">'rjbs'</span><span class="operator">,</span> <span class="single">'toby'</span><span class="operator">,</span> <span class="single">'yanick'</span><span class="structure">);</span><br /><span class="word">Toy</span><span class="operator">-></span><span class="word">load</span><span class="structure">(</span> <span class="single">'heckle_me_groucho'</span><span class="operator">,</span> <span class="word">git_repo</span> <span class="operator">=></span> <span class="symbol">$toystore</span> <span class="structure">)</span><br /> <span class="operator">-></span><span class="word">add_wishlist</span><span class="structure">(</span><span class="single">'arthur'</span><span class="structure">);</span><br /><span class="word">Toy</span><span class="operator">-></span><span class="word">load</span><span class="structure">(</span> <span class="single">'star_peace_inaction_figure'</span><span class="operator">,</span> <span class="word">git_repo</span> <span class="operator">=></span> <span class="symbol">$toystore</span><span class="structure">)</span><br /> <span class="operator">-></span><span class="word">add_wishlist</span><span class="structure">(</span><span class="single">'david'</span><span class="structure">);</span></code></pre>
<p>With that very simple system, Glugg had the audit feature requested by the bosses. Not in a super dainty way, mind you, but serviceable:</p>
<pre><code class="code-listing">$ git log my_pretty_platypus <br /><span class="synStatement">commit 3a89e96455f5704fd58b8ed786374998a1533d5d</span><br /><span class="synError">Author: anonymous <anon@127.0.0.1></span><br />Date: Sun Dec 8 20:52:58 2013 +0000<br /><br /><span class="synType">diff --git a/my_pretty_platypus b/my_pretty_platypus</span><br /><span class="synPreProc">index 111111..222222 100644</span><br /><span class="synType">--- a/my_pretty_platypus</span><br /><span class="synType">+++ b/my_pretty_platypus</span><br /><span class="synStatement">@@ -1 +1 @@</span><br /><span class="synSpecial">-{"__CLASS__":"Toy","quantity":2,"name":"my_pretty_platypus","wishlist":[]}</span><br /><span class="synIdentifier">+{"__CLASS__":"Toy","quantity":2,"name":"my_pretty_platypus","wishlist":["rjbs","toby","yanick"]}</span><br /><br />commit a3caacde128a24a79898dabd0afcbf4556f021b0<br />Author: anonymous <anon@127.0.0.1><br />Date: Sun Dec 8 20:52:58 2013 +0000<br /><br /><span class="synType">diff --git a/my_pretty_platypus b/my_pretty_platypus</span><br /><span class="synPreProc">index 222222..333333 100644</span><br /><span class="synType">--- a/my_pretty_platypus</span><br /><span class="synType">+++ b/my_pretty_platypus</span><br /><span class="synStatement">@@ -1 +1 @@</span><br /><span class="synSpecial">-{"__CLASS__":"Toy","quantity":0,"name":"my_pretty_platypus","wishlist":[]}</span><br /><span class="synIdentifier">+{"__CLASS__":"Toy","quantity":2,"name":"my_pretty_platypus","wishlist":[]}</span><br /><br />commit abc3f329823980464f67126b7e0afaeaeffe2101<br />Author: anonymous <anon@127.0.0.1><br />Date: Sun Dec 8 20:52:58 2013 +0000<br /><br /><span class="synType">diff --git a/my_pretty_platypus b/my_pretty_platypus</span><br /><span class="synPreProc">index 333333..444444 100644</span><br /><span class="synType">--- a/my_pretty_platypus</span><br /><span class="synType">+++ b/my_pretty_platypus</span><br /><span class="synStatement">@@ -0,0 +1 @@</span><br /><span class="synIdentifier">+{"__CLASS__":"Toy","quantity":0,"name":"my_pretty_platypus","wishlist":[]}</span></code></pre>
<p>And while the store was, of course, easily accessible via scripts to generate reports and whatnots:</p>
<pre><code class="code-listing"><span class="keyword">use</span> <span class="word">GitStore</span><span class="structure">;</span><br /><br /><span class="keyword">my</span> <span class="symbol">$gitstore</span> <span class="operator">=</span> <span class="word">GitStore</span><span class="operator">-></span><span class="word">new</span><span class="structure">(</span><span class="symbol">$toystore</span><span class="structure">);</span><br /><br /><span class="keyword">for</span> <span class="keyword">my</span> <span class="symbol">$toy</span> <span class="structure">(</span> <span class="symbol">$gitstore</span><span class="operator">-></span><span class="word">list</span> <span class="structure">)</span> <span class="structure">{</span><br /> <span class="word">Toy</span><span class="operator">-></span><span class="word">load</span><span class="structure">(</span> <span class="symbol">$toy</span><span class="operator">,</span> <span class="word">git_repo</span> <span class="operator">=></span> <span class="symbol">$toystore</span> <span class="structure">)</span><span class="operator">-></span><span class="word">status</span><span class="structure">;</span><br /><span class="structure">}</span><br /><br /><span class="separator">__END__</span><br /><span class="end">will print:<br /><br />heckle_me_groucho: all is good, surplus of 2 toys.<br />my_pretty_platypus: ALERT, 1 children in danger to be disappointed<br />star_peace_inaction_figure: all is good, surplus of 0 toys.</span></code></pre>
<p>It was also easily mungeable via other means. For example, some IT elves partial to the <i>fish</i> shell and to <a href="https://metacpan.org/module/App::jt">App::jt</a> got in the habit of getting the current toy tallies via:</p>
<pre><code class="code-listing">$ cd ~ttal/toystore<br />$ for toy in *; cat $toy | jt --fields name,quantity; end;<br /><span class="synIdentifier">{</span><br /><span class="synConstant">"quantity"</span> : 3,<br /><span class="synConstant">"name"</span> : <span class="synConstant">"heckle_me_groucho"</span><br /><span class="synIdentifier">}</span><br /><span class="synIdentifier">{</span><br /><span class="synConstant">"quantity"</span> : 2,<br /><span class="synConstant">"name"</span> : <span class="synConstant">"my_pretty_platypus"</span><br /><span class="synIdentifier">}</span><br /><span class="synIdentifier">{</span><br /><span class="synConstant">"quantity"</span> : 1,<br /><span class="synConstant">"name"</span> : <span class="synConstant">"star_peace_inaction_figure"</span><br /><span class="synIdentifier">}</span></code></pre>
<p>All in all, Glugg was pretty smug about his system. And with the TTAL department happily churning away, he was able to return to his pet project — a skunkwork initiative aimed at leveraging Big Data technologies in a fashion that would revolutionalize the way the North Pole was processing children. But this story, dear boys and dear girls, is a story for another night...</p>
<h2 id="See-Also">See Also</h2>
<ul>
<li><p><a href="https://metacpan.org/module/GitStore">GitStore</a></p>
</li>
<li><p><a href="https://metacpan.org/module/MooseX::Storage">MooseX::Storage</a></p>
</li>
<li><p><a href="https://metacpan.org/module/App::jt">App::jt</a></p>
</li>
</ul>
</div>2013-12-11T00:00:00ZYanick ChampouxGive the gift of dependency clarityhttp://perladvent.org/2013/2013-12-10.html<div class='pod'><h2 id="Oh-no-This-gist-does-what-I-need-but-it-wont-run">Oh no! This gist does what I need, but it won't run!</h2>
<p>How many times have you turned to your favorite search engine and found a code snippet that implements a solution to a problem, but it's not at all clear what dependencies are embedded in the code snippet?</p>
<p>Now this Advent, you can give the gift of clear dependencies to your users.</p>
<h2 id="Introducing-CPANfile">Introducing CPANfile</h2>
<p>A few years ago Tatsuhiko Miyagawa wrote a specification for perl projects based on the Ruby gemfile format. This specification is called <a href="https://metacpan.org/pod/release/MIYAGAWA/Module-CPANfile-1.0002/lib/cpanfile.pod">CPANfile</a> and it is not as well known as it ought to be.</p>
<h2 id="Why-CPANfile-is-super-cool">Why CPANfile is super cool</h2>
<ol>
<li><p>Makes dependency requirements explicit</p>
<p>Using a tool like <a href="https://metacpan.org/pod/Carton">carton</a> you can quickly and easily "freeze" the module dependencies for your project into a local folder, and then push the frozen deps along with the application code to your version control system and somewhere else checkout the same repo with the necessary dependencies already bundled in.</p>
<p>This is very useful in an environment where you want to pin some dependencies indefinitely — or if you want some environments (dev) where you have more control over dependencies to use one set of modules and another (prod) to use whatever's already agreed upon for that environment.</p>
</li>
<li><p>Makes experimenting with perl code from GitHub easy</p>
<p>Recent versions of <a href="https://metacpan.org/pod/release/MIYAGAWA/App-cpanminus-1.7001/bin/cpanm">cpanm</a> support parsing and installing the dependencies given in a CPANfile format. That makes cloning the code found in a gist and installing its dependencies a snap, instead of guessing at a dependency chain.</p>
</li>
<li><p>Sometimes code isn't worth the time to "CPAN-ize"</p>
<p>If you've written some scripts to help you get stuff done, and they're somewhat specific to your task at hand, it might not be worth the time effort to write tests, good docs or package something for release to CPAN.</p>
<p>In those situations, you should still share the code (it will eventually get indexed by some search engine) but you can include a CPANfile to make some future user (maybe even yourself) completely understand the dependencies for a given project.</p>
</li>
</ol>
<h2 id="Yeah-but-isnt-it-hard">Yeah, but isn't it hard?</h2>
<p>Not at all. If you're used to writing MakeMaker-style build scripts, learning CPANfile is a snap. Here's a sample CPANfile from a recent code project I did which converted WordPress style XML exports into Markdown formatted flatfiles. It's called <code><a href="https://github.com/mrallen1/wp2md">wp2md</a></code>.</p>
<pre><code class="code-listing"><span class="word">requires</span> <span class="single">'perl'</span><span class="operator">,</span> <span class="single">'5.014'</span><span class="structure">;</span><br /><br /><span class="word">requires</span> <span class="single">'Path::Tiny'</span><span class="structure">;</span><br /><span class="word">requires</span> <span class="single">'HTML::FormatMarkdown'</span><span class="structure">;</span><br /><span class="word">requires</span> <span class="single">'XML::Feed'</span><span class="structure">;</span><br /><span class="word">requires</span> <span class="single">'TOML'</span><span class="structure">;</span></code></pre>
<p>Notice the only specific version that's called out is the version of perl itself. Since I didn't use any explicit operators, these all mean the same as if you'd put them into MakeMaker as a <code>0</code> version dependency — which is to say, the latest version available unless you have a version installed locally.</p>
<p>A more complicated example would be something like:</p>
<pre><code class="code-listing"><span class="word">requires</span> <span class="single">'Catalyst'</span><span class="operator">,</span> <span class="single">'5.8000'</span><span class="structure">;</span> <span class="comment"># 5.8000 or newer</span><br /><span class="word">requires</span> <span class="single">'Catalyst::View::JSON'</span><span class="operator">,</span> <span class="single">'>= 0.30, < 0.40'</span><span class="structure">;</span><br /><br /><span class="word">recommends</span> <span class="single">'JSON::XS'</span><span class="operator">,</span> <span class="single">'2.0'</span><span class="structure">;</span><br /><span class="word">conflicts</span> <span class="single">'JSON'</span><span class="operator">,</span> <span class="single">'< 1.0'</span><span class="structure">;</span><br /><br /><span class="word">on</span> <span class="single">'test'</span> <span class="operator">=></span> <span class="keyword">sub</span> <span class="structure">{</span><br /> <span class="word">requires</span> <span class="single">'Test::More'</span><span class="operator">,</span> <span class="single">'>= 0.96, < 2.0'</span><span class="structure">;</span><br /> <span class="word">recommends</span> <span class="single">'Test::TCP'</span><span class="operator">,</span> <span class="single">'1.12'</span><span class="structure">;</span><br /><span class="structure">};</span><br /><br /><span class="word">on</span> <span class="single">'develop'</span> <span class="operator">=></span> <span class="keyword">sub</span> <span class="structure">{</span><br /> <span class="word">recommends</span> <span class="single">'Devel::NYTProf'</span><span class="structure">;</span><br /><span class="structure">};</span><br /><br /><span class="word">feature</span> <span class="single">'sqlite'</span><span class="operator">,</span> <span class="single">'SQLite support'</span> <span class="operator">=></span> <span class="keyword">sub</span> <span class="structure">{</span><br /> <span class="word">recommends</span> <span class="single">'DBD::SQLite'</span><span class="structure">;</span><br /><span class="structure">};</span></code></pre>
<p>And there you have it — some simple keywords like <code>requires</code>, <code>recommends</code>, <code>conflicts</code>, and <code>on</code>. The version operators do what it says on the tin like the keywords. You can see how in this line</p>
<pre><code class="code-listing"><span class="word">requires</span> <span class="single">'Test::More'</span><span class="operator">,</span> <span class="single">'>= 0.96, < 2.0'</span><span class="structure">;</span></code></pre>
<p>they can even be combined into an AND evaluation.</p>
<h2 id="See-Also">See Also</h2>
<ul>
<li><p><a href="https://speakerdeck.com/miyagawa/cpanfile">CPANfile presentation from LPW 2011</a></p>
</li>
<li><p><a href="https://metacpan.org/module/cpanm">cpanm</a></p>
</li>
<li><p><a href="https://metacpan.org/module/carton">carton</a></p>
</li>
</ul>
</div>2013-12-10T00:00:00ZMark AllenLocalize Your Perl Apps with this One Weird Trickhttp://perladvent.org/2013/2013-12-09.html<div class='pod'><p>These days, <a href="http://en.wikipedia.org/wiki/Gettext">gettext</a> is far and away the most widely-used localization (<a href="http://en.wikipedia.org/wiki/Language_localisation">l10n</a>) and internationalization (<a href="http://en.wikipedia.org/wiki/Internationalization_and_localization">i18n</a>) library for open-source software. So far, it has not been widely used in the Perl community, even though it's the most flexible, capable, and easy-to use solution, thanks to <a href="https://metacpan.org/module/Locale::TextDomain">Locale::TextDomain</a>¹. How easy? Let's get started!</p>
<h2 id="Module-Internationale">Module Internationale</h2>
<p>First, just <i>use</i> Locale::TextDomain. Say you're creating an awesome new module, Awesome::Module. These CPAN distribution will be named <code>Awesome-Module</code>, so that's the "domain" to use for its localizations. Just let Locale::TextDomain know:</p>
<pre><code class="code-listing"><span class="keyword">use</span> <span class="word">Locale::TextDomain</span> <span class="single">'Awesome-Module'</span><span class="structure">;</span></code></pre>
<p>Locale::TextDomain will later use this string to look for the appropriate translation catalogs. But don't worry about that just yet. Instead, start using it to translate user-visible strings in your code. With the assistance of the Locale::TextDomain's <a href="https://metacpan.org/pod/Locale::TextDomain#EXPORTED-FUNCTIONS">comprehensive documentation</a>, you'll find it second nature to internationalize your modules in no time. For example, simple strings are denoted with <code>__</code>:</p>
<pre><code class="code-listing"><span class="word">say</span> <span class="word">__</span> <span class="single">'Greetings puny human!'</span><span class="structure">;</span></code></pre>
<p>If you need to specify variables, use <code>__x</code>:</p>
<pre><code class="code-listing"><span class="word">say</span> <span class="word">__x</span><span class="structure">(</span><br /> <span class="single">'Thank you {sir}, may I have another?'</span><span class="operator">,</span><br /> <span class="word">sir</span> <span class="operator">=></span> <span class="symbol">$username</span><span class="operator">,</span><br /><span class="structure">);</span></code></pre>
<p>Need to manage plurals? Use <code>__n</code>:</p>
<pre><code class="code-listing"><span class="word">say</span> <span class="word">__n</span><span class="structure">(</span><br /> <span class="single">'I will not buy this record, it is scratched.'</span><span class="operator">,</span><br /> <span class="single">'I will not buy these records, they are scratched.'</span><span class="operator">,</span><br /> <span class="symbol">$num_records</span><br /><span class="structure">);</span></code></pre>
<p>If <code>$num_records</code> is 1, the first phrase will be used. Otherwise the second.</p>
<p>Sometimes you gotta do both, mix variables and plurals. <code>__nx</code> has got you covered there:</p>
<pre><code class="code-listing"><span class="word">say</span> <span class="word">__nx</span><span class="structure">(</span><br /> <span class="single">'One item has been grokked.'</span><span class="operator">,</span><br /> <span class="single">'{count} items have been grokked.'</span><span class="operator">,</span><br /> <span class="symbol">$num_items</span><span class="operator">,</span><br /> <span class="word">count</span> <span class="operator">=></span> <span class="symbol">$num_items</span><span class="operator">,</span><br /><span class="structure">);</span></code></pre>
<p>Congratulations! Your module is now internationalized. Wasn't that easy? Make a habit of using these functions in all the modules in your distribution, always with the <code>Awesome-Module</code> domain, and you'll be set.</p>
<h2 id="Encode-da-Code">Encode da Code</h2>
<p>Locale::TextDomain is great, but it dates from a time when Perl character encoding was, shall we say, sub-optimal. It therefore took it upon itself to try to do the right thing, which is to to detect the locale from the runtime environment and automatically encode as appropriate. Which might work okay if all you ever do is print localized messages — and never anything else.</p>
<p>If, on the other hand, you will be manipulating localized strings in your code, or emitting unlocalized text (such as that provided by the user or read from a database), then it's probably best to coerce Locale::TextDomain to return Perl strings, rather than encoded bytes. There's no formal interface for this in Locale::TextDomain, so we have to hack it a bit: set the <code>$OUTPUT_CHARSET</code> environment variable to "UTF-8" and then bind a filter. Don't know what that means? Me neither. Just put this code somewhere in your distribution where it will always run early, before anything gets localized:</p>
<pre><code class="code-listing"><span class="keyword">use</span> <span class="word">Locale::Messages</span> <span class="words">qw(bind_textdomain_filter)</span><span class="structure">;</span><br /><span class="keyword">use</span> <span class="word">Encode</span><span class="structure">;</span><br /><span class="keyword">BEGIN</span> <span class="structure">{</span><br /> <span class="symbol">$ENV</span><span class="structure">{</span><span class="word">OUTPUT_CHARSET</span><span class="structure">}</span> <span class="operator">=</span> <span class="single">'UTF-8'</span><span class="structure">;</span><br /> <span class="word">bind_textdomain_filter</span> <span class="single">'Awesome-Module'</span> <span class="operator">=></span> <span class="cast">\</span><span class="symbol">&Encode::decode_utf8</span><span class="structure">;</span><br /><span class="structure">}</span></code></pre>
<p>You only have to do this once per domain. So even if you use Locale::TextDomain with the <code>Awesome-Module</code> domain in a bunch of your modules, the presence of this code in a single early-loading module ensures that strings will always be returned as Perl strings by the localization functions.</p>
<h2 id="Environmental-Safety">Environmental Safety</h2>
<p>So what about output? There's one more bit of boilerplate you'll need to throw in. Or rather, put this into the <code>main</code> package that uses your modules to begin with, such as the command-line script the user invokes to run an application.</p>
<p>First, on the shebang line, follow <a href="http://stackoverflow.com/a/6163129/79202">Tom Christiansen's advice</a> and put <code>-CAS</code> in it (or set the <code>$PERL_UNICODE</code> environment variable to <code>AS</code>). Then use the <a href="https://metacpan.org/pod/POSIX#setlocale">POSIX <code>setlocale</code></a> function to the appropriate locale for the runtime environment. How? Like this:</p>
<pre><code class="code-listing"><span class="comment">#!/usr/bin/perl -CAS<br /></span><span class="keyword">use</span> <span class="version">v5.12</span><span class="structure">;</span><br /><span class="keyword">use</span> <span class="pragma">warnings</span><span class="structure">;</span><br /><span class="keyword">use</span> <span class="pragma">utf8</span><span class="structure">;</span><br /><span class="keyword">use</span> <span class="word">POSIX</span> <span class="words">qw(setlocale)</span><span class="structure">;</span><br /><span class="keyword">BEGIN</span> <span class="structure">{</span><br /> <span class="keyword">if</span> <span class="structure">(</span><span class="magic">$^O</span> <span class="operator">eq</span> <span class="single">'MSWin32'</span><span class="structure">)</span> <span class="structure">{</span><br /> <span class="word">require</span> <span class="word">Win32::Locale</span><span class="structure">;</span><br /> <span class="word">setlocale</span> <span class="word">POSIX::LC_ALL</span><span class="operator">,</span> <span class="word">Win32::Locale::get_locale</span><span class="structure">();</span><br /> <span class="structure">}</span> <span class="keyword">else</span> <span class="structure">{</span><br /> <span class="word">setlocale</span> <span class="word">POSIX::LC_ALL</span><span class="operator">,</span> <span class="single">''</span><span class="structure">;</span><br /> <span class="structure">}</span><br /><span class="structure">}</span><br /><br /><span class="keyword">use</span> <span class="word">Awesome::Module</span><span class="structure">;</span></code></pre>
<p>Locale::TextDomain will notice the locale and select the appropriate translation catalog at runtime.</p>
<h2 id="Is-that-all-there-is">Is that all there is?</h2>
<p>Now what? Well, you could do nothing. Ship your code and those internationalized phrases will be handled just like any other string in your code.</p>
<p>But what's the point of that? The real goal is to get these things translated. There are two parts to that process:</p>
<ol>
<li><p>Parsing the internationalized strings from your modules and creating language-specific translation catalogs, or "<a href="https://www.gnu.org/software/gettext/manual/html_node/PO-Files.html">PO files</a>", for translators to edit. These catalogs should be maintained in your source code repository.</p>
</li>
<li><p>Compiling the PO files into binary files, or "<a href="https://www.gnu.org/software/gettext/manual/html_node/MO-Files.html">MO files</a>", and distributing them with your modules. These files should <i>not</i> be maintained in your source code repository.</p>
</li>
</ol>
<p>Until a year ago, there was no Perl-native way to manage these processes. Locale::TextDomain ships with a <a href="https://metacpan.org/source/GUIDO/libintl-perl-1.23/sample/simplecal/po/Makefile">sample <i>Makefile</i></a> demonstrating the appropriate use of the <a href="https://www.gnu.org/software/gettext/">GNU gettext</a> command-line tools, but that seemed a steep price for a Perl hacker to pay.</p>
<p>A better fit for the Perl hacker's brain, I thought, is Dist::Zilla. So I wrote <a href="https://metacpan.org/module/Dist::Zilla::LocaleTextDomain">Dist::Zilla::LocaleTextDomain</a> to encapsulate the use of the gettext utiltiies. Here's how it works.</p>
<p>First, configuring Dist::Zilla to compile localization catalogs for distribution: add these lines to your <i>dist.ini</i> file:</p>
<pre><code class="code-listing"><span class="synSpecial">[ShareDir]</span><br /><span class="synSpecial">[LocaleTextDomain]</span></code></pre>
<p>There are <a href="https://metacpan.org/pod/Dist::Zilla::Plugin::LocaleTextDomain#Configuration">configuration attributes</a> for the <code>LocaleTextDomain</code> plugin, such as where to find the PO files and where to put the compiled MO files. In case you didn't use your distribution name as your localization domain in your modules, for example:</p>
<pre><code class="code-listing"><span class="keyword">use</span> <span class="word">Locale::TextDomain</span> <span class="single">'com.example.perl-libawesome'</span><span class="structure">;</span></code></pre>
<p>Then you'd set the <code>textdomain</code> attribute so that the <code>LocaleTextDomain</code> plugin can find the translation catalogs:</p>
<pre><code class="code-listing"><span class="synSpecial">[LocaleTextDomain]</span><br /><span class="synType">textdomain</span> =<span class="synConstant"> com.example.perl-libawesome</span></code></pre>
<p>Check out the <a href="https://metacpan.org/pod/Dist::Zilla::Plugin::LocaleTextDomain#Configuration">configuration docs</a> for details on all available attributes.</p>
<p>At this point, the plugin doesn't do much, because there are no translation catalogs yet. You might see this line from <code>dzil build</code>, though:</p>
<pre><code> [LocaleTextDomain] Skipping language compilation: directory po does not exist</code></pre>
<p>Let's give it something to do!</p>
<h2 id="Locale-Motion">Locale Motion</h2>
<p>To add a French translation file, use the <code><a href="https://metacpan.org/module/Dist::Zilla::App::Command::msg_init">msg-init</a></code> command²:</p>
<pre><code> % dzil msg-init fr
Created po/fr.po.</code></pre>
<p>The <code>msg-init</code> command uses the GNU gettext utilities to scan your Perl source code and initialize the French catalog, <code>po/fr.po</code>. This file is now ready for translation! Commit it into your source code repository so your agile-minded French-speaking friends can find it. Use <code>msg-init</code> to create as many language files as you like:</p>
<pre><code> % dzil msg-init de ja.JIS en_US.UTF-8 en_UK.UTF-8
Created po/de.po.
Created po/ja.po.
Created po/en_US.po.
Created po/en_UK.po.</code></pre>
<p>Each language has its on PO file. You can even have region-specific catalogs, such as the <code>en_US</code> and <code>en_UK</code> variants here. Each time a catalog is updated, the changes should be committed to the repository, like code. This allows the latest translations to always be available for compilation and distribution. The output from <code>dzil build</code> now looks something like:</p>
<pre><code> po/fr.po: 10 translated messages, 1 fuzzy translation, 0 untranslated messages.
po/ja.po: 10 translated messages, 1 fuzzy translation, 0 untranslated messages.
po/en_US.po: 10 translated messages, 1 fuzzy translation, 0 untranslated messages.
po/en_UK.po: 10 translated messages, 1 fuzzy translation, 0 untranslated messages.</code></pre>
<p>The resulting MO files will be in the shared directory of your distribution:</p>
<pre><code> % find Awesome-Module-0.01/share -type f
Awesome-Module-0.01/share/LocaleData/de/LC_MESSAGES/Awesome-Module.mo
Awesome-Module-0.01/share/LocaleData/en_UK/LC_MESSAGES/Awesome-Module.mo
Awesome-Module-0.01/share/LocaleData/en_US/LC_MESSAGES/Awesome-Module.mo
Awesome-Module-0.01/share/LocaleData/ja/LC_MESSAGES/Awesome-Module.mo</code></pre>
<p>From here <a href="https://metacpan.org/module/Module::Build">Module::Build</a> or <a href="https://metacpan.org/module/ExtUtils::MakeMaker">ExtUtils::MakeMaker</a> will install these MO files with the rest of your distribution, right where Locale::TextDomain can find them at runtime. The PO files, on the other hand, won't be used at all, so you might as well exclude them from the distribution. Add this line to your <code>MANIFEST.SKIP</code> to prevent the <code>po</code> directory and its contents from being included in the distribution:</p>
<pre><code> ^po/</code></pre>
<h2 id="Mergers-and-Acquisitions">Mergers and Acquisitions</h2>
<p>Of course no code base is static. In all likelihood, you'll change your code — and end up adding, editing, and removing localizable strings as a result. You'll need to periodically merge these changes into all of your translation catalogs so that your translators can make the corresponding updates. That's what the the <code><a href="https://metacpan.org/pod/Dist::Zilla::App::Command::msg_merge">msg-merge</a></code> command is for:</p>
<pre><code> % dzil msg-merge
extracting gettext strings
Merging gettext strings into po/de.po
Merging gettext strings into po/en_UK.po
Merging gettext strings into po/en_US.po
Merging gettext strings into po/ja.po</code></pre>
<p>This command re-scans your Perl code and updates all of the language files. Old messages will be commented-out and new ones added. Commit the changes and give your translators a holler so they can keep the awesome going.</p>
<h2 id="Template-Scan">Template Scan</h2>
<p>The <code>msg-init</code> and <code>msg-merge</code> commands don't actually scan your source code. Sort of lied about that. Sorry. What they actually do is merge a template file into the appropriate catalog files. If this template file does not already exist, a temporary one will be created and discarded when the initialization or merging is done.</p>
<p>But projects commonly maintain a permanent template file, stored in the source code repository along with the translation catalogs. For this purpose, we have the <code>msg-scan</code> command. Use it to create or update the template, or POT file:</p>
<pre><code> % dzil msg-scan
extracting gettext strings into po/Awesome-Module.pot</code></pre>
<p>From here on in, the resulting <code>.pot</code> file will be used by <code>msg-init</code> and <code>msg-merge</code> instead of scanning your code all over again. But keep in mind that, if you do maintain a POT file, future merges will be a two-step process: First run <code>msg-scan</code> to update the POT file, then <code>msg-merge</code> to merge its changes into the PO files:</p>
<pre><code> % dzil msg-scan
extracting gettext strings into po/Awesome-Module.pot
% dzil msg-merge
Merging gettext strings into po/de.po
Merging gettext strings into po/en_UK.po
Merging gettext strings into po/en_US.po
Merging gettext strings into po/ja.po</code></pre>
<h2 id="Lost-in-Translation">Lost in Translation</h2>
<p>One more thing, a note for translators. They can, of course, also use <code>msg-scan</code> and <code>msg-merge</code> to update the catalogs they're working on. But how do they test their translations? Easy: use the <code><a href="https://metacpan.org/pod/Dist::Zilla::App::Command::msg_compile">msg-compile</a></code> command to compile a single catalog:</p>
<pre><code> % dzil msg-compile po/fr.po
[LocaleTextDomain] po/fr.po: 195 translated messages.</code></pre>
<p>The resulting compiled catalog will be saved to the <i>LocaleData</i> subdirectory of the current directory, so it's easily available to your app for testing. Just be sure to tell Perl to include the current directory in the search path, and set the <code>$LANGUAGE</code> environment variable for your language. For example, here's how I test the <a href="http://sqitch.org/">Sqitch</a> French catalog:</p>
<pre><code> % dzil msg-compile po/fr.po
[LocaleTextDomain] po/fr.po: 148 translated messages, 36 fuzzy translations, 27 untranslated messages.
% LANGUAGE=fr perl -Ilib -CAS -I. bin/sqitch foo
"foo" n'est pas une commande valide</code></pre>
<p>Just be sure to delete the <i>LocaleData</i> directory when you're done — or at least don't commit it to the repository.</p>
<h2 id="TL-DR">TL;DR</h2>
<p>This may seem like a lot of steps, and it is. But once you have the basics in place — Configuring the <a href="https://metacpan.org/module/Dist::Zilla::LocaleTextDomain">Dist::Zilla::LocaleTextDomain</a> plugin, setting up the "textdomain filter", setting and the locale in the application — there are just a few habits to get into:</p>
<ul>
<li><p>Use the functions <code>__</code>, <code>__x</code>, <code>__n</code>, and <code>__nx</code> to internationalize user-visible strings</p>
</li>
<li><p>Run <code>msg-scan</code> and <code>msg-merge</code> to keep the catalogs up-to-date</p>
</li>
<li><p>Keep your translators in the loop.</p>
</li>
</ul>
<p>The Dist::Zilla::LocaleTextDomain plugin will do the rest.</p>
<h2 id="Footnotes">Footnotes</h2>
<ul>
<p>1 What about <a href="https://metacpan.org/module/Locale::Maketext">Locale::Maketext</a>, you ask? It has not, alas, withsthood the test of time. For details, see Nikolai Prokoschenko's epic 2009 polemic, "<a href="http://rassie.org/archives/247">On the state of i18n in Perl</a>." See also Steffen Winkler's presentation, <a href="http://download.steffen-winkler.de/dpws2010/I18N_STEFFENW.pod">Internationalisierungs-Framework auswählen</a> (and the <a href="https://gist.github.com/ap/909197">English translation</a> by <a href="http://blogs.perl.org/users/aristotle/2011/04/stop-using-maketext.html">Aristotle Pagaltzis</a>), from <a href="http://conferences.yapceurope.org/gpw2010/">German Perl Workshop 2010</a>.</p>
<p>2 The <code>msg-init</code> function — like all of the <code>dzil msg-*</code> commands — uses the <a href="https://www.gnu.org/software/gettext/">GNU gettext</a> utilities under the hood. You'll need a reasonably modern version in your path, or else it won't work.</p>
</ul>
<h2 id="See-Also">See Also</h2>
<ul>
<li><p><a href="https://metacpan.org/module/Dist::Zilla::LocaleTextDomain">Dist::Zilla::LocaleTextDomain</a></p>
</li>
<li><p><a href="https://metacpan.org/module/Locale::TextDomain">Locale::TextDomain</a></p>
</li>
</ul>
</div>2013-12-09T00:00:00ZDavid WheelerThe PAUSE Permissions Modelhttp://perladvent.org/2013/2013-12-08.html<div class='pod'><p>PAUSE has a permissions model that is defined in terms of <i>modules</i> and not <i>distributions</i>. It controls who can release what modules onto CPAN. Actually, that's not quite true, but it's a good enough approximation to get started with.</p>
<h3 id="Uploading-a-new-module">Uploading a new module</h3>
<p>If you upload a new module to CPAN, you become the <i>owner</i> of that module. From that point forward only you can upload that module, unless you give someone co-maint permissions for your module.</p>
<p>If you upload a new dist that contains multiple new modules, then you're given ownership for each module.</p>
<p>When you upload a dist to PAUSE, you get two emails back. The first tells you whether the dist was successfully uploaded to your author's directory. PAUSE then checks whether you have upload permissions for every module. If you don't, the second email will identify the offending modules, and the dist won't be <i>indexed</i>. <a href="http://search.cpan.org">search.cpan.org</a> flags such uploads as an <b>** UNAUTHORIZED RELEASE **</b>.</p>
<h3 id="perms.txt"><i>06perms.txt</i></h3>
<p>PAUSE holds all information about users, modules, releases, permissions, and more, in a database. Some of this information is dumped into text files by hourly cronjobs; these files are distributed on CPAN.</p>
<p>The permissions data is written to <a href="http://www.cpan.org/modules/06perms.txt">06perms.txt</a>. The body of this file is a CSV, with triples that give module name, PAUSE id, and permission.</p>
<pre><code> % grep Module::Path, 06perms.txt
Module::Path,NEILB,f</code></pre>
<p>The '<b>f</b>' permission ('first come') says that I was the first person to upload the module, so I'm the owner.</p>
<p>I recently took over maintenance of <a href="https://metacpan.org/module/enum">enum</a> from ZENIN, and was granted co-maintenance by the PAUSE admins (with ZENIN's blessing):</p>
<pre><code> % grep ^enum, 06perms.txt
enum,NEILB,c
enum,ZENIN,m</code></pre>
<p>The '<b>m</b>' permission against ZENIN says that he registered it on the module list. Within PAUSE, ZENIN also has the 'f' permission, but 'm' takes precedence, so that's what's listed.</p>
<p><a href="https://metacpan.org/module/PAUSE::Permissions">PAUSE::Permissions</a> gives a simple interface to <code>06perms.txt</code>, letting you iterate over it either line-by-line, or by module.</p>
<h3 id="Co-maint">Co-maint</h3>
<p>If you have co-maint permissions for a module, you can upload a new version onto CPAN, but you can't grant co-maint permissions to anyone else. Only the owner can do that.</p>
<p>In <i>06perms.txt</i>, co-maint is indicated with a 'c'. There are a small number of modules that have both 'm' and 'f' permissions, for different users. As noted above, the 'm' takes precedence, and the user with 'f' is treated as a co-maint.</p>
<h3 id="Deleting-dists">Deleting dists</h3>
<p>You can only delete dists that you uploaded. Even if you're the owner, you can't delete dists uploaded by someone with co-maint permission(s) (remember: the permissions model relates to modules, not dists).</p>
<p>If you upload a dist containing one new module, and later delete the dist (via PAUSE), then the module won't exist on CPAN, but you'll have an 'f' permission, and no-one will be able to use that namespace. This can be an issue if you refactor a dist, and change some class names.</p>
<p>You can release the permissions via the PAUSE web interface ("Change Permissions"), either by transferring them to another PAUSE user, or relinquishing them, which means anyone could then use that module name.</p>
<h3 id="Watch-out-for-inconsistent-permissions">Watch out for inconsistent permissions</h3>
<p>Let's say you upload a dist containing a number of modules. You'll be owner ('f' permission) for all modules. Later, you grant co-maint permissions to a couple of friends, giving them 'c' permissions for all modules. You take it in turns to do releases, using a shared GitHub repo.</p>
<p>If one of your friends adds a new module, (s)he will be given ownership of that module ('f'irst come), and the rest of you won't have permissions. If you subsequently try to release a version of the dist, it will fail the indexing stage, because you don't have permission for one of the modules in the dist. When someone adds a new class, they need to remember to give co-maint permissions to everyone else (using the PAUSE web interface).</p>
<h3 id="Check-your-dists">Check your dists!</h3>
<p>If you install <a href="https://metacpan.org/module/App::PAUSE::CheckPerms">App::PAUSE::CheckPerms</a>, you'll get a script which will check the permissions consistency of all your dists. For example, if you run:</p>
<pre><code> % pause-checkperms --user DOY</code></pre>
<p>you'll see a number of dists listed, including:</p>
<pre><code> Resource-Pack
Resource::Pack | doy STEVAN
Resource::Pack::Dir | doy STEVAN
Resource::Pack::File | doy STEVAN
Resource::Pack::FromFile | DOY
Resource::Pack::Installable | DOY
Resource::Pack::Resource | DOY
Resource::Pack::URL | doy STEVAN</code></pre>
<p>The owner of a module is indicated by an UPPER CASE pause id. A lower-case pause id signifies co-maint. In this example, STEVAN couldn't release the dist, and neither DOY nor STEVAN could grant co-maint to a third party on their own.</p>
<p>The <a href="https://metacpan.org/module/comaint">comaint</a> script that comes with <a href="https://metacpan.org/module/App::PAUSE::Comaint">App::PAUSE::Comaint</a> can be used to give co-maint permissions on the command-line.</p>
<h2 id="See-Also">See Also</h2>
<ul>
<li><p><a href="https://metacpan.org/module/App::PAUSE::CheckPerms">App::PAUSE::CheckPerms</a></p>
</li>
<li><p><a href="https://github.com/andk/pause">the PAUSE source code</a></p>
</li>
<li><p><a href="https://metacpan.org/module/App::PAUSE::Comaint">App::PAUSE::Comaint</a></p>
</li>
</ul>
</div>2013-12-08T00:00:00ZNeil BowersWeb done better!http://perladvent.org/2013/2013-12-07.html<div class='pod'><h2 id="Remembering-the-horror">Remembering the horror</h2>
<p>If you've done any web programming in Perl for more than a few years, you probably know how difficult and annoying server-side web programming can be. If you're new, just hold on to your hat for a few minutes.</p>
<h2 id="So-you-want-to-write-a-server-side-web-application">So you want to write a server-side web application?</h2>
<p>Welcome! How would you like to write your web application? Do you want to use <a href="https://metacpan.org/module/CGI">CGI.pm</a>, <b>mod_perl</b>, <a href="https://metacpan.org/module/FCGI">FCGI</a>, <a href="https://metacpan.org/module/Catalyst">Catalyst</a>, <a href="https://metacpan.org/module/Jifty">Jifty</a>? Maybe you want to write it yourself manually? Each form means a different output. Each server (Apache, Lighttpd, Nginx, etc.) supports some technologies but not others, and requires data in a different format.</p>
<p>You're probably beginning to see the problem. In web programming you're basically marrying yourself to a specific server environment. Beyond that, each framework usually settles on a specific server environment protocol, whether it is CGI or mod_perl. Then, if the web server doesn't work, or if you want to move to a different protocol, your web application needs rewriting. Yay! Oh wait, no. That sucks.</p>
<h2 id="Great-artists-are-inspired">Great artists are inspired</h2>
<p>Picasso said that <i>good artists copy, great artists steal</i>, but a better paraphrase might be that great artists <i>are inspired</i>. As such, Perl superhero Tatsuhiko Miyagawa was inspired by specifications available in other languages (Ruby's <a href="http://rack.github.com/">Rack</a>, Python's <a href="http://wsgi.readthedocs.org/en/latest/">WSGI</a>) that provide an interface layer between different server environment protocols. He created Perl's <a href="https://metacpan.org/module/PSGI">PSGI</a>.</p>
<p>PSGI finally provides a clear specification for interfacing with different layers. This effectively separates between the web application, the interface (<a href="https://metacpan.org/module/HTTP::Engine">HTTP::Engine</a>, CGI, FCGI), and the web server (Apache, Nginx, <a href="https://metacpan.org/module/HTTP::Server::Simple">HTTP::Server::Simple</a>), which up until now were mashed together like a an awful software train wreck.</p>
<p>Do you want to write your application in <a href="https://metacpan.org/module/Catalyst">Catalyst</a>? Maybe in <a href="https://metacpan.org/module/Web::Simple">Web::Simple</a>? As long as they support the PSGI protocol, you can do that. Now you can deploy them on any web server, use any technology (whether it's CGI, FastCGI, or anything else), and even run them on Perl-based web servers as a backend to a reverse-proxy server (Nginx, Apache + mod_proxy, and so on).</p>
<p>PSGI comes with a reference implementation called <a href="https://metacpan.org/module/Plack">Plack</a>, which includes a range of utilities, and implementations for servers (under the Plack::Server namespace).</p>
<h2 id="Welcome-to-a-Modern-Perl-web">Welcome to a Modern Perl web</h2>
<p>All modern Perl web frameworks now support the PSGI protocol (<a href="https://metacpan.org/module/Catalyst">Catalyst</a>, <a href="https://metacpan.org/module/Dancer">Dancer</a>, <a href="https://metacpan.org/module/Web::Simple">Web::Simple</a>, <a href="https://metacpan.org/module/Mojolicious">Mojolicious</a>, <a href="https://metacpan.org/module/Mason">Mason</a>, <a href="https://metacpan.org/module/OX">OX</a>, <a href="https://metacpan.org/module/Tatsumaki">Tatsumaki</a>, and more), and you can deploy on any web server, including Perl web servers (<a href="https://metacpan.org/module/Starman">Starman</a>, <a href="https://metacpan.org/module/Starlet">Starlet</a>, <a href="https://metacpan.org/module/Twiggy">Twiggy</a>, <a href="https://metacpan.org/module/Corona">Corona</a>).</p>
<p>PSGI also specifies different layers of action called <i>middleware</i>, allowing you to add blocks on top of your web application providing a range of services, such as caching, privacy and authorization control, REPL, debugging screens, session management and more.</p>
<h2 id="Words-are-Cheap">Words are Cheap</h2>
<p>To anyone with an appetite for understanding, this is probably not enough. Seeing is believing, isn't it? What does a PSGI app really look like?</p>
<p>In essence, a PSGI application is just a code reference:</p>
<pre><code class="code-listing"><span class="keyword">my</span> <span class="symbol">$app</span> <span class="operator">=</span> <span class="keyword">sub</span> <span class="structure">{</span><br /><span class="comment"> # your application<br /></span><span class="structure">};</span></code></pre>
<p>That reference is then sent to the server. For every new HTTP request, the server will call the code reference and send it the environment variables of the request in a hash structure, conventionally called <code>$env</code>.</p>
<pre><code class="code-listing"><span class="symbol">$env</span> <span class="operator">=</span> <span class="structure">{</span><br /> <span class="word">HTTP_ACCEPT</span> <span class="operator">=></span> <span class="double">"*/*"</span><span class="operator">,</span><br /> <span class="word">HTTP_HOST</span> <span class="operator">=></span> <span class="double">"localhost:5000"</span><span class="operator">,</span><br /> <span class="word">HTTP_USER_AGENT</span> <span class="operator">=></span> <span class="double">"curl/7.27.0"</span><span class="operator">,</span><br /> <span class="word">PATH_INFO</span> <span class="operator">=></span> <span class="double">"/"</span><span class="operator">,</span><br /> <span class="word">psgi</span><span class="operator">.</span><span class="word">errors</span> <span class="operator">=></span> <span class="symbol">*main::STDERR</span><span class="operator">,</span><br /> <span class="word">psgi</span><span class="operator">.</span><span class="word">input</span> <span class="operator">=></span> <span class="symbol">*HTTP::Server::PSGI::input</span><span class="operator">,</span><br /> <span class="word">psgi</span><span class="operator">.</span><span class="word">multiprocess</span> <span class="operator">=></span> <span class="double">""</span><span class="operator">,</span><br /> <span class="word">psgi</span><span class="operator">.</span><span class="word">multithread</span> <span class="operator">=></span> <span class="double">""</span><span class="operator">,</span><br /> <span class="word">psgi</span><span class="operator">.</span><span class="word">nonblocking</span> <span class="operator">=></span> <span class="double">""</span><span class="operator">,</span><br /> <span class="word">psgi</span><span class="operator">.</span><span class="word">run_once</span> <span class="operator">=></span> <span class="double">""</span><span class="operator">,</span><br /> <span class="word">psgi</span><span class="operator">.</span><span class="word">streaming</span> <span class="operator">=></span> <span class="number">1</span><span class="operator">,</span><br /> <span class="word">psgi</span><span class="operator">.</span><span class="word">url_scheme</span> <span class="operator">=></span> <span class="double">"http"</span><span class="operator">,</span><br /> <span class="word">psgi</span><span class="operator">.</span><span class="word">version</span> <span class="operator">=></span> <span class="structure">[</span> <span class="number">1</span><span class="operator">,</span> <span class="number">1</span> <span class="structure">]</span><span class="operator">,</span><br /> <span class="word">psgix</span><span class="operator">.</span><span class="word">harakiri</span> <span class="operator">=></span> <span class="number">1</span><span class="operator">,</span><br /> <span class="word">psgix</span><span class="operator">.</span><span class="word">input</span><span class="operator">.</span><span class="word">buffered</span> <span class="operator">=></span> <span class="number">1</span><span class="operator">,</span><br /> <span class="word">psgix</span><span class="operator">.</span><span class="word">io</span> <span class="operator">=></span> <span class="symbol">*Symbol::GEN1</span><span class="operator">,</span><br /> <span class="word">QUERY_STRING</span> <span class="operator">=></span> <span class="double">""</span><span class="operator">,</span><br /> <span class="word">REMOTE_ADDR</span> <span class="operator">=></span> <span class="double">"127.0.0.1"</span><span class="operator">,</span><br /> <span class="word">REMOTE_PORT</span> <span class="operator">=></span> <span class="number">37063</span><span class="operator">,</span><br /> <span class="word">REQUEST_METHOD</span> <span class="operator">=></span> <span class="double">"GET"</span><span class="operator">,</span><br /> <span class="word">REQUEST_URI</span> <span class="operator">=></span> <span class="double">"/"</span><span class="operator">,</span><br /> <span class="word">SCRIPT_NAME</span> <span class="operator">=></span> <span class="double">""</span><span class="operator">,</span><br /> <span class="word">SERVER_NAME</span> <span class="operator">=></span> <span class="number">0</span><span class="operator">,</span><br /> <span class="word">SERVER_PORT</span> <span class="operator">=></span> <span class="number">5000</span><span class="operator">,</span><br /> <span class="word">SERVER_PROTOCOL</span> <span class="operator">=></span> <span class="double">"HTTP/1.1"</span><br /><span class="structure">};</span></code></pre>
<p>You can use this environment hash to understand the request. Alternatively you could use one of the available PSGI-supported web frameworks. They abstract the code that handled these environment variables and allows you to define code paths for your web application.</p>
<p>Next comes the reply. With CGI, you would return two chunks of output to STDOUT: one of headers to the browser, and the other of the actual content.</p>
<p>PSGI needs the same information from you, but in a structured form:</p>
<pre><code class="code-listing"><span class="keyword">my</span> <span class="symbol">$app</span> <span class="operator">=</span> <span class="keyword">sub</span> <span class="structure">{</span><br /> <span class="keyword">my</span> <span class="symbol">$env</span> <span class="operator">=</span> <span class="core">shift</span><span class="structure">;</span><br /> <span class="operator">...</span><br /><br /> <span class="keyword">return</span> <span class="structure">[</span><br /> <span class="single">'200'</span><span class="operator">,</span> <span class="comment"># HTTP code</span><br /> <span class="structure">[</span><br /> <span class="single">'Content-Type'</span> <span class="operator">=></span> <span class="single">'application/json'</span><span class="operator">,</span><br /> <span class="symbol">%additional_header_pairs</span><span class="operator">,</span><br /> <span class="structure">]</span><span class="operator">,</span><br /> <span class="structure">[</span> <span class="symbol">@content_hunks</span> <span class="structure">]</span><span class="operator">,</span><br /> <span class="structure">];</span><br /><span class="structure">};</span></code></pre>
<p>Once the server calls the code reference with the environment, it awaits this reply. It will then use this reply to return the proper data to the user.</p>
<h2 id="And-the-middlewares">And the middlewares?</h2>
<p>Oh right! The middlewares! Since it is all code references, we can wrap them in another code reference. We use <a href="https://metacpan.org/module/Plack::Builder">Plack::Builder</a> for that:</p>
<pre><code class="code-listing"><span class="keyword">use</span> <span class="word">Plack::Builder</span><span class="structure">;</span><br /><span class="keyword">use</span> <span class="word">Plack::Middleware::BufferedStreaming</span><span class="structure">;</span><br /><br /><span class="keyword">my</span> <span class="symbol">$webapp</span> <span class="operator">=</span> <span class="keyword">sub</span> <span class="structure">{</span> <span class="operator">...</span> <span class="structure">};</span><br /><span class="keyword">my</span> <span class="symbol">$app</span> <span class="operator">=</span> <span class="word">builder</span> <span class="structure">{</span><br /> <span class="word">enable</span> <span class="single">'BufferedStreaming'</span><span class="operator">,</span><br /> <span class="symbol">$webapp</span><span class="operator">,</span><br /><span class="structure">};</span></code></pre>
<p>The <code>builder</code> function (from <a href="https://metacpan.org/module/Plack::Builder">Plack::Builder</a>) creates a code references that receives any number of code references and sends the request it receives to each one in turn. This allows us to aggregate more and more <i>PSGI applications</i>. Our web application is a PSGI app, but so is a middleware. when we call <code>enable</code>, it will receive the middleware code reference and register it.</p>
<p>Thus we created a code reference that aggregates multiple code references, providing our software with a layer on top that will add buffering. We can stack more and more middlewares to provide even more features before it even reaches our actual web application code.</p>
<h2 id="The-future-seems-bright">The future seems bright</h2>
<p>Now that we have PSGI and Plack, we can finally program in any web framework we want without worrying about painting ourselves into a corner, limiting ourselves with regards to the web server, the technology, and the platform. No more! The future is open, and web programming is so much better.</p>
<h2 id="See-Also">See Also</h2>
<ul>
<li><p><a href="https://metacpan.org/module/PSGI">PSGI</a></p>
</li>
<li><p><a href="https://metacpan.org/module/Plack">Plack</a></p>
</li>
</ul>
</div>2013-12-07T00:00:00ZSawyer XFind My Santahttp://perladvent.org/2013/2013-12-06.html<div class='pod'><p>From the look on the young elf's face running towords him, the Wise Old Elf knew something had gone terribly terribly wrong.</p>
<p>"It's our worse nightmare, Sir" Private Jingle McCandySticks reported. "We just found a letter for Santa down the back of the Sofa in the mailroom, Sir!".</p>
<p>This was bad news indeed. Santa had already set off on his annual round the world present giving extravaganza, and if no-one had read that letter yet, someone was going to have an empty stocking come Christmas morning.</p>
<p>"That's okay CandySticks", the wise old elf reassured the Private, taking the letter as he did so. "Santa has his iPhone on him, it's freshly charged, so one phone call and we'll be sure that ... let's see here ... little José Castro will get the ninja costume he always wanted."</p>
<p>"But that's just it, Sir. Ever since Lieutenant Pudding Von Snowflake accidentally dialed Santa's cell phone instead of the Pizza place his phone is on strict Do Not Disturb. It won't even ring for Mrs. Claus, Sir!"</p>
<p>"Ah yes," sighed the Wise Old Elf, "well we can't blame him about that. Not after his Rockin' Around The Christmas Tree ringtone woke up those Rottweilers. Still, don't worry, I think I can solve this with a little Perl script..."</p>
<pre><code class="code-listing"><span class="comment"># access Santa's Where's My iPhone account with his iCloud credentials<br /># and get access to his iPhone's details<br /></span><span class="keyword">use</span> <span class="word">WebService::FindMyiPhone</span><span class="structure">;</span><br /><span class="keyword">my</span> <span class="symbol">$icloud</span> <span class="operator">=</span> <span class="word">WebService::FindMyiPhone</span><span class="operator">-></span><span class="word">new</span><span class="structure">(</span><br /> <span class="word">username</span> <span class="operator">=></span> <span class="single">'kriskringle@icloud.com'</span><span class="operator">,</span><br /> <span class="word">password</span> <span class="operator">=></span> <span class="single">'RudyGuideMySleigh2Nite!'</span><span class="operator">,</span><br /><span class="structure">);</span><br /><span class="keyword">my</span> <span class="symbol">$iphone</span> <span class="operator">=</span> <span class="symbol">$icloud</span><span class="operator">-></span><span class="word">get_device_by</span><span class="structure">(</span> <span class="word">name</span> <span class="operator">=></span> <span class="double">"Santa's iPhone"</span> <span class="structure">);</span><br /><br /><span class="comment"># wait for Santa to fly west out of Portugal towards the Americas, so we know<br /># that he's in the air and when we make his phone make noise, and it won't<br /># wake anyone up<br /></span><span class="keyword">while</span> <span class="structure">(</span><span class="number">1</span><span class="structure">)</span> <span class="structure">{</span><br /> <span class="word">last</span> <span class="word">if</span> <span class="symbol">$iphone</span><span class="operator">-></span><span class="word">location</span><span class="operator">-></span><span class="structure">{</span><span class="word">longitude</span><span class="structure">}</span> <span class="operator"><</span> <span class="float">-9.6</span><span class="structure">;</span><br /> <span class="word">sleep</span> <span class="number">60</span> <span class="operator">*</span> <span class="number">5</span><span class="structure">;</span><br /><span class="structure">}</span><br /><br /><span class="comment"># make his phone bleep until he acknowledges the emergency message<br /></span><span class="symbol">$iphone</span><span class="operator">-></span><span class="word">send_message</span><span class="structure">(</span><br /> <span class="number">1</span><span class="operator">,</span> <span class="comment"># true = make noise</span><br /> <span class="double">"Go back, J.Casto (#F8034672F5DC4E4B965A7F0C1D0FD2AC) needs Ninja Costume"</span><span class="operator">,</span><br /><span class="structure">);</span></code></pre>
<h2 id="See-Also">See Also</h2>
<ul>
<li><p><a href="https://metacpan.org/module/WebService::FindMyiPhone">WebService::FindMyiPhone</a></p>
</li>
</ul>
</div>2013-12-06T00:00:00ZMark FowlerPlaying it safe with Safe::Isahttp://perladvent.org/2013/2013-12-05.html<div class='pod'><p>Earlier this year in Manhattan, a garage worker drove an Audi into an open car elevator shaft. The car fell three floors and the worker escaped through the sun roof.</p>
<p>Every year I see stories of people falling in elevator shafts — sometimes dying — when the elevator they are expecting to be there suddenly isn't.</p>
<p>But what do elevator shafts have to do with Perl?</p>
<p>There is a common idiom for checking an object's class that is remarkably like stepping through an elevator door without checking that the elevator is there:</p>
<pre><code class="code-listing"><span class="keyword">if</span> <span class="structure">(</span> <span class="symbol">$thing</span><span class="operator">-></span><span class="word">isa</span><span class="structure">(</span> <span class="double">"Class::I'm::Looking::For"</span> <span class="structure">)</span> <span class="structure">}</span> <span class="structure">{</span><br /><span class="comment"> # do something with $thing<br /></span><span class="structure">}</span></code></pre>
<p>If <code>$thing</code> is an unblessed reference, you've just fallen down the elevator shaft and gotten a fatal error.</p>
<p>If <code>$thing</code> is a scalar, then it's treated like a class name. That might be what you want, but if you really wanted <i>an object</i>, then you're in trouble if you call any object methods on it.</p>
<p>Usually, the <code>isa</code> method comes from the <a href="https://metacpan.org/module/UNIVERSAL">UNIVERSAL</a> class, so maybe you thought (or were taught) to call it as a function:</p>
<pre><code class="code-listing"><span class="keyword">if</span> <span class="structure">(</span> <span class="word">UNIVERSAL::isa</span><span class="structure">(</span> <span class="symbol">$thing</span><span class="operator">,</span> <span class="double">"Class::I'm::Looking::For"</span> <span class="structure">)</span> <span class="structure">}</span> <span class="structure">{</span><br /><span class="comment"> # do something with $thing<br /></span><span class="structure">}</span></code></pre>
<p>That is wrong, too, because <code>isa</code> is supposed to be a <i>method</i>, and you've just skipped the entire <code>@ISA</code> hierarchy. If any class defined its own <code>isa</code> method, you'll get a different answer than what you should. (A <a href="https://en.wikipedia.org/wiki/Mock_object">mock object</a> used in testing might do that, for instance.)</p>
<p>You might have learned to check for an object first, with <a href="https://metacpan.org/module/Scalar::Util">Scalar::Util</a> and <code>blessed</code>:</p>
<pre><code class="code-listing"><span class="keyword">use</span> <span class="word">Scalar::Util</span> <span class="single">'blessed'</span><span class="structure">;</span><br /><br /><span class="keyword">if</span> <span class="structure">(</span> <span class="word">blessed</span><span class="structure">(</span> <span class="symbol">$thing</span> <span class="structure">)</span> <span class="operator">&&</span> <span class="symbol">$thing</span><span class="operator">-></span><span class="word">isa</span><span class="structure">(</span> <span class="double">"Class::I'm::Looking::For"</span> <span class="structure">)</span> <span class="structure">}</span> <span class="structure">{</span><br /><span class="comment"> # do something with $thing<br /></span><span class="structure">}</span></code></pre>
<p>That is mostly correct (someone could have blessed an object into the class "0" for instance), but in any ordinary code, it will do what you want.</p>
<p>Unfortunately, that's a lot to write over and over, as you might if you're using some sort of exception object system like <a href="https://metacpan.org/module/Throwable">Throwable</a> or <a href="https://metacpan.org/module/failures">failures</a> or the venerable <a href="https://metacpan.org/module/Exception::Class">Exception::Class</a>.</p>
<p>For example, imagine you're using <a href="https://metacpan.org/module/failures">failures</a> and you've wrapped some possibly fatal code with <code>try</code> from <a href="https://metacpan.org/module/Try::Tiny">Try::Tiny</a> and you need to test the error to see if it's an object of various types or just a string.</p>
<p>Do you really want to type <code>blessed</code> in every conditional?</p>
<pre><code class="code-listing"><span class="keyword">use</span> <span class="pragma">failures</span> <span class="words">qw/io::file io::network/</span><span class="structure">;</span><br /><span class="keyword">use</span> <span class="word">Try::Tiny</span><span class="structure">;</span><br /><br /><span class="word">try</span> <span class="structure">{</span><br /> <span class="word">something_that_might_fail</span><span class="structure">()</span><br /><span class="structure">}</span><br /><span class="word">catch</span> <span class="structure">{</span><br /> <span class="keyword">if</span> <span class="structure">(</span> <span class="word">blessed</span><span class="structure">(</span><span class="magic">$_</span><span class="structure">)</span> <span class="operator">&&</span> <span class="magic">$_</span><span class="operator">-></span><span class="word">isa</span><span class="structure">(</span><span class="double">"failure::io::file"</span><span class="structure">)</span> <span class="structure">)</span> <span class="structure">{</span><br /> <span class="operator">...</span><br /> <span class="structure">}</span><br /> <span class="keyword">elsif</span><span class="structure">(</span> <span class="word">blessed</span><span class="structure">(</span><span class="magic">$_</span><span class="structure">)</span> <span class="operator">&&</span> <span class="magic">$_</span><span class="operator">-></span><span class="word">isa</span><span class="structure">(</span><span class="double">"failure::io"</span><span class="structure">)</span> <span class="structure">)</span> <span class="structure">{</span><br /> <span class="operator">...</span><br /> <span class="structure">}</span><br /> <span class="keyword">elsif</span><span class="structure">(</span> <span class="word">blessed</span><span class="structure">(</span><span class="magic">$_</span><span class="structure">)</span> <span class="operator">&&</span> <span class="magic">$_</span><span class="operator">-></span><span class="word">isa</span><span class="structure">(</span><span class="double">"failure"</span><span class="structure">)</span> <span class="structure">)</span> <span class="structure">{</span><br /> <span class="operator">...</span><br /> <span class="structure">}</span><br /> <span class="keyword">else</span> <span class="structure">{</span> <span class="comment"># string or ref or other object exception</span><br /> <span class="operator">...</span><br /> <span class="structure">}</span><br /><span class="structure">}</span></code></pre>
<p>Or wrap it all in another <code>if</code> just to test <code>blessed</code>?</p>
<pre><code class="code-listing"><span class="keyword">use</span> <span class="pragma">failures</span> <span class="words">qw/io::file io::network/</span><span class="structure">;</span><br /><span class="keyword">use</span> <span class="word">Try::Tiny</span><span class="structure">;</span><br /><br /><span class="word">try</span> <span class="structure">{</span><br /> <span class="word">something_that_might_fail</span><span class="structure">()</span><br /><span class="structure">}</span><br /><span class="word">catch</span> <span class="structure">{</span><br /> <span class="keyword">if</span> <span class="structure">(</span> <span class="word">blessed</span><span class="structure">(</span><span class="magic">$_</span><span class="structure">)</span> <span class="structure">)</span> <span class="structure">{</span><br /> <span class="keyword">if</span> <span class="structure">(</span> <span class="magic">$_</span><span class="operator">-></span><span class="word">isa</span><span class="structure">(</span><span class="double">"failure::io::file"</span><span class="structure">)</span> <span class="structure">)</span> <span class="structure">{</span><br /> <span class="operator">...</span><br /> <span class="structure">}</span><br /> <span class="keyword">elsif</span><span class="structure">(</span> <span class="magic">$_</span><span class="operator">-></span><span class="word">isa</span><span class="structure">(</span><span class="double">"failure::io"</span><span class="structure">)</span> <span class="structure">)</span> <span class="structure">{</span><br /> <span class="operator">...</span><br /> <span class="structure">}</span><br /> <span class="keyword">elsif</span><span class="structure">(</span> <span class="magic">$_</span><span class="operator">-></span><span class="symbol">$isa</span><span class="structure">(</span><span class="double">"failure"</span><span class="structure">)</span> <span class="structure">)</span> <span class="structure">{</span><br /> <span class="operator">...</span><br /> <span class="structure">}</span><br /> <span class="keyword">else</span> <span class="structure">{</span> <span class="comment"># other object</span><br /> <span class="operator">...</span><br /> <span class="structure">}</span><br /> <span class="structure">}</span><br /> <span class="keyword">else</span> <span class="structure">{</span> <span class="comment"># string or ref exception</span><br /> <span class="operator">...</span><br /> <span class="structure">}</span><br /><span class="structure">}</span></code></pre>
<p><a href="https://metacpan.org/module/Safe::Isa">Safe::Isa</a> makes this easier by exporting an <code>$_isa</code> variable containing a code reference that you can use in place of <code>UNIVERSAL::isa</code>. It checks <code>blessed</code> and <code>isa</code> for you, just the way you want:</p>
<pre><code class="code-listing"><span class="keyword">use</span> <span class="word">Safe::Isa</span><span class="structure">;</span><br /><br /><span class="keyword">if</span> <span class="structure">(</span> <span class="symbol">$thing</span><span class="operator">-></span><span class="symbol">$_isa</span><span class="structure">(</span> <span class="double">"Class::I'm::Looking::For"</span> <span class="structure">)</span> <span class="structure">}</span> <span class="structure">{</span><br /><span class="comment"> # do something with $thing<br /></span><span class="structure">}</span></code></pre>
<p>This works because Perl treats a code reference on the right side of an arrow operator as a method to invoke. These are equivalent:</p>
<pre><code class="code-listing"><span class="symbol">$thing</span><span class="operator">-></span><span class="symbol">$_isa</span><span class="structure">(</span> <span class="double">"Class::I'm::Looking::For"</span> <span class="structure">)</span><br /><span class="symbol">$_isa</span><span class="operator">-></span><span class="structure">(</span> <span class="symbol">$thing</span><span class="operator">,</span> <span class="double">"Class::I'm::Looking::For"</span> <span class="structure">)</span></code></pre>
<p>That makes our earlier <code>failures</code> example a bit more concise:</p>
<pre><code class="code-listing"><span class="keyword">use</span> <span class="pragma">failures</span> <span class="words">qw/io::file io::network/</span><span class="structure">;</span><br /><span class="keyword">use</span> <span class="word">Try::Tiny</span><span class="structure">;</span><br /><span class="keyword">use</span> <span class="word">Safe::Isa</span><span class="structure">;</span> <span class="comment"># for $_isa</span><br /><br /><span class="word">try</span> <span class="structure">{</span><br /> <span class="word">something_that_might_fail</span><span class="structure">()</span><br /><span class="structure">}</span><br /><span class="word">catch</span> <span class="structure">{</span><br /> <span class="keyword">if</span> <span class="structure">(</span> <span class="magic">$_</span><span class="operator">-></span><span class="symbol">$_isa</span><span class="structure">(</span><span class="double">"failure::io::file"</span><span class="structure">)</span> <span class="structure">)</span> <span class="structure">{</span><br /> <span class="operator">...</span><br /> <span class="structure">}</span><br /> <span class="keyword">elsif</span><span class="structure">(</span> <span class="magic">$_</span><span class="operator">-></span><span class="symbol">$_isa</span><span class="structure">(</span><span class="double">"failure::io"</span><span class="structure">)</span> <span class="structure">)</span> <span class="structure">{</span><br /> <span class="operator">...</span><br /> <span class="structure">}</span><br /> <span class="keyword">elsif</span><span class="structure">(</span> <span class="magic">$_</span><span class="operator">-></span><span class="symbol">$_isa</span><span class="structure">(</span><span class="double">"failure"</span><span class="structure">)</span> <span class="structure">)</span> <span class="structure">{</span><br /> <span class="operator">...</span><br /> <span class="structure">}</span><br /> <span class="keyword">else</span> <span class="structure">{</span><br /> <span class="operator">...</span><br /> <span class="structure">}</span><br /><span class="structure">}</span></code></pre>
<p><a href="https://metacpan.org/module/Safe::Isa">Safe::Isa</a> gives you several similar helpers, including <code>$_can</code>, <code>$_does</code>, and <code>$_DOES</code>, plus a generic <code>$_call_if_object</code> code reference that works like this:</p>
<pre><code class="code-listing"><span class="symbol">$thing</span><span class="operator">-></span><span class="symbol">$_call_if_object</span><span class="structure">(</span><span class="word">method_name</span> <span class="operator">=></span> <span class="symbol">@args</span><span class="structure">);</span></code></pre>
<p>The lesson is this: calling a method on something that you aren't sure is an object is like stepping into an elevator without checking that it's there. Most of the time, you're safe, right until you have a long fall and crash.</p>
<p>Using <a href="https://metacpan.org/module/Safe::Isa">Safe::Isa</a> gives you a safe, concise way to look before you step.</p>
<h2 id="See-Also">See Also</h2>
<ul>
<li><p><a href="https://metacpan.org/module/Safe::Isa">Safe::Isa</a></p>
</li>
</ul>
</div>2013-12-05T00:00:00ZDavid GoldenGift Exchanges as a Practical Example of Cyclic Directional Graphshttp://perladvent.org/2013/2013-12-04.html<div class='pod'><p>Sometimes, graphs are huge, complex drawings showing the far-stretching relationships between myriads of elements.</p>
<p>Other times? We just feel the need to draw a few boxes and arrows to get a visual idea of what the heck is going on.</p>
<p>For those latter cases, <a href="https://metacpan.org/module/Graph::Easy">Graph::Easy</a> is your friend.</p>
<p><i>Graph::Easy</i> is a helping elf with no delusion of grandeur. It is primary meant for tackling modest graphs (think less than 100 nodes), but it does it with a simplicity and an ease of use that is very nice indeed.</p>
<p>For example, let's say you're managing a gift exchange. A simple one where you just have to decide who's giving to who, and what. Well, that's easy enough:</p>
<pre><code class="code-listing"><span class="keyword">use</span> <span class="version">5.16.0</span><span class="structure">;</span><br /><br /><span class="keyword">use</span> <span class="word">Graph::Easy</span><span class="structure">;</span><br /><span class="keyword">use</span> <span class="word">List::AllUtils</span> <span class="words">qw/ shuffle /</span><span class="structure">;</span><br /><br /><span class="keyword">my</span> <span class="symbol">@peeps</span> <span class="operator">=</span> <span class="word">shuffle</span> <span class="words">qw/<br /> alice bernard charlotte dee ezekiel <br /> felicia gregory heidi isaac julia karl <br /> leo marie nathan<br />/</span><span class="structure">;</span><br /><br /><span class="keyword">my</span> <span class="symbol">@gifts</span> <span class="operator">=</span> <span class="word">shuffle</span> <span class="words">qw/<br /> book CD slippers teddy bear bathrobe<br /> mittens scarf chocolate candles wine<br /> clock calendar mirror playing cards<br /> beanie<br />/</span><span class="structure">;</span><br /><br /><span class="keyword">my</span> <span class="symbol">$exchange</span> <span class="operator">=</span> <span class="word">Graph::Easy</span><span class="operator">-></span><span class="word">new</span><span class="structure">;</span><br /><br /><span class="keyword">while</span><span class="structure">(</span> <span class="keyword">my</span><span class="structure">(</span> <span class="symbol">$i</span><span class="operator">,</span> <span class="symbol">$p</span> <span class="structure">)</span> <span class="operator">=</span> <span class="word">each</span> <span class="symbol">@peeps</span> <span class="structure">)</span> <span class="structure">{</span><br /><span class="comment"> # from, to, gift<br /></span> <span class="symbol">$exchange</span><span class="operator">-></span><span class="word">add_edge</span><span class="structure">(</span> <span class="symbol">$p</span><span class="operator">,</span> <span class="symbol">$peeps</span><span class="structure">[</span><span class="symbol">$i</span><span class="operator">-</span><span class="number">1</span><span class="structure">]</span><span class="operator">,</span> <span class="symbol">$gifts</span><span class="structure">[</span><span class="symbol">$i</span><span class="structure">]</span> <span class="structure">);</span><br /><span class="structure">}</span></code></pre>
<p>Our graph now contains all the information we want, and we can get it back in a variety of formats. We can get a human-friendly list of edges:</p>
<pre><code class="code-listing"><span class="word">print</span> <span class="symbol">$exchange</span><span class="operator">-></span><span class="word">as_txt</span><span class="structure">;</span></code></pre>
<p>which will output</p>
<pre><code> [ ezekiel ] -- wine --> [ heidi ]
[ heidi ] -- CD --> [ bernard ]
[ bernard ] -- slippers --> [ charlotte ]
[ charlotte ] -- playing --> [ leo ]
[ leo ] -- book --> [ karl ]
[ karl ] -- cards --> [ nathan ]
[ nathan ] -- chocolate --> [ felicia ]
[ felicia ] -- scarf --> [ marie ]
[ marie ] -- teddy --> [ gregory ]
[ gregory ] -- bear --> [ dee ]
[ dee ] -- beanie --> [ alice ]
[ alice ] -- mirror --> [ julia ]
[ julia ] -- bathrobe --> [ isaac ]
[ isaac ] -- clock --> [ ezekiel ]</code></pre>
<p>or we can get an ascii representation of the graph:</p>
<pre><code> print $exchange->as_ascii;</code></pre>
<p>which output</p>
<pre><code> chocolate
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
v |
+-------+ beanie +---------+ candles +------+ book +---------+ teddy +---------+ cards +-------+ clock +-----------+ slippers +--------+ calendar +---------+ bear +-----+ mittens +-------+ playing +-----+ mirror +-------+ CD +-------+
| marie | --------> | gregory | ---------> | karl | ------> | ezekiel | -------> | felicia | -------> | isaac | -------> | charlotte | ----------> | nathan | ----------> | bernard | ------> | dee | ---------> | julia | ---------> | leo | --------> | alice | ----> | heidi |
+-------+ +---------+ +------+ +---------+ +---------+ +-------+ +-----------+ +--------+ +---------+ +-----+ +-------+ +-----+ +-------+ +-------+</code></pre>
<p>Granted, that format is useful for small graphes, but it get hard to grok for bigger ones. For those, there are better suited graphical output formats. Like <code>svg</code>, provided by <a href="https://metacpan.org/module/Graph::Easy::As_svg">Graph::Easy::As_svg</a> (which is not part of the core <i>Graph::Easy</i> distribution):</p>
<pre><code class="code-listing"><span class="word">print</span> <span class="symbol">$exchange</span><span class="operator">-></span><span class="word">as_svg</span><span class="structure">;</span></code></pre>
<p>which gives us the prettier</p>
<div style='overflow:scroll'>
<svg width="2456.312" height="165.56" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generated at Sun Dec 1 14:49:55 2013 by:
Graph::Easy v0.73
Graph::Easy::As_svg v0.23
-->
<title>Untitled graph</title>
<defs>
<!-- open arrow -->
<g id="ah" stroke-linecap="round" stroke-width="1">
<line x1="-8" y1="-4" x2="1" y2="0" />
<line x1="1" y1="0" x2="-8" y2="4" />
</g>
<!-- class definitions -->
<style type="text/css"><![CDATA[
.edge {
font-size: 13px;
stroke: black;
text-align: center;
}
.graph {
font-size: 16px;
text-align: center;
}
.node {
font-size: 16px;
text-align: center;
}
]]></style>
</defs>
<!-- graph background with border (mainly for printing) -->
<rect x="0.5" y="0.5" width="2454.312" height="163.56" fill="white" stroke="white" />
<g id="0" class="edge">
<!-- from ezekiel to nathan -->
<!-- horizontal -->
<line x1="105.92" y1="114.92" x2="200.25" y2="114.92" stroke="#000000" />
<use stroke="#000000" xlink:href="#ah" x="201.25" y="114.92"/>
<text x="114" y="110" style="font-family:sans-serif;font-size:12.8px" fill="#000000" stroke="none">playing</text>
</g>
<g id="11" class="edge">
<!-- from julia to dee -->
<!-- horizontal -->
<line x1="1769.82" y1="114.92" x2="1853.1" y2="114.92" stroke="#000000" />
<use stroke="#000000" xlink:href="#ah" x="1854.1" y="114.92"/>
<text x="1779" y="110" style="font-family:sans-serif;font-size:12.8px" fill="#000000" stroke="none">clock</text>
</g>
<g id="13" class="edge">
<!-- from heidi to julia -->
<!-- horizontal -->
<line x1="1588.21" y1="114.92" x2="1692.17" y2="114.92" stroke="#000000" />
<use stroke="#000000" xlink:href="#ah" x="1693.17" y="114.92"/>
<text x="1595" y="110" style="font-family:sans-serif;font-size:12.8px" fill="#000000" stroke="none">bathrobe</text>
</g>
<g id="15" class="edge">
<!-- from charlotte to heidi -->
<!-- horizontal -->
<line x1="1408.45" y1="114.92" x2="1504.02" y2="114.92" stroke="#000000" />
<use stroke="#000000" xlink:href="#ah" x="1505.02" y="114.92"/>
<text x="1416" y="110" style="font-family:sans-serif;font-size:12.8px" fill="#000000" stroke="none">candles</text>
</g>
<g id="17" class="edge">
<!-- from felicia to charlotte -->
<!-- horizontal -->
<line x1="1212.03" y1="114.92" x2="1292.23" y2="114.92" stroke="#000000" />
<use stroke="#000000" xlink:href="#ah" x="1293.23" y="114.92"/>
<text x="1222" y="110" style="font-family:sans-serif;font-size:12.8px" fill="#000000" stroke="none">wine</text>
</g>
<g id="19" class="edge">
<!-- from gregory to felicia -->
<!-- horizontal -->
<line x1="1018.33" y1="114.92" x2="1120.04" y2="114.92" stroke="#000000" />
<use stroke="#000000" xlink:href="#ah" x="1121.04" y="114.92"/>
<text x="1025" y="110" style="font-family:sans-serif;font-size:12.8px" fill="#000000" stroke="none">calendar</text>
</g>
<g id="21" class="edge">
<!-- from bernard to gregory -->
<!-- horizontal -->
<line x1="838.86" y1="114.92" x2="909.54" y2="114.92" stroke="#000000" />
<use stroke="#000000" xlink:href="#ah" x="910.54" y="114.92"/>
<text x="850" y="110" style="font-family:sans-serif;font-size:12.8px" fill="#000000" stroke="none">CD</text>
</g>
<g id="23" class="edge">
<!-- from marie to bernard -->
<!-- horizontal -->
<line x1="652.89" y1="114.92" x2="732.78" y2="114.92" stroke="#000000" />
<use stroke="#000000" xlink:href="#ah" x="733.78" y="114.92"/>
<text x="663" y="110" style="font-family:sans-serif;font-size:12.8px" fill="#000000" stroke="none">bear</text>
</g>
<g id="25" class="edge">
<!-- from isaac to marie -->
<!-- horizontal -->
<line x1="479.01" y1="114.92" x2="564.02" y2="114.92" stroke="#000000" />
<use stroke="#000000" xlink:href="#ah" x="565.02" y="114.92"/>
<text x="488" y="110" style="font-family:sans-serif;font-size:12.8px" fill="#000000" stroke="none">teddy</text>
</g>
<g id="27" class="edge">
<!-- from nathan to isaac -->
<!-- horizontal -->
<line x1="299.28" y1="114.92" x2="395.15" y2="114.92" stroke="#000000" />
<use stroke="#000000" xlink:href="#ah" x="396.15" y="114.92"/>
<text x="307" y="110" style="font-family:sans-serif;font-size:12.8px" fill="#000000" stroke="none">mittens</text>
</g>
<g id="3" class="edge">
<!-- from karl to ezekiel -->
<!-- south/west corner -->
<g stroke="#000000">
<line x1="2412.31" y1="49.14" x2="2412.31" y2="75.88" />
<line x1="2386.31" y1="49.64" x2="2412.81" y2="49.64" />
</g>
<!-- horizontal -->
<line x1="94" y1="49.64" x2="2386.31" y2="49.64" stroke="#000000" />
<text x="119.6" y="44" style="font-family:sans-serif;font-size:12.8px" fill="#000000" stroke="none">book</text>
<!-- south/east corner -->
<g stroke="#000000">
<line x1="55.5" y1="49.14" x2="55.5" y2="74.75" />
<line x1="55" y1="49.64" x2="94" y2="49.64" />
</g>
<use stroke="#000000" xlink:href="#ah" transform="translate(55.5 75.75)rotate(90)"/>
</g>
<g id="5" class="edge">
<!-- from leo to karl -->
<!-- horizontal -->
<line x1="2274.45" y1="114.92" x2="2372.88" y2="114.92" stroke="#000000" />
<use stroke="#000000" xlink:href="#ah" x="2373.88" y="114.92"/>
<text x="2282" y="110" style="font-family:sans-serif;font-size:12.8px" fill="#000000" stroke="none">slippers</text>
</g>
<g id="7" class="edge">
<!-- from alice to leo -->
<!-- horizontal -->
<line x1="2113.5" y1="114.92" x2="2206.3" y2="114.92" stroke="#000000" />
<use stroke="#000000" xlink:href="#ah" x="2207.3" y="114.92"/>
<text x="2122" y="110" style="font-family:sans-serif;font-size:12.8px" fill="#000000" stroke="none">mirror</text>
</g>
<g id="9" class="edge">
<!-- from dee to alice -->
<!-- horizontal -->
<line x1="1925.05" y1="114.92" x2="2031.36" y2="114.92" stroke="#000000" />
<use stroke="#000000" xlink:href="#ah" x="2032.36" y="114.92"/>
<text x="1932" y="110" style="font-family:sans-serif;font-size:12.8px" fill="#000000" stroke="none">chocolate</text>
</g>
<g id="1" class="node">
<!-- ezekiel, rect -->
<rect fill="#ffffff" height="64.28" stroke="#000000" width="76" x="17.5" y="82.78" />
<text x="55" y="120" style="font-family:serif" fill="#000000" text-anchor="middle">ezekiel</text>
</g>
<g id="2" class="node">
<!-- nathan, rect -->
<rect fill="#ffffff" height="64.28" stroke="#000000" width="73" x="213.668" y="82.78" />
<text x="250" y="120" style="font-family:serif" fill="#000000" text-anchor="middle">nathan</text>
</g>
<g id="4" class="node">
<!-- karl, rect -->
<rect fill="#ffffff" height="64.28" stroke="#000000" width="51" x="2386.812" y="82.78" />
<text x="2412" y="120" style="font-family:serif" fill="#000000" text-anchor="middle">karl</text>
</g>
<g id="6" class="node">
<!-- leo, rect -->
<rect fill="#ffffff" height="64.28" stroke="#000000" width="42" x="2219.524" y="82.78" />
<text x="2240" y="120" style="font-family:serif" fill="#000000" text-anchor="middle">leo</text>
</g>
<g id="8" class="node">
<!-- alice, rect -->
<rect fill="#ffffff" height="64.28" stroke="#000000" width="55" x="2046.276" y="82.78" />
<text x="2073" y="120" style="font-family:serif" fill="#000000" text-anchor="middle">alice</text>
</g>
<g id="10" class="node">
<!-- dee, rect -->
<rect fill="#ffffff" height="64.28" stroke="#000000" width="46" x="1865.132" y="82.78" />
<text x="1888" y="120" style="font-family:serif" fill="#000000" text-anchor="middle">dee</text>
</g>
<g id="12" class="node">
<!-- julia, rect -->
<rect fill="#ffffff" height="64.28" stroke="#000000" width="52" x="1706.788" y="82.78" />
<text x="1732" y="120" style="font-family:serif" fill="#000000" text-anchor="middle">julia</text>
</g>
<g id="14" class="node">
<!-- heidi, rect -->
<rect fill="#ffffff" height="64.28" stroke="#000000" width="57" x="1517.588" y="82.78" />
<text x="1546" y="120" style="font-family:serif" fill="#000000" text-anchor="middle">heidi</text>
</g>
<g id="16" class="node">
<!-- charlotte, rect -->
<rect fill="#ffffff" height="64.28" stroke="#000000" width="92" x="1303.884" y="82.78" />
<text x="1349" y="120" style="font-family:serif" fill="#000000" text-anchor="middle">charlotte</text>
</g>
<g id="18" class="node">
<!-- felicia, rect -->
<rect fill="#ffffff" height="64.28" stroke="#000000" width="67" x="1134.38" y="82.78" />
<text x="1167" y="120" style="font-family:serif" fill="#000000" text-anchor="middle">felicia</text>
</g>
<g id="20" class="node">
<!-- gregory, rect -->
<rect fill="#ffffff" height="64.28" stroke="#000000" width="85" x="919.996" y="82.78" />
<text x="962" y="120" style="font-family:serif" fill="#000000" text-anchor="middle">gregory</text>
</g>
<g id="22" class="node">
<!-- bernard, rect -->
<rect fill="#ffffff" height="64.28" stroke="#000000" width="85" x="744.396" y="82.78" />
<text x="786" y="120" style="font-family:serif" fill="#000000" text-anchor="middle">bernard</text>
</g>
<g id="24" class="node">
<!-- marie, rect -->
<rect fill="#ffffff" height="64.28" stroke="#000000" width="66" x="576.276" y="82.78" />
<text x="609" y="120" style="font-family:serif" fill="#000000" text-anchor="middle">marie</text>
</g>
<g id="26" class="node">
<!-- isaac, rect -->
<rect fill="#ffffff" height="64.28" stroke="#000000" width="59" x="408.756" y="82.78" />
<text x="438" y="120" style="font-family:serif" fill="#000000" text-anchor="middle">isaac</text>
</g>
</svg>
</div>
<p>And, of course, in true Perlish fashion, we can also take things into our own hands and just work on the graph ourselves:</p>
<pre><code class="code-listing"><span class="word">printf</span> <span class="double">"From: %s, To: %s, item: %s\n"</span><span class="operator">,</span> <br /> <span class="magic">$_</span><span class="operator">-></span><span class="word">label</span><span class="operator">,</span> <br /><span class="comment"> # because we know there's only one edge per peep<br /></span> <span class="word">map</span> <span class="structure">{</span> <span class="magic">$_</span><span class="operator">-></span><span class="word">to</span><span class="operator">-></span><span class="word">label</span><span class="operator">,</span> <span class="magic">$_</span><span class="operator">-></span><span class="word">label</span> <span class="structure">}</span><span class="magic">$_</span><span class="operator">-></span><span class="word">edges</span> <span class="word">for</span> <span class="symbol">$exchange</span><span class="operator">-></span><span class="word">nodes</span><span class="structure">;</span></code></pre>
<p>which gives us</p>
<pre><code> From: alice, To: karl, item: beanie
From: bernard, To: leo, item: playing
From: charlotte, To: felicia, item: CD
From: dee, To: dee, item: chocolate
From: ezekiel, To: marie, item: mittens
From: felicia, To: dee, item: chocolate
From: gregory, To: nathan, item: bathrobe
From: heidi, To: ezekiel, item: book
From: isaac, To: bernard, item: cards
From: julia, To: charlotte, item: mirror
From: karl, To: julia, item: scarf
From: leo, To: gregory, item: clock
From: marie, To: alice, item: calendar
From: nathan, To: nathan, item: bathrobe</code></pre>
<h2 id="See-Also">See Also</h2>
<ul>
<li><p><a href="https://metacpan.org/module/Graph::Easy">Graph::Easy</a></p>
</li>
</ul>
</div>2013-12-04T00:00:00ZYanick ChampouxSwarm your webserverhttp://perladvent.org/2013/2013-12-03.html<div class='pod'><p>"My name is Legion, for we are many."¹</p>
<p>App::Legion is a tool for loading up your server(s) and seeing how well the load is handled. It is specifically written for static content served to many clients. Obviously you <i>could</i> use it for dynamic content, and if you are pro enough to serve dynamic content to thousands of concurrent requests I tip my hat to you.</p>
<p>The special feature that Legion brings to the table is that it can use multiple computers as clients concurrently. If you have <i>ssh</i> access to a unix machine it is likely that it can work as a Legion client with little work on your end. There are three things that are required for Legion to use a server as a client:</p>
<dl>
<dt>ssh access</dt>
<dd>
<p>ssh is how Legion connects to clients and ships code and data over the wire</p>
</dd>
<dt>perl</dt>
<dd>
<p>Perl must be installed on the unix machine that is slated to be a client for Legion to run</p>
</dd>
<dt>ab</dt>
<dd>
<p>This is probably the only requirement that a typical unix box doesn't already meet. <i>ab</i> is the "apache bench" tool that comes from the <i>apache2-utils</i> package in debian based systems. (Eventually I'd like to support <i>wrk</i>, but I'd like to wait until it is prepackaged for major distributions before supporting it.)</p>
</dd>
</dl>
<h3 id="Example">Example</h3>
<pre><code class="code-listing"><span class="keyword">use</span> <span class="word">App::Legion</span><span class="structure">;</span><br /><span class="keyword">use</span> <span class="word">Devel::Dwarn</span><span class="structure">;</span><br /><br /><span class="keyword">my</span> <span class="symbol">$stats</span> <span class="operator">=</span> <span class="word">App::Legion</span><span class="operator">-></span><span class="word">new</span><span class="structure">(</span><br /> <span class="word">server_host</span> <span class="operator">=></span> <span class="single">'test-server-1'</span><span class="operator">,</span><br /> <span class="word">client_hosts</span> <span class="operator">=></span> <span class="structure">[</span><span class="single">'frew@client1'</span><span class="operator">,</span> <span class="single">'frew@client2'</span><span class="structure">]</span><span class="operator">,</span><br /> <span class="word">concurrency</span> <span class="operator">=></span> <span class="number">100</span><span class="operator">,</span><br /> <span class="word">requests</span> <span class="operator">=></span> <span class="number">5_000</span><span class="operator">,</span><br /> <span class="word">urls</span> <span class="operator">=></span> <span class="structure">[</span><span class="words">qw(<br /> /css.css<br /> /js.js<br /> /sound/cache/123.wav<br /> /static/cache/123.html<br /> )</span><span class="structure">]</span><span class="operator">,</span><br /><span class="structure">)</span><span class="operator">-></span><span class="word">run</span><span class="structure">;</span><br /><br /><span class="word">DwarnF</span> <span class="structure">{</span> <span class="double">"rps per url: $_[0]"</span> <span class="structure">}</span> <span class="symbol">$stats</span><span class="operator">-></span><span class="word">requests_per_second_by_url</span><span class="structure">;</span></code></pre>
<p>The above will fire up clients on the hosts client1 and client2, hit four distinct urls at a concurrency of 100 <i>each</i>, totalling to a concurrency of about 800 against the server. Obviously numbers need to be tweaked for your usecase.</p>
<p>The object returned from <code>run</code> contains all of the information measured by each <code>ab</code> instance. There are a few methods that you can use to query it, but as I suspect that I don't know what all people want to know, I decided to just store the information in a SQLite database that can easily be queried against to do more complicated reporting. If you are a fan of <a href="https://metacpan.org/module/DBIx::Class">DBIx::Class</a> you can use that to query the db:</p>
<pre><code class="code-listing"><span class="operator">+</span><span class="structure">{</span><br /> <span class="word">map</span> <span class="structure">{</span> <span class="magic">$_</span><span class="operator">-></span><span class="structure">{</span><span class="word">url</span><span class="structure">}</span> <span class="operator">=></span> <span class="magic">$_</span><span class="operator">-></span><span class="structure">{</span><span class="word">tpr</span><span class="structure">}</span> <span class="structure">}</span><br /> <span class="symbol">$self</span><span class="operator">-></span><span class="word">_schema</span><span class="operator">-></span><span class="word">resultset</span><span class="structure">(</span><span class="single">'Measurement'</span><span class="structure">)</span><span class="operator">-></span><span class="word">search</span><span class="structure">(</span><span class="core">undef</span><span class="operator">,</span> <span class="structure">{</span><br /> <span class="word">columns</span> <span class="operator">=></span> <span class="structure">{</span><br /> <span class="word">tpr</span> <span class="operator">=></span> <span class="structure">{</span> <span class="word">avg</span> <span class="operator">=></span> <span class="single">'time_per_request'</span> <span class="structure">}</span><span class="operator">,</span><br /> <span class="word">url</span> <span class="operator">=></span> <span class="single">'url.url'</span><span class="operator">,</span><br /> <span class="structure">}</span><span class="operator">,</span><br /> <span class="word">join</span> <span class="operator">=></span> <span class="structure">[</span><span class="words">qw(url)</span><span class="structure">]</span><span class="operator">,</span><br /> <span class="word">group_by</span> <span class="operator">=></span> <span class="structure">[</span><span class="words">qw(url.url)</span><span class="structure">]</span><span class="operator">,</span><br /> <span class="word">result_class</span> <span class="operator">=></span> <span class="single">'DBIx::Class::ResultClass::HashRefInflator'</span><span class="operator">,</span><br /> <span class="structure">})</span><span class="operator">-></span><span class="word">all</span><br /><span class="structure">}</span></code></pre>
<p>or if you prefer to just use raw sql, that's obviously fine too:</p>
<pre><code class="code-listing"><span class="symbol">$stats</span><span class="operator">-></span><span class="word">dbh</span><span class="operator">-></span><span class="word">selectrow_hashref</span><span class="structure">(</span><span class="heredoc"><<'SQL'</span><span class="structure">)</span><br /><span class="heredoc_content"><br />FROM "measurements" "me"<br />JOIN "urls" "url" ON "me"."url_id" = "url"."id"<br />GROUP BY "url"."url"<br /></span><span class="heredoc_terminator">SQL<br /></span></code></pre>
<p>The structure of the schema can be seen <a href="https://metacpan.org/module/App::Legion::Schema">here</a>.</p>
<h3 id="Guts">Guts</h3>
<p>I think that how Legion works is pretty interesting. Basically it's just the glue between two technologies: <code>ab</code> and <a href="https://metacpan.org/module/Object::Remote">Object::Remote</a>. <code>ab</code> is not super exciting but it certainly can hit servers harder than I could with pure Perl. <a href="https://metacpan.org/module/Object::Remote">Object::Remote</a>, on the other hand, is a much more interesting beast.</p>
<p><a href="https://metacpan.org/module/Object::Remote">Object::Remote</a> is a tool that allows you to write Perl (explicitly pure Perl, which means Moose, DBI, and many other cpan modules are not allowed) objects and run them elsewhere. It's not quite bulletproof yet, but for the most part it has worked for me.</p>
<p>It has a fairly in depth logging system; the ability to run remote code (what this module uses), local code (forks instead of remote connections), and local superuser code. It could use more documentation, but I'm sure the authors would be willing to take patches for that.</p>
<h3 id="Next-Steps">Next Steps</h3>
<p>Because <a href="https://metacpan.org/module/Object::Remote">Object::Remote</a> gives us this incredibly useful ability to run code on servers with basically no configuration (everything has ssh and perl, right?) there are some really handy ideas that can come in the future. I would like to refactor Legion to be a wrapper around a generic <a href="http://research.google.com/archive/mapreduce.html">MapReduce</a> library.</p>
<h3 id="A-Warning">A Warning</h3>
<p>Due to the nature of what Legion is and the tools it leverages, it is far from perfect. It is perfectly suited to loading up a web server and seeing how the web server holds up. On the other hand, if you were to use it as some kind of core tech in your application I would say you should either hold off and wait or work with <a href="http://shadow.cat/">Shadowcat</a> to improve <a href="https://metacpan.org/module/Object::Remote">Object::Remote</a>. On top of that, <code>ab</code> sometimes gives up and crashes earlier than I'd rather, but there is little I can do about that aside from increasing timeouts and whatnot.</p>
<h2 id="Footnotes">Footnotes</h2>
<ul>
<p>1 Bible quotes are Christmassy, right? — Ed.</p>
</ul>
<h2 id="See-Also">See Also</h2>
<ul>
<li><p><a href="https://metacpan.org/module/Object::Remote">Object::Remote</a></p>
</li>
</ul>
</div>2013-12-03T00:00:00ZArthur Axel "fREW" SchmidtDancer Goes Megasplathttp://perladvent.org/2013/2013-12-02.html<div class='pod'><p>No, Santa Claus' sleigh just didn't have the mother of all reindeer-benders. This article is rather about the little-known but very useful feature of <a href="https://metacpan.org/module/Dancer">Dancer</a> known as the megasplat.</p>
<p>So, what's the megasplat? Well, <code>Dancer</code>, being heavily influenced by Ruby's <a href="http://www.sinatrarb.com/">Sinatra</a>, adopted its <i>splat</i> placeholder, which allows to capture elements of a route:</p>
<pre><code class="code-listing"><span class="keyword">use</span> <span class="word">Dancer</span><span class="structure">;</span><br /><br /><span class="word">get</span> <span class="single">'/wishlist/*'</span> <span class="operator">=></span> <span class="keyword">sub</span> <span class="structure">{</span><br /> <span class="keyword">my</span><span class="structure">(</span> <span class="symbol">$child</span> <span class="structure">)</span> <span class="operator">=</span> <span class="word">splat</span><span class="structure">;</span><br /><br /> <span class="keyword">return</span> <span class="word">NortPole::DB</span><span class="operator">-></span><span class="word">get_wishlist</span><span class="structure">(</span> <span class="symbol">$child</span> <span class="structure">);</span><br /><span class="structure">};</span></code></pre>
<p>That route will match <i>/wishlist/timmy</i>, and <i>/wishlist/sandy</i>, and the wishlist of every other child in the world, but what if we want to match several path elements? That's where we go mega:</p>
<pre><code class="code-listing"><span class="keyword">use</span> <span class="word">Dancer</span><span class="structure">;</span><br /><br /><span class="word">get</span> <span class="single">'/giddy_up/**'</span> <span class="operator">=></span> <span class="keyword">sub</span> <span class="structure">{</span><br /> <span class="keyword">my</span><span class="structure">(</span> <span class="symbol">$reindeers</span> <span class="structure">)</span> <span class="operator">=</span> <span class="word">splat</span><span class="structure">;</span><br /><br /> <span class="keyword">my</span> <span class="symbol">@exclamations</span> <span class="operator">=</span> <span class="structure">(</span><br /> <span class="single">'Now'</span><span class="operator">,</span> <span class="single">'On'</span><span class="operator">,</span> <span class="single">'To the top of the porch'</span><span class="operator">,</span> <span class="single">'To the top of the wall'</span><br /> <span class="structure">);</span><br /><br /> <span class="keyword">return</span> <span class="word">join</span> <span class="single">''</span><span class="operator">,</span> <span class="word">map</span> <span class="structure">{</span><br /> <span class="word">sprintf</span> <span class="double">"%s, %s!\n"</span><span class="operator">,</span><br /> <span class="symbol">$exclamations</span><span class="structure">[</span><span class="word">rand</span> <span class="symbol">@exclamations</span><span class="structure">]</span><span class="operator">,</span> <span class="magic">$_</span><br /> <span class="structure">}</span> <span class="cast">@</span><span class="symbol">$reindeers</span><span class="structure">;</span><br /><span class="structure">};</span><br /><br /><span class="word">dance</span><span class="structure">;</span></code></pre>
<p>With that, we can hit <i>/giddy_up/Prancer/Dancer/Vixen/Cupid</i> and get back:</p>
<pre><code> Now, Prancer!
To the top of the porch, Dancer!
To the top of the wall, Vixen!
On, Cupid!</code></pre>
<p>Besides that, the megasplat can also be used to mimick <a href="https://metacpan.org/module/Catalyst">Catalyst</a>'s chaining behavior:</p>
<pre><code class="code-listing"><span class="keyword">use</span> <span class="version">5.10.0</span><span class="structure">;</span><br /><br /><span class="keyword">use</span> <span class="word">Dancer</span><span class="structure">;</span><br /><br /><span class="keyword">my</span><span class="structure">(</span> <span class="symbol">@naughty</span><span class="operator">,</span> <span class="symbol">@nice</span><span class="operator">,</span> <span class="symbol">%gift</span><span class="operator">,</span> <span class="symbol">$child</span> <span class="structure">);</span><br /><br /><span class="word">any</span> <span class="single">'/child/*/**'</span> <span class="operator">=></span> <span class="keyword">sub</span> <span class="structure">{</span><br /> <span class="structure">(</span><span class="symbol">$child</span><span class="structure">)</span> <span class="operator">=</span> <span class="word">splat</span><span class="structure">;</span><br /> <span class="word">pass</span><span class="structure">;</span><br /><span class="structure">};</span><br /><br /><span class="word">prefix</span> <span class="operator">=</span> <span class="single">'/child/*'</span><span class="structure">;</span><br /><br /><span class="word">get</span> <span class="single">'/naughty'</span> <span class="operator">=></span> <span class="keyword">sub</span> <span class="structure">{</span> <span class="word">push</span> <span class="symbol">@naughty</span><span class="operator">,</span> <span class="symbol">$child</span><span class="structure">;</span> <span class="single">'tsk tsk'</span> <span class="structure">};</span><br /><span class="word">get</span> <span class="single">'/nice'</span> <span class="operator">=></span> <span class="keyword">sub</span> <span class="structure">{</span> <span class="word">push</span> <span class="symbol">@nice</span><span class="operator">,</span> <span class="symbol">$child</span><span class="structure">;</span> <span class="single">'nicely done'</span> <span class="structure">};</span><br /><br /><span class="word">put</span> <span class="single">'/gift/*'</span> <span class="operator">=></span> <span class="keyword">sub</span> <span class="structure">{</span> <span class="symbol">$gift</span><span class="structure">{</span><span class="symbol">$child</span><span class="structure">}</span> <span class="operator">=</span> <span class="structure">(</span><span class="word">splat</span><span class="structure">)[</span><span class="number">1</span><span class="structure">]</span> <span class="structure">};</span><br /><br /><span class="word">get</span> <span class="single">'/gift'</span> <span class="operator">=></span> <span class="keyword">sub</span> <span class="structure">{</span> <span class="symbol">$child</span> <span class="operator">~~</span> <span class="symbol">$naughty</span> <span class="operator">?</span> <span class="single">'coal'</span> <span class="operator">:</span> <span class="symbol">$gift</span><span class="structure">{</span><span class="symbol">$child</span><span class="structure">}</span> <span class="structure">};</span><br /><br /><span class="word">dance</span><span class="structure">;</span></code></pre>
<p>Which will give Santa a nice little basic web service for his <i>Nice & Naughty</i> book keeping:</p>
<pre><code> $ curl http://api.toydb.np/child/rjbs/nice
nicely done
$ curl http://api.toydb.np/child/yanick/naughty
tsk tsk
$ curl -X PUT http://api.toydb.np/child/rjbs/gift/pony
noted
$ curl -X PUT http://api.toydb.np/child/yanick/gift/pony
noted
$ curl http://api.toydb.np/child/yanick/gift
coal
$ curl http://api.toydb.np/child/rjbs/gift
pony</code></pre>
<h2 id="See-Also">See Also</h2>
<ul>
<li><p><a href="https://metacpan.org/module/Dancer">Dancer</a></p>
</li>
<li><p><a href="http://www.sinatrarb.com/">Sinatra</a></p>
</li>
</ul>
</div>2013-12-02T00:00:00ZYanick ChampouxSemantic Perlhttp://perladvent.org/2013/2013-12-01.html<div class='pod'><h2 id="SEMANTIC-PERL">SEMANTIC PERL</h2>
<p>Oh, what was that Christmas song I was trying to remember? It was a duet... I know that. Wikipedia's "Christmas songs" list is enormous; I don't want to click through each of those to find it.</p>
<p>Anyway, I'll forget about that for now; time for a Perl Advent...</p>
<h3 id="The-Triple">The Triple</h3>
<p>The semantic web is built around the idea of the "triple". The idea of the triple is so simple that a three year old can grasp it. (Trust me.)</p>
<p>To meaningfully describe anything we need at least three pieces of information:</p>
<ul>
<li><p>We need to know what thing is being described.</p>
</li>
<li><p>We need to specify an attribute of the thing.</p>
</li>
<li><p>We need to provide a value for that attribute.</p>
</li>
</ul>
<p>For example, assuming we have two <code>Person</code> objects, in Perl we might write something like:</p>
<pre><code class="code-listing"><span class="comment">### Three triples...<br /></span><span class="symbol">$person1</span><span class="operator">-></span><span class="word">name</span><span class="structure">(</span><span class="double">"Alice"</span><span class="structure">);</span> <span class="comment"># $person1's name is "Alice".</span><br /><span class="symbol">$person2</span><span class="operator">-></span><span class="word">name</span><span class="structure">(</span><span class="double">"Bob"</span><span class="structure">);</span> <span class="comment"># $person2's name is "Bob".</span><br /><span class="symbol">$person1</span><span class="operator">-></span><span class="word">spouse</span><span class="structure">(</span><span class="symbol">$person2</span><span class="structure">);</span> <span class="comment"># $person1's spouse is $person2.</span></code></pre>
<p>If you've ever told anyone your name, then you've used a triple.</p>
<p>More complex descriptions might be temporally or geographically qualified (Alice's spouse hasn't been Bob since the dawn of time), but information theory tells us that complex facts can be broken down into multiple triples, generally by taking a relationship and turning it into a "thing" in its own right:</p>
<pre><code class="code-listing"><span class="symbol">$marriage</span><span class="operator">-></span><span class="word">participant1</span><span class="structure">(</span><span class="symbol">$person1</span><span class="structure">);</span><br /><span class="symbol">$marriage</span><span class="operator">-></span><span class="word">participant2</span><span class="structure">(</span><span class="symbol">$person2</span><span class="structure">);</span><br /><span class="symbol">$marriage</span><span class="operator">-></span><span class="word">start</span><span class="structure">(</span><span class="symbol">$wedding_date</span><span class="structure">);</span><br /><span class="symbol">$marriage</span><span class="operator">-></span><span class="word">legally_recognised_in</span><span class="structure">(</span><span class="symbol">@countries</span><span class="structure">);</span></code></pre>
<p>So that's the triple. Three components. Any fewer would be useless; any more are just sugar.</p>
<p>A little terminology: in semantic web circles these three components are generally referred to as the subject, predicate and object respectively.</p>
<h3 id="The-Resource">The Resource</h3>
<p>The semantic web takes the concept of the triple and marries it with the concept of "resources".</p>
<p>What is a resource? A resource is anything that can be identified with a uniform resource identifier (URI). (If you're unfamiliar with URIs, think URL, or "web address". They're almost the same thing. Almost.) This is a somewhat circular definition.</p>
<p><code>https://metacpan.org/</code> is a URI. It is an identifier for a resource. That particular identifier happens to identify a resource which is a document. There are plenty of other URIs that identify documents, images, videos, mailboxes, FTP sites, and so forth on the Internet.</p>
<p>But nothing in the URI specifications places any limits on what kind of things may be identified by a URI. You could generate a URI to identify a car, or a planet, or a person.</p>
<p>While you can "dereference" <code>https://metacpan.org/</code> to get (a copy of) the actual document identified by that URI, you cannot expect to dereference a URI representing a car to retrieve an actual car. This is the difference between URLs and URIs. URLs are locators; URIs are mere identifiers. URLs are a subset of URIs.</p>
<p>URIs give us a global namespace for identifying things. So in the semantic web, we have triples where each component is a resource (i.e. something that can be identified by a URI).</p>
<p>It is fine to have multiple URIs identifying the same thing (think multiple references to the same object in Perl), but multiple things identified by the same URI leads to ambiguity.</p>
<p>This model of triples of resources is referred to as the Resource Description Framework (snappy name, right?) or RDF.</p>
<h3 id="My-First-Triple">My First Triple</h3>
<p>Let's assume that I've chosen the URI <code>http://tobyinkster.co.uk/#i</code> to identify myself. The inclusion of <code>#i</code> means that it's different from the URL that identifies my homepage. (Remember, multiple things identified by the same URI leads to ambiguity; so the URI I use to identify myself must be different to the URI for my homepage.) Now I can state my name in RDF like this:</p>
<pre><code class="code-listing"> <span class="synIdentifier"><</span><span class="synSpecial">http</span><span class="synComment">:</span><span class="synIdentifier">//</span><span class="synType">tobyinkster</span><span class="synComment">.</span><span class="synType">co</span><span class="synComment">.</span><span class="synType">uk</span><span class="synIdentifier">/#i></span><br /> <span class="synIdentifier"><</span><span class="synSpecial">http</span><span class="synComment">:</span><span class="synIdentifier">//</span><span class="synType">xmlns</span><span class="synComment">.</span><span class="synType">com</span><span class="synIdentifier">/</span><span class="synType">foaf</span><span class="synIdentifier">/0.1/name></span><br /> "Toby" .</code></pre>
<p>The second component there is a URI defined by the FOAF specification to identify the concept of having a name,</p>
<p>Note that the last component there is not a URI. A resource is anything that <i>can</i> be identified by a URI, but that doesn't always mean that it <i>must</i> be identified by a URI. Sometimes it's useful for a string to just be a string.</p>
<h3 id="Introducing-RDF::Trine-and-RDF::Query">Introducing RDF::Trine and RDF::Query</h3>
<p>While there are several other semantic web tool-kits on CPAN, <a href="https://metacpan.org/module/RDF::Trine">RDF::Trine</a> has emerged as the defacto standard.</p>
<p>RDF::Trine provides an object-oriented interface for dealing with resources and triples; persistent stores for triples, along with some basic methods for querying them; parsers and serialisers for various triple-based file formats (RDF/XML, Turtle, etc).</p>
<p>RDF::Trine is often used in conjunction with <a href="https://metacpan.org/module/RDF::Query">RDF::Query</a> which provides an implementation of SPARQL, an SQL-like query and update language for triple stores. The author of RDF::Trine and RDF::Query is involved in the W3C group standardising SPARQL 1.1, and as a result his Perl libraries are very high quality and standards-compliant implementations.</p>
<p>Here's an example of using the previous triple in RDF::Trine:</p>
<pre><code class="code-listing"><span class="keyword">use</span> <span class="float">5.010</span><span class="structure">;</span><br /><span class="keyword">use</span> <span class="pragma">strict</span><span class="structure">;</span><br /><span class="keyword">use</span> <span class="word">RDF::Trine</span> <span class="words">qw( statement iri literal )</span><span class="structure">;</span><br /><span class="keyword">use</span> <span class="word">RDF::Query</span><span class="structure">;</span><br /><br /><span class="comment"># Create the triple.<br />#<br /></span><span class="keyword">my</span> <span class="symbol">$triple</span> <span class="operator">=</span> <span class="word">statement</span><span class="structure">(</span><br /> <span class="word">iri</span><span class="structure">(</span><span class="double">"http://tobyinkster.co.uk/#i"</span><span class="structure">)</span><span class="operator">,</span><br /> <span class="word">iri</span><span class="structure">(</span><span class="double">"http://xmlns.com/foaf/0.1/name"</span><span class="structure">)</span><span class="operator">,</span><br /> <span class="word">literal</span><span class="structure">(</span><span class="double">"Toby"</span><span class="structure">)</span><span class="operator">,</span><br /><span class="structure">);</span><br /><br /><span class="comment"># Let's take a look at that.<br />#<br /></span><span class="word">say</span> <span class="symbol">$triple</span><span class="operator">-></span><span class="word">as_string</span><span class="structure">;</span><br /><br /><span class="comment"># Create an in-memory triple database for querying...<br />#<br /></span><span class="keyword">my</span> <span class="symbol">$model</span> <span class="operator">=</span> <span class="word">RDF::Trine::Model</span><span class="operator">-></span><span class="word">new</span><span class="structure">;</span><br /><br /><span class="comment"># ... and add our triple.<br />#<br /></span><span class="symbol">$model</span><span class="operator">-></span><span class="word">add_statement</span><span class="structure">(</span><span class="symbol">$triple</span><span class="structure">);</span><br /><br /><span class="comment"># I told you it was SQL-like...<br />#<br /></span><span class="keyword">my</span> <span class="symbol">$query</span> <span class="operator">=</span> <span class="word">RDF::Query</span><span class="operator">-></span><span class="word">new</span><span class="structure">(</span><span class="heredoc"><<'SPARQL'</span><span class="structure">);</span><br /><span class="heredoc_content">SELECT $name<br />WHERE {<br /> <http://tobyinkster.co.uk/#i><br /> <http://xmlns.com/foaf/0.1/name><br /> $name .<br />}<br /></span><span class="heredoc_terminator">SPARQL<br /></span><br /><span class="comment"># Run the query against the database<br />#<br /></span><span class="keyword">my</span> <span class="symbol">$results</span> <span class="operator">=</span> <span class="symbol">$query</span><span class="operator">-></span><span class="word">execute</span><span class="structure">(</span><span class="symbol">$model</span><span class="structure">);</span><br /><br /><span class="comment"># This is an iterator, a bit like DBI results<br />#<br /></span><span class="keyword">while</span> <span class="structure">(</span><span class="keyword">my</span> <span class="symbol">$row</span> <span class="operator">=</span> <span class="symbol">$results</span><span class="operator">-></span><span class="word">next</span><span class="structure">)</span> <span class="structure">{</span><br /> <span class="word">say</span> <span class="double">"GOT "</span><span class="operator">,</span> <span class="symbol">$row</span><span class="operator">-></span><span class="structure">{</span><span class="word">name</span><span class="structure">}</span><span class="operator">-></span><span class="word">value</span><span class="structure">;</span><br /><span class="structure">}</span></code></pre>
<h3 id="What-is-it-Good-For">What is it Good For?</h3>
<p>RDF is a good way of representing highly heterogeneous data.</p>
<p>Imagine that you're storing the following data in an SQL database:</p>
<ul>
<li><p>Alice is called Alice</p>
</li>
<li><p>Bob is called Bob</p>
</li>
<li><p>Alice is married to Bob</p>
</li>
</ul>
<p>Easy peasy, right? You can probably already envisage the tables you'd use. Now let's store some more data:</p>
<ul>
<li><p>Alice takes a drug called Foo-lin.</p>
</li>
<li><p>Foo-lin is manufactured by ACME Corp.</p>
</li>
<li><p>Foo-lin is a variety of insulin.</p>
</li>
<li><p>Bob likes "Fight Club".</p>
</li>
<li><p>"Fight Club" is a film.</p>
</li>
<li><p>"Fight Club" stars Brad Pitt.</p>
</li>
<li><p>Brad Pitt is called Brad.</p>
</li>
</ul>
<p>Ten facts, and already the tables are spiralling out of control. Using RDF all that is just ten triples.</p>
<p>RDF allows you to model messy data; allows you to merge data from different data sources which have different models of the world. As long as two RDF data sources agree on URIs to identify things with, merging two databases can be as easy as concatenating two lists of triples.</p>
<h3 id="All-You-Can-Eat-Data-Buffet">All You Can Eat Data Buffet</h3>
<p>There are over <a href="http://wifo5-03.informatik.uni-mannheim.de/lodcloud/state/">30 billion RDF triples</a> out there on the Internet. Because RDF uses URIs to identify things, and different data sources can use each others' URIs, this forms a loosely interlinked "web of data". (Just as web pages link to each other to form a "web of documents".)</p>
<p>DBpedia, a project to lift Wikipedia's information into RDF, might indicate the location for a particular World War II battle using a URI from the GeoNames project. Status.net, an open source microblogging platform, uses the same predicate URIs to describe people as LiveJournal.</p>
<p>I won't say that it's <i>easy</i> to use the entire web of data as a massive distributed database, but it's beginning to look possible.</p>
<p>For our conclusion, let's focus on just one of those linked open data projects: DBpedia.</p>
<h3 id="The-SPARQL-Protocol">The SPARQL Protocol</h3>
<p>(Yes, that sounds like a new Dan Brown book.)</p>
<p>As well as being an SQL-like query language, SPARQL also includes a RESTful HTTP protocol for querying remote RDF data stores.</p>
<p>DBpedia's SPARQL endpoint is <a href="http://dbpedia.org/sparql">http://dbpedia.org/sparql</a>. Let's query it using <a href="https://metacpan.org/module/RDF::Query::Client">RDF::Query::Client</a>.</p>
<pre><code class="code-listing"><span class="keyword">use</span> <span class="float">5.010</span><span class="structure">;</span><br /><span class="keyword">use</span> <span class="pragma">strict</span><span class="structure">;</span><br /><span class="keyword">use</span> <span class="word">RDF::Query::Client</span><span class="structure">;</span><br /><span class="keyword">use</span> <span class="pragma">constant</span> <span class="word">DBPEDIA</span> <span class="operator">=></span> <span class="single">'http://dbpedia.org/sparql'</span><span class="structure">;</span><br /><br /><span class="comment"># Notice the "PREFIX" keyword in SPARQL can be used to set up<br /># abbreviations for long URIs.<br />#<br /></span><span class="keyword">my</span> <span class="symbol">$query</span> <span class="operator">=</span> <span class="word">RDF::Query::Client</span><span class="operator">-></span><span class="word">new</span><span class="structure">(</span><span class="heredoc"><<'SPARQL'</span><span class="structure">);</span><br /><span class="heredoc_content">PREFIX category: <http://dbpedia.org/resource/Category:><br />PREFIX dc: <http://purl.org/dc/terms/><br />PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#><br />SELECT $title<br />WHERE {<br /> $resource dc:subject category:Christmas_songs .<br /> $resource dc:subject category:Vocal_duets .<br /> $resource rdfs:label $title .<br /> FILTER ( langMatches(lang($title), "en") )<br />}<br /></span><span class="heredoc_terminator">SPARQL<br /></span><br /><span class="keyword">my</span> <span class="symbol">$results</span> <span class="operator">=</span> <span class="symbol">$query</span><span class="operator">-></span><span class="word">execute</span><span class="structure">(</span> <span class="word">DBPEDIA</span> <span class="structure">);</span><br /><span class="keyword">while</span> <span class="structure">(</span><span class="keyword">my</span> <span class="symbol">$row</span> <span class="operator">=</span> <span class="symbol">$results</span><span class="operator">-></span><span class="word">next</span><span class="structure">)</span> <span class="structure">{</span><br /> <span class="word">say</span> <span class="double">"GOT "</span><span class="operator">,</span> <span class="symbol">$row</span><span class="operator">-></span><span class="structure">{</span><span class="word">title</span><span class="structure">}</span><span class="operator">-></span><span class="word">value</span><span class="structure">;</span><br /><span class="structure">}</span></code></pre>
<p>This gives me a list of five songs; much easier to narrow down the song I was looking for. Oh yes, that was it...</p>
<h2 id="See-Also">See Also</h2>
<ul>
<li><p><a href="https://metacpan.org/module/RDF::Trine">RDF::Trine</a></p>
</li>
<li><p><a href="https://metacpan.org/module/RDF::Query">RDF::Query</a></p>
</li>
<li><p><a href="https://metacpan.org/module/RDF::Query::Client">RDF::Query::Client</a></p>
</li>
</ul>
</div>2013-12-01T00:00:00ZToby Inkster