<?xml version="1.0" encoding="us-ascii"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>RJBS Advent Calendar 2009</title><id>http://advent.rjbs.manxome.org/2009/</id><link href="http://advent.rjbs.manxome.org/2009/atom.xml" rel="self"/><updated>2011-10-07T19:52:52-04:00</updated><author><name>Ricardo Signes</name></author><generator uri="http://search.cpan.org/dist/XML-Atom-SimpleFeed/" version="0.86">XML::Atom::SimpleFeed</generator><entry><title>One Last Present, All Boxed Up</title><link href="http://advent.rjbs.manxome.org/2009/2009-12-26.html"/><id>http://advent.rjbs.manxome.org/2009/2009-12-26.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h2 id=&#34;Its-Boxing-Day-&#34;&gt;It&#38;#39;s Boxing Day!&lt;/h2&gt;

&lt;p&gt;Boxing day, the day after Christmas, is so called because it is the time of year when you take all the gifts you received &lt;i&gt;and liked&lt;/i&gt; and put them in a box to keep. The rest you give to someone who couldn&#38;#39;t be bothered to show up for Christmas with the rest of the family. It is also known as St. Stephen&#38;#39;s day, in honor of my brother.&lt;/p&gt;

&lt;h2 id=&#34;Perl-Perl-is-in-the-box-&#34;&gt;Perl! Perl is in the box!&lt;/h2&gt;

&lt;p&gt;I maintain a box of my favorite presents from the CPAN. Some of them are my own donations, already mentioned this month. Plenty of them were shared with the CPAN by other contributors. This box is &lt;a href=&#34;https://metacpan.org/module/Task::BeLike::RJBS&#34;&gt;Task::BeLike::RJBS&lt;/a&gt;. It&#38;#39;s a &lt;a href=&#34;https://metacpan.org/module/Task&#34;&gt;Task&lt;/a&gt; distribution, which means that it doesn&#38;#39;t actually do anything on its own. It&#38;#39;s just a pile of prerequisites. Instead of installing each one, you can install the task and the rest are installed for you.&lt;/p&gt;

&lt;p&gt;When I set up a new workstation, the first thing I do is compile my own recent &lt;i&gt;perl&lt;/i&gt; to avoid any weird vendor packaging issues. The next thing I do is install Task::BeLike::RJBS. Whether or not &lt;i&gt;you&lt;/i&gt; want to be like me, I&#38;#39;m stuck with it, so I try to do it as efficiently as possible.&lt;/p&gt;

&lt;p&gt;If you&#38;#39;re interested in the modules that I consider essential to getting work done, check out the task and its contents.&lt;/p&gt;

&lt;h2 id=&#34;Building-Your-Own-Box&#34;&gt;Building Your Own Box&lt;/h2&gt;

&lt;p&gt;Task::BeLike::RJBS is built with Dist::Zilla -- specifically with &lt;a href=&#34;https://metacpan.org/module/Dist::Zilla::Plugin::TaskWeaver&#34;&gt;Dist::Zilla::Plugin::TaskWeaver&lt;/a&gt;, a plugin for building tasks. To use TaskWeaver, you just write a module with some Pod like this:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;=pkgroup Simple Modules (Wednesdays)&lt;br /&gt;&lt;br /&gt;=pkg Number::Nary 0.108 has robust unique-decodability detection&lt;br /&gt;&lt;br /&gt;=pkg Data::Section&lt;br /&gt;&lt;br /&gt;=pkg String::RewritePrefix 0.005 provides &#38;quot;rewrite&#38;quot; export&lt;br /&gt;&lt;br /&gt;=pkg Sort::ByExample&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;You&#38;#39;ll get output Pod like this:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;br /&gt;15:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;synStatement&#34;&gt;=head1&lt;/span&gt;&lt;span class=&#34;synConstant&#34;&gt; TASK CONTENTS&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;=head2&lt;/span&gt;&lt;span class=&#34;synConstant&#34;&gt; Simple Modules (Wednesdays)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;=head3&lt;/span&gt;&lt;span class=&#34;synConstant&#34;&gt; Number::Nary 0.108&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Version 1.08 is required because: has robust unique-decodability detection&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;=head3&lt;/span&gt;&lt;span class=&#34;synConstant&#34;&gt; Data Section&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;=head3&lt;/span&gt;&lt;span class=&#34;synConstant&#34;&gt; String::RewritePrefix 0.005&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Version 0.005 is required because: provides &#38;quot;rewrite&#38;quot; export&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;=head3&lt;/span&gt;&lt;span class=&#34;synConstant&#34;&gt; Sort::ByExample&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;You&#38;#39;ll also get all those packages, with the versions given (if any) listed as prerequisites, so installing your task will get all those prerequisites as well.&lt;/p&gt;

&lt;p&gt;Have fun, make some bundles, share, and enjoy.&lt;/p&gt;

&lt;h2 id=&#34;See-Also&#34;&gt;See Also&lt;/h2&gt;

&lt;ul&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Task::BeLike::RJBS&#34;&gt;Task::BeLike::RJBS&lt;/a&gt; - my box&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Task::BeLike::BINGOS&#34;&gt;Task::BeLike::BINGOS&lt;/a&gt;, &lt;a href=&#34;https://metacpan.org/module/Task::BeLike::hanekomu&#34;&gt;Task::BeLike::hanekomu&lt;/a&gt;, &lt;a href=&#34;https://metacpan.org/module/Task::BeLike::YANICK&#34;&gt;Task::BeLike::YANICK&lt;/a&gt; - others like it&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Bundle::Ovid&#34;&gt;Bundle::Ovid&lt;/a&gt;, &lt;a href=&#34;https://metacpan.org/module/Bundle::Theory&#34;&gt;Bundle::Theory&lt;/a&gt;, and many more&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Dist::Zilla::Plugin::TaskWeaver&#34;&gt;Dist::Zilla::Plugin::TaskWeaver&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;</summary><updated>2009-12-26T00:00:00-05:00</updated><category term="Perl"/><category term="RJBS"/></entry><entry><title>You Can Keep the Calendar</title><link href="http://advent.rjbs.manxome.org/2009/2009-12-25.html"/><id>http://advent.rjbs.manxome.org/2009/2009-12-25.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h2 id=&#34;Merry-Christmas-Advent-is-over.&#34;&gt;Merry Christmas! Advent is over.&lt;/h2&gt;

&lt;p&gt;It&#38;#39;s a common misconception that Advent calendars include today, Christmas Day, but traditionally they stop yesterday on the 24th. Still, who am I to argue with the Perl Advent Calendar traditions? Here&#38;#39;s my compromise: today, I&#38;#39;ll just give you the calendar itself: &lt;a href=&#34;https://metacpan.org/module/WWW::AdventCalendar&#34;&gt;WWW::AdventCalendar&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&#34;In-which-our-author-fails-to-steal-from-his-peers...&#34;&gt;In which our author fails to steal from his peers...&lt;/h2&gt;

&lt;p&gt;On November 18th, I decided it might be fun to write a series of Advent Calendar articles for just my own code, published along side the other calendars. I asked one or two people if they thought this was a terrible idea, and they said it was not, so I decided I&#38;#39;d better get to work as quickly as possible. That means not worrying about writing any software to produce the article, but just to write articles. I would steal someone else&#38;#39;s code!&lt;/p&gt;

&lt;p&gt;First, I looked for whatever powered the &lt;a href=&#34;http://perladvent.org&#34;&gt;Perl Advent Calendar&lt;/a&gt;. I figured with new CSS it would be fine. I found &lt;a href=&#34;https://metacpan.org/module/Pod::Advent&#34;&gt;Pod::Advent&lt;/a&gt;, but something about it made me decide to keep looking. I have no idea what anymore. Then I went to &lt;a href=&#34;http://dev.catalyst.perl.org/repos/Catalyst/trunk/examples/CatalystAdvent&#34;&gt;CatalystAdvent&lt;/a&gt;, which powers the &lt;a href=&#34;http://www.catalystframework.org/calendar&#34;&gt;Catalyst Advent Calendar&lt;/a&gt;. I liked its look out of the box, so I started to install it, but it needed things no longer on CPAN. I hacked around that and then started to wonder whether I wouldn&#38;#39;t be happier just publishing static files. Why? Who knows.&lt;/p&gt;

&lt;p&gt;I try pretty hard not to re-invent solutions to solved problems, and (believe it or not) I succeed more often than not in quashing my urge to rewrite perfectly good systems. Here, though, it seemed like I&#38;#39;d be happier with something I wrote for myself. In the end, I think I was.&lt;/p&gt;

&lt;p&gt;Anyway, I mostly stole the CSS and templates from CatalystAdvent, and I&#38;#39;m pretty happy that, too.&lt;/p&gt;

&lt;h2 id=&#34;WWW::AdventCalendar&#34;&gt;WWW::AdventCalendar&lt;/h2&gt;

&lt;p&gt;WWW::AdventCalendar is, as you might expect, pretty stupidly simple. Right now it only works for Advent, although I&#38;#39;d like to make it better at doing longer spans of time. Could I use a &#38;quot;real&#38;quot; blogging system for this? Yes. Am I likely to? No.&lt;/p&gt;

&lt;p&gt;There&#38;#39;s just a program to run that looks for your articles, decides how many to publish, and writes out the article HTML, the index, the Atom feed, and a few other files.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  ~/code/advent$ ./bin/advcal -c advcal.ini --today 2009-12-08
  processing article for 2009-12-01...
  processing article for 2009-12-02...
  processing article for 2009-12-03...
  processing article for 2009-12-04...
  processing article for 2009-12-05...
  processing article for 2009-12-06...
  processing article for 2009-12-07...
  processing article for 2009-12-08...&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The input files are Pod documents where the non-pod content is an email document. Alternately, the input files are email documents where the body is Pod. &lt;i&gt;What??&lt;/i&gt; Well:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;synIdentifier&#34;&gt;Title:&lt;/span&gt;   You can take the calendar with you when you go...&lt;br /&gt;&lt;span class=&#34;synIdentifier&#34;&gt;Package:&lt;/span&gt; WWW::AdventCalendar&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;=head1&lt;/span&gt;&lt;span class=&#34;synConstant&#34;&gt; Merry Christmas!  Advent is over.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It&#39;s a common misconception that Advent calendars include today, Christmas&lt;br /&gt;Day,&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;I originally made the body markup type pluggable, but then I remembered how much I love Pod and I dropped that feature. This let me use one set of syntax semantics for everything. For example, I could write:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;synStatement&#34;&gt;=begin&lt;/span&gt; &lt;span class=&#34;synIdentifier&#34;&gt;vim&lt;/span&gt; lisp&lt;br /&gt;&lt;br /&gt;(format nil &#38;quot;~4,&#39;0d-~2,&#39;0d-~2,&#39;0d&#38;quot; 2005 6 10) ; ==&#38;gt; 2005-06-10&lt;br /&gt;(format nil &#38;quot;~:(~a~)&#38;quot; &#38;quot;tHe Quick BROWN foX&#38;quot;)  ; ==&#38;gt; &#38;quot;The Quick Brown Fox&#38;quot;&lt;br /&gt;(format nil &#38;quot;~:r&#38;quot; 1234)  ; ==&#38;gt; &#38;quot;one thousand two hundred thirty-fourth&#38;quot;&lt;br /&gt;(format nil &#38;quot;~:&lt;span class=&#34;synIdentifier&#34;&gt;@r&lt;/span&gt;&#38;quot; 1234) ; ==&#38;gt; &#38;quot;MCCXXXIIII&#38;quot;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;=end&lt;/span&gt; &lt;span class=&#34;synIdentifier&#34;&gt;vim&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;...and get some nicely colorized Lisp code. (The color scheme, by the way, is based on &lt;a href=&#34;http://www.vim.org/scripts/script.php?script_id=260&#34;&gt;my Vim colorscheme&lt;/a&gt;. The code uses &lt;a href=&#34;https://metacpan.org/module/Text::VimColor&#34;&gt;Vim&lt;/a&gt; (the editor) to colorize my code, but for Perl I decided to use &lt;a href=&#34;https://metacpan.org/module/PPI::HTML&#34;&gt;PPI::HTML&lt;/a&gt;, which was faster and had a bit more control. I could just write &lt;code&gt;=begin perl&lt;/code&gt; but that got tedious, so I added another transformation so that by writing...&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;but that got tedious, so I added another transformation so that by writing...&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;#!perl&lt;br /&gt;&#38;nbsp;&#38;nbsp;my $x = { foo =&#38;gt; 10 };&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;The indented block&#38;#39;s shebang would be noticed, and instead I&#38;#39;d get:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$x&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;foo&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;10&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;h2 id=&#34;The-Pod-Transformers&#34;&gt;The Pod Transformers&lt;/h2&gt;

&lt;h3 id=&#34;Syntax-Highlighting&#34;&gt;Syntax Highlighting&lt;/h3&gt;

&lt;p&gt;So, those bits of code are the useful bits, unless you really want to run an advent calendar just like me. For now they&#38;#39;re being released with WWW::AdventCalendar, because they&#38;#39;re just a bit too hacky to be for general use yet, I think. Still, here&#38;#39;s what they do:&lt;/p&gt;

&lt;p&gt;I&#38;#39;m using &lt;a href=&#34;https://metacpan.org/module/Pod::Simple::XHTML&#34;&gt;Pod::Simple::XHTML&lt;/a&gt; to convert from Pod to HTML. I&#38;#39;d started with &lt;a href=&#34;https://metacpan.org/module/Pod::Xhtml&#34;&gt;Pod::Xhtml&lt;/a&gt;, but it was buggy and unmaintained. Pod::Simple, on the other hand, is buggy and maintained. Or, at least, it&#38;#39;s maintained. It can be hard to tell whether it&#38;#39;s buggy or just incomprehensible. Anyway, I can have a &lt;code&gt;=begin html&lt;/code&gt; block that lets me provide literal XHTML rather than Pod. This is perfect for providing marked up, colorized code blocks. All I had to do was get those XHTML blocks produced before Pod::Simple::XHTML did its thing.&lt;/p&gt;

&lt;p&gt;Obviously, this was a job for &lt;a href=&#34;https://metacpan.org/module/Pod::Elemental&#34;&gt;Pod::Elemental&lt;/a&gt;, the engine behind &lt;a href=&#34;https://metacpan.org/module/Pod::Weaver&#34;&gt;Pod::Weaver&lt;/a&gt;! I wrote two libraries, &lt;a href=&#34;https://metacpan.org/module/Pod::Elemental::Transformer::PPIHTML&#34;&gt;Pod::Elemental::Transformer::PPIHTML&lt;/a&gt; and &lt;a href=&#34;https://metacpan.org/module/Pod::Elemental::Transformer::VimHTML&#34;&gt;Pod::Elemental::Transformer::VimHTML&lt;/a&gt;, both of which composed the &lt;a href=&#34;https://metacpan.org/module/Pod::Elemental::Transformer::SynHi&#34;&gt;Pod::Elemental::Transformer::SynHi&lt;/a&gt; role. All that left for the transformers to do was have a method that rewrote plain text into marked up HTML.&lt;/p&gt;

&lt;p&gt;I&#38;#39;m hoping that these will make it easy to write other syntax highlighting engines for Pod-to-HTML conversion in the future -- possibly engines that don&#38;#39;t require spawning Vim instances!&lt;/p&gt;

&lt;h3 id=&#34;Shorthand-Lists&#34;&gt;Shorthand Lists&lt;/h3&gt;

&lt;p&gt;I mentioned using &lt;a href=&#34;https://metacpan.org/module/Pod::WikiDoc&#34;&gt;Pod::WikiDoc&lt;/a&gt; syntax for lists when talking about &lt;a href=&#34;http://advent.rjbs.manxome.org/2009-12-18.html&#34;&gt;Pod::Weaver&lt;/a&gt;. WikiDoc regions are really powerful, and make writing lists really easy, but they do much more than lists and I didn&#38;#39;t &lt;i&gt;want&lt;/i&gt; them to! For example, look at this region:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;synStatement&#34;&gt;=for&lt;/span&gt; &lt;span class=&#34;synIdentifier&#34;&gt;wikidoc&lt;/span&gt;&lt;br /&gt;* &lt;span class=&#34;synIdentifier&#34;&gt;L&#38;lt;Acme::ProgressBar&#38;gt;&lt;/span&gt;&lt;br /&gt;* &lt;span class=&#34;synIdentifier&#34;&gt;L&#38;lt;Games::Nintendo::Mario&#38;gt;&lt;/span&gt; - it&#39;s &lt;span class=&#34;synIdentifier&#34;&gt;I&#38;lt;super&#38;gt;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;It doesn&#38;#39;t do what I want, because it doesn&#38;#39;t expect formatting codes (things like &lt;code&gt;L&#38;lt;...&#38;gt;&lt;/code&gt;. What I have to write is:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;synStatement&#34;&gt;=for&lt;/span&gt; &lt;span class=&#34;synIdentifier&#34;&gt;wikidoc&lt;/span&gt;&lt;br /&gt;* [Acme::ProgressBar]&lt;br /&gt;* [Games::Nintendo::Mario] - it&#39;s ~super~&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;This isn&#38;#39;t so bad, but it&#38;#39;s not what I&#38;#39;m using in the rest of the document! To get lists that were as easy to write as those in Pod::WikiDoc, but still Pod, I wrote &lt;a href=&#34;https://metacpan.org/module/Pod::Elemental::Transformer::List&#34;&gt;Pod::Elemental::Transformer::List&lt;/a&gt;, which lets me write&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;synStatement&#34;&gt;=for&lt;/span&gt; &lt;span class=&#34;synIdentifier&#34;&gt;:list&lt;/span&gt;&lt;br /&gt;* &lt;span class=&#34;synIdentifier&#34;&gt;L&#38;lt;Acme::ProgressBar&#38;gt;&lt;/span&gt;&lt;br /&gt;* &lt;span class=&#34;synIdentifier&#34;&gt;L&#38;lt;Games::Nintendo::Mario&#38;gt;&lt;/span&gt; - it&#39;s &lt;span class=&#34;synIdentifier&#34;&gt;I&#38;lt;super&#38;gt;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;The colon in &lt;code&gt;:list&lt;/code&gt; says that the contents of the region are really Pod (even though they&#38;#39;re re-interpreted into more Pod by the transformer. It&#38;#39;s easy to write nested lists, too:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;br /&gt;15:&#38;nbsp;&lt;br /&gt;16:&#38;nbsp;&lt;br /&gt;17:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;synStatement&#34;&gt;=begin&lt;/span&gt; &lt;span class=&#34;synIdentifier&#34;&gt;:list&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;* glossary&lt;br /&gt;&lt;br /&gt;These words are useful to know:&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;=for&lt;/span&gt; &lt;span class=&#34;synIdentifier&#34;&gt;:list&lt;/span&gt;&lt;br /&gt;= advent&lt;br /&gt;the four weeks leading up to Christmas&lt;br /&gt;= noel&lt;br /&gt;the two weeks beginning on Christmas eve&lt;br /&gt;&lt;br /&gt;* glossy&lt;br /&gt;&lt;br /&gt;These words mean shiny: ...&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;=end&lt;/span&gt; &lt;span class=&#34;synIdentifier&#34;&gt;list&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;h2 id=&#34;Same-Code-Next-Year&#34;&gt;Same Code Next Year&lt;/h2&gt;

&lt;p&gt;I&#38;#39;ll definitely be using this code again next year... if I decide to try to repeat this undertaking, which is a big if. I&#38;#39;m hoping to make the syntax stuff a useful tool for other projects, and I really want to make the advent calendar work across arbitrary date ranges. Still, it was fun to write, easy to use, and I hope somebody else gets some kind of benefit from it in the future.&lt;/p&gt;

&lt;p&gt;Until then... Merry Christmas!&lt;/p&gt;

&lt;h2 id=&#34;See-Also&#34;&gt;See Also&lt;/h2&gt;

&lt;ul&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/WWW::AdventCalendar&#34;&gt;WWW::AdventCalendar&lt;/a&gt; - the calendar site generating code&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pod-handling code produced to power the calendar:&lt;/p&gt;

&lt;ul&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Pod::Elemental::Transformer::List&#34;&gt;Pod::Elemental::Transformer::List&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Pod::Elemental::Transformer::SynHi&#34;&gt;Pod::Elemental::Transformer::SynHi&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Pod::Elemental::Transformer::PPIHTML&#34;&gt;Pod::Elemental::Transformer::PPIHTML&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Pod::Elemental::Transformer::VimHTML&#34;&gt;Pod::Elemental::Transformer::VimHTML&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Pod::Advent&#34;&gt;Pod::Advent&lt;/a&gt; - the Pod formatter used by &lt;a href=&#34;http://perladvent.org&#34;&gt;http://perladvent.org&lt;/a&gt; (not me)&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;http://dev.catalyst.perl.org/repos/Catalyst/trunk/examples/CatalystAdvent/&#34;&gt;CatalystAdvent&lt;/a&gt; - the Catalyst Advent Calendar, whose CSS I stole&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Text::VimColor&#34;&gt;Text::VimColor&lt;/a&gt; - colorize any syntax type that Vim understands&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/PPI::HTML&#34;&gt;PPI::HTML&lt;/a&gt; - turn Perl into syntax marked HTML with &lt;a href=&#34;https://metacpan.org/module/PPI&#34;&gt;PPI&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Pod::Simple&#34;&gt;Pod::Simple&lt;/a&gt; - the most commonly-used Pod parser&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;</summary><updated>2009-12-25T00:00:00-05:00</updated><category term="Perl"/><category term="RJBS"/></entry><entry><title>Sending Email Simply</title><link href="http://advent.rjbs.manxome.org/2009/2009-12-24.html"/><id>http://advent.rjbs.manxome.org/2009/2009-12-24.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h2 id=&#34;The-Biggest-Box-Under-the-Tree&#34;&gt;The Biggest Box Under the Tree&lt;/h2&gt;

&lt;p&gt;Of everything I did in 2009, I think Email::Sender is the most important and the one I most hope to see adopted. For better or worse, I often found myself looked at as &#38;quot;that guy who does the email code,&#38;quot; and people ask me what library they should use for this or that. I end up shrugging, most of the time, and saying, &#38;quot;What I look for in an email module is not the same as what you will care about. I&#38;#39;m a weirdo. I have very peculiar needs.&#38;quot;&lt;/p&gt;

&lt;p&gt;Email::Sender is not like that. If you are going to send email from any code that matters, you should use Email::Sender. Let&#38;#39;s see why.&lt;/p&gt;

&lt;h2 id=&#34;Sending-Email-Simply&#34;&gt;Sending Email Simply&lt;/h2&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Email::Sender::Simple&lt;/span&gt; &lt;span class=&#34;words&#34;&gt;qw(sendmail)&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;sendmail&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$email&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;That&#38;#39;s it. For most values that you&#38;#39;re likely to throw into &lt;code&gt;$email&lt;/code&gt;, that will work. Either it will be delivered for all recipients, or it will throw an exception. It will decide whether to use &lt;i&gt;sendmail&lt;/i&gt; or SMTP based on your operating system and the availability of the &lt;i&gt;sendmail&lt;/i&gt; program. It will decide on the envelope sender and recipient based on the message headers. If you don&#38;#39;t know what an envelope is, you don&#38;#39;t have to. It will do what you expect.&lt;/p&gt;

&lt;p&gt;If you &lt;i&gt;do&lt;/i&gt; know what the envelope is, you know how important it is to be able to control it. It lets you manage bounces, perform BCC or blind distribution list, and do all sorts of other really important things. It&#38;#39;s easy:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;word&#34;&gt;sendmail&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$email&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;@recipients&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$sender&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;The success value returned or the failure exception thrown both can be inspected for more information, but that&#38;#39;s rarely useful for common cases; you just want to know whether it worked or not.&lt;/p&gt;

&lt;h2 id=&#34;Specifying-a-Transport&#34;&gt;Specifying a Transport&lt;/h2&gt;

&lt;p&gt;Normally, Email::Sender::Simple can pick what transport to use for you. You can always specify one by hand, though.&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;br /&gt;15:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$transport&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Email::Sender::Transport::SMTP&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;({&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;host&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;smtp.pobox.com&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;ssl&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;sasl_username&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$username&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;sasl_password&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$password&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;sendmail&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$email&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$sender&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;to&lt;/span&gt;   &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;@recipients&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;transport&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$transport&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;Now we&#38;#39;ll send that message through the configured SMTP relay. This can be useful for unusual cases, but the same kind of feature can be vastly more useful in testing your code. You can override the transport with the environment (&lt;code&gt;%ENV&lt;/code&gt;), and that will affect every use of Email::Sender::Simple, whether or not an override is given in the call to &lt;code&gt;sendmail&lt;/code&gt; itself. That means you can very easily test every email your program will send like this:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;symbol&#34;&gt;$ENV&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;EMAIL_SENDER_TRANSPORT&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Test&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;test_app&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;MyAppCmd&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;sendreports&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@args&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;]);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@deliveries&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Email::Sender::Simple&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;default_transport&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;deliveries&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# ...and now we inspect the mail we would have sent out...&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;Setting that environment variable behaves as if you&#38;#39;d created a single instance of Email::Sender::Transport::Test and passed it as the &lt;code&gt;transport&lt;/code&gt; parameter for every call to &lt;code&gt;sendmail&lt;/code&gt; everywhere.&lt;/p&gt;

&lt;p&gt;This works very well for testing things. I have &lt;i&gt;many times&lt;/i&gt; turned up unexpected emails from some deep subsystem by using this. Sometimes they&#38;#39;ve been reports of encountered but handled exceptions going to the admin staff -- so by consistently testing all the email we&#38;#39;d send, I could find all kinds of weird problems.&lt;/p&gt;

&lt;p&gt;This is great for those tests, but lots of our tests fork. Once our test process forks, storing all its deliveries in what is effectively a global variable, scoped &lt;i&gt;per process&lt;/i&gt;, isn&#38;#39;t very useful. Instead, we test like this:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;symbol&#34;&gt;$ENV&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;EMAIL_SENDER_TRANSPORT&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;SQLite&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;test_app&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;MyAppCmd&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;sendreports&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@args&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;]);&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# here there be forks&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$rows&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Email::Sender::Simple&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;default_transport&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;dbh&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;selectall_arrayref&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;  # ...&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# ...and now we inspect the mail we would have sent out...&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;We&#38;#39;ve trivially collected all the mail sent by any forked child -- &lt;i&gt;and&lt;/i&gt; by any spawned subprocess that uses Email::Sender.&lt;/p&gt;

&lt;h2 id=&#34;More-Testing-Tools&#34;&gt;More Testing Tools&lt;/h2&gt;

&lt;p&gt;Want to run your program and look at the results yourself? You can set the environment to send all the output mail to your mailbox. You can send it all to an &lt;i&gt;mbox&lt;/i&gt; or &lt;i&gt;Maildir&lt;/i&gt; on disk. You can route it all to &lt;i&gt;/dev/null&lt;/i&gt; or to the screen. These things are all easy. Really, they&#38;#39;re trivial. You just set the &lt;code&gt;EMAIL_SENDER_TRANSPORT&lt;/code&gt; environment variable and exactly what you want happens.&lt;/p&gt;

&lt;p&gt;What&#38;#39;s less trivial -- but immensely powerful for testing -- is the Failable transport wrapper.&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;br /&gt;15:&#38;nbsp;&lt;br /&gt;16:&#38;nbsp;&lt;br /&gt;17:&#38;nbsp;&lt;br /&gt;18:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$sender&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Email::Sender::Transport::Test&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$failer&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Email::Sender::Transport::Failable&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;({&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;transport&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$sender&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$i&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$failer&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;fail_if&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;failing half of all mail to test&#38;quot;&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$i&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;++&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$result&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;eval&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$failer&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;send&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$message&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;words&#34;&gt;qw(ok@ok.ok)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;})&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;ok&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$result&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;success&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;eval&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$result&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$failer&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;send&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$message&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;words&#34;&gt;qw(ok@ok.ok)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;})&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;isa_ok&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;magic&#34;&gt;$@&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Email::Sender::Failure&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;we died&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;See what we did there? We told our program to send mail through a transport that is guaranteed to fail every other delivery. We could also have failed on deliveries to specific domains, over a given size, or almost anything else. This makes it easy to test how our program behaves when its email-sending routines fail, which is an often ignored code branch -- because it&#38;#39;s traditionally been so hard to test. Making all your mail go through that kind of transport is easy: you throw the failure conditions in a package and set your environment variables accordingly.&lt;/p&gt;

&lt;h2 id=&#34;Seriously-Use-It&#34;&gt;Seriously, Use It&lt;/h2&gt;

&lt;p&gt;Because of the global effects of the testing environment settings (and other related tools not seen here), the more code that uses Email::Sender::Simple, the more testable everything becomes. It&#38;#39;s easy to extend to new kinds of transports and messages. Even if you don&#38;#39;t plan on testing your code&#38;#39;s email sending, by using Email::Sender::Simple, you&#38;#39;ll make it possible for anyone else to do so second-hand. That can be your gift to them: an application that&#38;#39;s easier to maintain and test.&lt;/p&gt;

&lt;h2 id=&#34;See-Also&#34;&gt;See Also&lt;/h2&gt;

&lt;ul&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Email::Sender::Manual::QuickStart&#34;&gt;Email::Sender::Manual::QuickStart&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Email::Sender::Simple&#34;&gt;Email::Sender::Simple&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Email::Sender&#34;&gt;Email::Sender&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Email::Sender::Transport::SQLite&#34;&gt;Email::Sender::Transport::SQLite&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;</summary><updated>2009-12-24T00:00:00-05:00</updated><category term="Perl"/><category term="RJBS"/></entry><entry><title>Sorting Automatically, By Hand</title><link href="http://advent.rjbs.manxome.org/2009/2009-12-23.html"/><id>http://advent.rjbs.manxome.org/2009/2009-12-23.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;p&gt;Here&#38;#39;s a nice easy one: sorting stuff by providing a pre-sorted set of data.&lt;/p&gt;

&lt;p&gt;The problem with custom sort functions is that sometimes it&#38;#39;s stupidly easy to explain how you want to sort something to a person, but once you try to explain it to the computer, it becomes a real chore. Here&#38;#39;s an example: we&#38;#39;ve got a bunch of presents to delivery, and usually we deliver them by the destination&#38;#39;s latitude, northerly destinations first, but we have a few VIP users who always get first service. Their presents get delivered first, then everybody else&#38;#39;s.&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Sort::ByExample&lt;/span&gt; &lt;span class=&#34;words&#34;&gt;qw(sbe)&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$sorter&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;sbe&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Klortho the Magnificent&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Mrs. Claus&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Cold Miser&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;xform&lt;/span&gt;    &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;recipient&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;fallback&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;degrees_north&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;&#38;lt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;degrees_north&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;operator&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;submission&lt;/span&gt;    &lt;span class=&#34;operator&#34;&gt;&#38;lt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;submission&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@jobs&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$sorter&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@presents&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;Now all deliveries will be sorted by destination, but presents for our three VIPs will be pulled out of order: first, all of Klortho&#38;#39;s gifts (by submission time), then Mrs. Claus&#38;#39;s, then Cold Miser&#38;#39;s. The &lt;code&gt;xform&lt;/code&gt; callback is used to perform a &lt;a href=&#34;http://en.wikipedia.org/wiki/Schwartzian_transform&#34;&gt;Schwartzian transform&lt;/a&gt;, so that the sort routines will see the recipient&#38;#39;s name rather than the present object. &lt;code&gt;fallback&lt;/code&gt; provides a callback to sort items not sorted by the example, or that have the same position in the example. Note that the &lt;code&gt;fallback&lt;/code&gt; routine looks at the third and fourth elements rather than the first two. These give it access to the value before transformation.&lt;/p&gt;

&lt;p&gt;Finally, you can mark items as &#38;quot;ties&#38;quot; in the example sort by using a hashref as the example, with the values indicating rank. By marking two as having the same value, they&#38;#39;ll get send to the fallback to break the tie:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$sorter&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;sbe&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;Klortho the Magnificent&#39;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;Mrs. Claus&#39;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;Cold Miser&#39;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;Heat Miser&#39;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;xform&lt;/span&gt;    &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;recipient&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;fallback&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;degrees_north&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;&#38;lt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;degrees_north&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;operator&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;submission&lt;/span&gt;    &lt;span class=&#34;operator&#34;&gt;&#38;lt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;submission&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;Sort::ByExample is not intended to be blazing fast, but it should be fairly efficient. It also isn&#38;#39;t &lt;a href=&#34;https://metacpan.org/release/Sort-Maker&#34;&gt;the Swiss Army chainsaw of sorting&lt;/a&gt;. I tried to use that at first before giving up and writing this code.&lt;/p&gt;

&lt;p&gt;Sort::ByExample solves a pretty specific problem, and one that could always be solved by writing just a few more lines of Perl. Still, not having to write those lines is a pretty nice perk that leaves more time for solving more pressing problems.&lt;/p&gt;

&lt;h2 id=&#34;See-Also&#34;&gt;See Also&lt;/h2&gt;

&lt;ul&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Sort::ByExample&#34;&gt;Sort::ByExample&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Sort::Maker&#34;&gt;Sort::Maker&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;</summary><updated>2009-12-23T00:00:00-05:00</updated><category term="Perl"/><category term="RJBS"/></entry><entry><title>Object Marginalia</title><link href="http://advent.rjbs.manxome.org/2009/2009-12-22.html"/><id>http://advent.rjbs.manxome.org/2009/2009-12-22.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h2 id=&#34;Scribbling-Notes-on-an-Object&#34;&gt;Scribbling Notes on an Object&lt;/h2&gt;

&lt;p&gt;Mixin::ExtraFields is hard to summarize, but here&#38;#39;s a whack at it: it&#38;#39;s a system for storing extra data related to an object and creating methods for accessing and altering that state.&lt;/p&gt;

&lt;p&gt;Here&#38;#39;s a really simple example to start with. We have an object that&#38;#39;s a blessed hashref and we want to have a bucket for arbitrary state:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Holiday&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Mixin::ExtraFields&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;-fields&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;moniker&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;tradition&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;driver&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;HashGuts&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;id&lt;/span&gt;  &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;Now we&#38;#39;ve got this bucket for extra values in our Holiday objects which we can use in a few ways, like:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;br /&gt;15:&#38;nbsp;&lt;br /&gt;16:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$holiday&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Holiday&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;Christmas&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$holiday&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;set_tradition&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;colors&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;words&#34;&gt;qw(red green)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;]);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$holiday&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;set_tradition&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;music&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Unbearable&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$holiday&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;set_tradition&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;icon&lt;/span&gt;   &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Santa Claus&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# ...&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;die&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;nothing to eat!&#38;quot;&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;unless&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$holiday&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;exists_tradition&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;food&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$thing&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$holiday&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;get_all_tradition_names&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;stringf&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;The traditional %s for %i is %r.\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$thing&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$holiday&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$holiday&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;get_tradition&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$thing&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;If we use Data::Dumper on our object, we might see something like this:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;symbol&#34;&gt;$VAR1&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;bless&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;id&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Christmas&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;Mixin::ExtraFields::Driver::HashGuts=HASH(0x100864e18)@0&#39;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;foo&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Holiday&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;That horrible key is generated as a place in our object to put a reference to its associated data. That&#38;#39;s only one reference, though. We keep track of data for that object externally, too. That means if we create another object with the same id, it will have the same traditions.&lt;/p&gt;

&lt;p&gt;This means we can also have objects share their extra fields:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Holiday&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Mixin::ExtraFields&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;-fields&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;moniker&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;tradition&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;word&#34;&gt;driver&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;HashGuts&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;-fields&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;moniker&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;month_info&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;driver&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;HashGuts&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;id&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;month&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;Then we can say:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$christmas&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Holiday&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;({&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;id&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Christmas&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;month&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Dec&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$kwanzaa&lt;/span&gt;   &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Holiday&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;({&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;id&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Kwanzaa&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;   &lt;span class=&#34;word&#34;&gt;month&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Dec&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$christmas&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;set_tradition&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;color&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;green&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$christmas&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;get_tradition&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;color&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;   &lt;span class=&#34;comment&#34;&gt;# ==&#38;gt; green&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$kwanzaa&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;get_tradition&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;color&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;     &lt;span class=&#34;comment&#34;&gt;# ==&#38;gt; undef&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$christmas&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;set_month_info&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;length&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;31&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$christmas&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;get_month_info&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;length&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# ==&#38;gt; 31&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$kwanzaa&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;get_month_info&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;length&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;   &lt;span class=&#34;comment&#34;&gt;# ==&#38;gt; 31&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;This can be a quick way to add state to a class you don&#38;#39;t control for the sake of debugging:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Weird::Object&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Mixin::ExtraFields&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;into&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Weird::Object&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# add methods to that class, not this one&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;-fields&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;-prefix&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;__&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;       &lt;span class=&#34;comment&#34;&gt;# make our methods very private&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;driver&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;HashGuts&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;id&lt;/span&gt;      &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;core&#34;&gt;undef&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;      &lt;span class=&#34;comment&#34;&gt;# they have no id-like method; use the refaddr&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;moniker&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;debug&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$object&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Weird::Object&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$object&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;__set_debug&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;brand new&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;h2 id=&#34;Alternate-Sets-of-Methods&#34;&gt;Alternate Sets of Methods&lt;/h2&gt;

&lt;p&gt;It&#38;#39;s easy to provide methods other than the &lt;code&gt;get_extra&lt;/code&gt; and &lt;code&gt;set_extra&lt;/code&gt; (and the half dozen related methods) that we saw above. For example, you could use &lt;a href=&#34;https://metacpan.org/module/Mixin::ExtraFields::Param&#34;&gt;Mixin::ExtraFields::Param&lt;/a&gt; instead and get a method like &lt;a href=&#34;https://metacpan.org/module/CGI&#34;&gt;CGI.pm&lt;/a&gt;&#38;#39;s &lt;code&gt;param&lt;/code&gt;:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;br /&gt;15:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Holiday&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Mixin::ExtraFields::Param&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;-fields&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;moniker&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;tradition&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;driver&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;HashGuts&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# ...&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$holiday&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;tradition&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;color&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;words&#34;&gt;qw(red green)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;food&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;sugarplum&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;tree&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;artificial&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$holiday&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;tradition&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;food&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# ==&#38;gt; sugarplum&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;Or, my favorite, &lt;a href=&#34;https://metacpan.org/module/Mixin::ExtraFields::Hive&#34;&gt;Mixin::ExtraFields::Hive&lt;/a&gt; to get a &lt;a href=&#34;https://metacpan.org/module/Data::Hive&#34;&gt;Data::Hive&lt;/a&gt;-based hierarchical-looking set of methods. The hive makes it look like you have a deep storage structure, but flattens everything out to key/value pairs for storage. It lets us do tricks like this:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;br /&gt;15:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Holiday&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Mixin::ExtraFields::Hive&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;-hive&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;moniker&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;tradition&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;driver&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;HashGuts&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# ...&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$holiday&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;tradition&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;floral&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;tree&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;decoration&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;SET&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;tinsel&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$holiday&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;tradition&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;mood&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;malice&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;DELETE&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$phrase&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$holiday&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;tradition&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;exclamation&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;GET&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;say&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$phrase&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;The fact that Data::Hive takes this apparently structured data and stores it in a flat table is extremely useful, because it keeps to a known quantity the number of methods that alternate drivers have to provide.&lt;/p&gt;

&lt;h2 id=&#34;Alternate-Storage-Drivers&#34;&gt;Alternate Storage Drivers&lt;/h2&gt;

&lt;p&gt;Alternate storage is why we had to keep saying we wanted the HashGuts driver, above. If you wanted, you could write a driver that stored all attributes only in some otherwise inaccessible hashref. You could store attributes by calling another set of methods on the object being altered. There are lots of possibilites, but the one I&#38;#39;ve used the most is storing the table of extra values in a &lt;i&gt;database&lt;/i&gt; table.&lt;/p&gt;

&lt;p&gt;We can decorate objects in our program with these extra fields, storing any set values in a database and retrieving them back from the database. So we can write a class like this:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;br /&gt;15:&#38;nbsp;&lt;br /&gt;16:&#38;nbsp;&lt;br /&gt;17:&#38;nbsp;&lt;br /&gt;18:&#38;nbsp;&lt;br /&gt;19:&#38;nbsp;&lt;br /&gt;20:&#38;nbsp;&lt;br /&gt;21:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Holiday&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Calendar::Schema&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Mixin::ExtraFields::Hive&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;-hive&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;moniker&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;tradition&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;driver&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;class&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;DBIC&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;schema&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Calendar::Schema&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;connect&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;rs_moniker&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;HolidayTradition&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$class&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$holiday&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;@_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;bless&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;id&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$holiday&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$class&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;id&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$self&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;@_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$self&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;It&#38;#39;s about the simplest object you could get, with just one attribute stored in a plain old hash, but then it has this &#38;quot;hive&#38;quot; mixed in that persists things in your &lt;a href=&#34;https://metacpan.org/module/DBIx::Class&#34;&gt;DBIx::Class&lt;/a&gt; database schema. You can turn your little holiday objects into flyweights for accessing (apparently) structured data like:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;word&#34;&gt;printf&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Tonight we will eat %s!&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;Holiday&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;Christmas&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;tradition&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;food&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;dinner&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;entree&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;GET&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;...and we&#38;#39;ll pull that out of the database from the initial load of all our favorite holiday traditions. (To keep things easy for you, the DBIC driver can actually set up the DBIC resultsource for you, so your HolidayTradition source above, need only be two or three lines of code.&lt;/p&gt;

&lt;p&gt;Sometimes you might just want to stick your extra data into an object&#38;#39;s guts, and sometimes you might just want to use a full database layer to map your whole object to SQL, and sometimes you might want a &lt;a href=&#34;https://metacpan.org/module/Moose&#34;&gt;full meta-programming layer&lt;/a&gt; for adding attributes to your classes. Other times, though, you need a quick way to add data to objects and share it correctly without having to think about it too much. That&#38;#39;s exactly when I start mixing this library in.&lt;/p&gt;

&lt;h2 id=&#34;See-Also&#34;&gt;See Also&lt;/h2&gt;

&lt;ul&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Mixin::ExtraFields&#34;&gt;Mixin::ExtraFields&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Mixin::ExtraFields::Param&#34;&gt;Mixin::ExtraFields::Param&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Mixin::ExtraFields::Hive&#34;&gt;Mixin::ExtraFields::Hive&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Data::Hive&#34;&gt;Data::Hive&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Mixin::ExtraFields::Driver::DBIC&#34;&gt;Mixin::ExtraFields::Driver::DBIC&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/DBIx::Class&#34;&gt;DBIx::Class&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Object::Annotate&#34;&gt;Object::Annotate&lt;/a&gt; - a related, failed experiment&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;</summary><updated>2009-12-22T00:00:00-05:00</updated><category term="Perl"/><category term="RJBS"/></entry><entry><title>Gimme Everything You Got</title><link href="http://advent.rjbs.manxome.org/2009/2009-12-21.html"/><id>http://advent.rjbs.manxome.org/2009/2009-12-21.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h2 id=&#34;Priming-Your-New-Workstations-code&#34;&gt;Priming Your New Workstation&#38;#39;s ~/code&lt;/h2&gt;

&lt;p&gt;...or &lt;code&gt;~/src&lt;/code&gt; or whatever you use. Personally, I have &lt;code&gt;~/code/hub/&lt;/code&gt;, in which I have a clone of &lt;a href=&#34;http://github.com/rjbs&#34;&gt;all the repositories&lt;/a&gt; that I host on &lt;a href=&#34;http://github.com/&#34;&gt;GitHub&lt;/a&gt;. If you checked, you saw that I have a lot of repositories there. This can be a real pain when I set up a new workstation. (That doesn&#38;#39;t happen often, but if Santa wants to bring me a brand new MacBook, I will leave out extra milk and cookies.) It&#38;#39;s also a big pain to get all my repos up to date, which I like to do before travel, or as a backup procedure. I wanted one command that would ensure I had every repo cloned and up to date. That command is &lt;code&gt;git megapull&lt;/code&gt;. When run, it finds all your remote repositories and, for each, checks whether you have a matching directory in &lt;i&gt;cwd&lt;/i&gt;. If you don&#38;#39;t, the repository is cloned. If you do, its origin is fetched and the master branch is merged. It also tells you if you have directories lying around that don&#38;#39;t correspond to remote repositories.&lt;/p&gt;

&lt;p&gt;There are three switches to &lt;code&gt;git megapull&lt;/code&gt;. &lt;code&gt;-c&lt;/code&gt; will only clone repositories; existing clones will not be updated. &lt;code&gt;-b&lt;/code&gt; will create bare repositories when cloning, which is great for making backups.&lt;/p&gt;

&lt;p&gt;The third switch is &lt;code&gt;-s&lt;/code&gt; or &lt;code&gt;--source&lt;/code&gt;. It tells megapull how to get a listing of your remote repositories. &lt;a href=&#34;https://metacpan.org/module/Git::Megapull&#34;&gt;Git::Megapull&lt;/a&gt; comes with a source for GitHub, so you can run &lt;code&gt;git megapull -s Github&lt;/code&gt; (or put &#38;quot;GitHub&#38;quot; in the &lt;code&gt;megapull.source&lt;/code&gt; entry of your &lt;i&gt;~/.gitconfig&lt;/i&gt;) to find and clone all your repositories from GitHub using their API.&lt;/p&gt;

&lt;h3 id=&#34;Providing-Other-Sources&#34;&gt;Providing Other Sources&lt;/h3&gt;

&lt;p&gt;Once I had this tool working on my laptop and a few other workstations, I wanted it at work, where we use gitosis. This was pretty easy to throw together; a source just needs to return a hashref of names and cloneable URIs.&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;br /&gt;15:&#38;nbsp;&lt;br /&gt;16:&#38;nbsp;&lt;br /&gt;17:&#38;nbsp;&lt;br /&gt;18:&#38;nbsp;&lt;br /&gt;19:&#38;nbsp;&lt;br /&gt;20:&#38;nbsp;&lt;br /&gt;21:&#38;nbsp;&lt;br /&gt;22:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;strict&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;warnings&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Git::Megapull::Source::Pobox&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;base&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Git::Megapull::Source&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;repo_uris&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$self&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;@_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@repos&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;backtick&#34;&gt;`ssh git.pobox.com &#39;gfind ~git/repositories -type d -mindepth 1 -maxdepth 1&#39;`&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;chomp&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@repos&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;substitute&#34;&gt;s/\.git//g&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@repos&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;substitute&#34;&gt;s{\A.+/repositories/}{}g&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@repos&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;%repo_uri&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$repo_uri&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;git\@git.pobox.com:$_.git&#38;quot;&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@repos&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;%repo_uri&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;h2 id=&#34;See-Also&#34;&gt;See Also&lt;/h2&gt;

&lt;ul&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Git::Megapull&#34;&gt;Git::Megapull&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/rgit&#34;&gt;rgit&lt;/a&gt; - execute a command on all the git repos in a directory&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;</summary><updated>2009-12-21T00:00:00-05:00</updated><category term="Perl"/><category term="RJBS"/></entry><entry><title>...aka Config::RJBS::AndNobodyElse::KnowsWTFItDoes</title><link href="http://advent.rjbs.manxome.org/2009/2009-12-20.html"/><id>http://advent.rjbs.manxome.org/2009/2009-12-20.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h2 id=&#34;Im-not-apologizing-&#34;&gt;I&#38;#39;m not apologizing!&lt;/h2&gt;

&lt;p&gt;This is &lt;a href=&#34;http://en.wikipedia.org/wiki/Advent&#34;&gt;Advent&lt;/a&gt;, not &lt;a href=&#34;http://en.wikipedia.org/wiki/Lent&#34;&gt;Lent&lt;/a&gt;! It&#38;#39;s a time for giving wonderful things, not for feeling stupid about the dumb things we did. I&#38;#39;ve published plenty of stupid unneeded code, and maybe someday I&#38;#39;ll make a &lt;a href=&#34;http://lent.rjbs.manxome.org&#34;&gt;big list of my screwups&lt;/a&gt;, but for now it&#38;#39;s not happening. I&#38;#39;m gonna shove this present down your throat and you&#38;#39;re gonna love it.&lt;/p&gt;

&lt;p&gt;Ho ho ho. Now I have chainsaws, too.&lt;/p&gt;



&lt;div style=&#39;padding:.25em 0;text-align:center;background: black; color: white;font-size:200%;font-face:monospace&#39;&gt;&lt;span style=&#39;color:#c6c600&#39;&gt;d&#38;#68;&lt;/span&gt;&#38;#x00bb;&#38;#x00bb;&#38;#x00bb; &lt;span style=&#39;color:#c6c600&#39;&gt;d&#38;#68;&lt;/span&gt;&#38;#x00bb;&#38;#x00bb;&#38;#x00bb; &lt;span style=&#39;color:#c6c600&#39;&gt;d&#38;#68;&lt;/span&gt;&#38;#x00bb;&#38;#x00bb;&#38;#x00bb; &lt;span style=&#39;color:#c6c600&#39;&gt;d&#38;#68;&lt;/span&gt;&#38;#x00bb;&#38;#x00bb;&#38;#x00bb; &lt;span style=&#39;color:#c6c600&#39;&gt;d&#38;#68;&lt;/span&gt;&#38;#x00bb;&#38;#x00bb;&#38;#x00bb; &lt;/span&gt;&lt;/div&gt;

&lt;h2 id=&#34;Its-Called-Config::MVP&#34;&gt;It&#38;#39;s Called &#38;quot;Config::MVP&#38;quot;&lt;/h2&gt;

&lt;p&gt;There are a &lt;i&gt;lot&lt;/i&gt; of config-reading libraries. There are &lt;i&gt;hundreds&lt;/i&gt; of them. There are even some that I like, so what the heck was I thinking? I was thinking, &#38;quot;using any of those other hundreds of modules is going to suck for what I want to do.&#38;quot; What I wanted to do, at the time, was screw around with my &lt;i&gt;procmail&lt;/i&gt; settings, but that&#38;#39;s another story.&lt;/p&gt;

&lt;p&gt;I had a few major goals:&lt;/p&gt;

&lt;ul&gt;

&lt;li&gt;&lt;p&gt;make &#38;quot;configuration for a plugin&#38;quot; also mean &#38;quot;load the plugin&#38;quot;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;allow plugins to help validate and contextualize their own configuration&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;allow any given plugin to be loaded multiple times&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;force plugins to be kept in a specific order&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I ended up using the INI format because it was so easy to work with, and because I&#38;#39;d already started down that road before formulating what I really wanted. (That&#38;#39;s how &lt;a href=&#34;https://metacpan.org/module/Config::INI&#34;&gt;Config::INI&lt;/a&gt; was born, which is also another story.) So, here&#38;#39;s an example of all of the above features in use:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;br /&gt;15:&#38;nbsp;&lt;br /&gt;16:&#38;nbsp;&lt;br /&gt;17:&#38;nbsp;&lt;br /&gt;18:&#38;nbsp;&lt;br /&gt;19:&#38;nbsp;&lt;br /&gt;20:&#38;nbsp;&lt;br /&gt;21:&#38;nbsp;&lt;br /&gt;22:&#38;nbsp;&lt;br /&gt;23:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;synSpecial&#34;&gt;[@CorePrep]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synSpecial&#34;&gt;[Name]&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;synSpecial&#34;&gt;[Version]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synSpecial&#34;&gt;[Region  / prelude]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synSpecial&#34;&gt;[Generic / SYNOPSIS]&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;synSpecial&#34;&gt;[Generic / DESCRIPTION]&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;synSpecial&#34;&gt;[Generic / OVERVIEW]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synSpecial&#34;&gt;[Collect / ATTRIBUTES]&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;synType&#34;&gt;command =&lt;/span&gt; attr&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synSpecial&#34;&gt;[Collect / METHODS]&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;synType&#34;&gt;command =&lt;/span&gt; method&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synSpecial&#34;&gt;[Leftovers]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synSpecial&#34;&gt;[Region  / postlude]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synSpecial&#34;&gt;[Authors]&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;synSpecial&#34;&gt;[Legal]&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;Hey, look! It&#38;#39;s configuration just like &lt;a href=&#34;http://advent.rjbs.manxome.org/2009-12-18.html&#34;&gt;Pod::Weaver&lt;/a&gt;! Dist::Zilla and Pod::Weaver both use Config::MVP to great effect. It works like this: every block of the configuration is associated with a plugin -- we use &lt;a href=&#34;http://advent.rjbs.manxome.org/2009-12-16.html&#34;&gt;String::RewritePrefix&lt;/a&gt; to expand the short form into a package name. If there&#38;#39;s something after the slash, we use that as the plugin&#38;#39;s name. That way we can have (for example) multiple &lt;code&gt;Generic&lt;/code&gt; sections like we see above. We just can&#38;#39;t have two sections named &lt;code&gt;OVERVIEW&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Packages can provide methods like &lt;code&gt;mvp_multivalue_args&lt;/code&gt; and &lt;code&gt;mvp_aliases&lt;/code&gt; to tweak how its inputs are handled. For example, one plugin might let you provide multiple entries for &lt;code&gt;author&lt;/code&gt; while another would not. These methods aren&#38;#39;t required, so any package can be treated as a plugin by Config::MVP.&lt;/p&gt;

&lt;h2 id=&#34;The-Config-Sequence&#34;&gt;The Config Sequence&lt;/h2&gt;

&lt;p&gt;There are a few ways to read in MVP-style config, but as far as I know, everything serious right now uses &lt;a href=&#34;https://metacpan.org/module/Config::MVP::Reader::INI&#34;&gt;Config::MVP::Reader::INI&lt;/a&gt;. Any reader, though, will return a Config::MVP::Sequence object. It&#38;#39;s easy to deal with -- it lets you get at your plugin configuration as a list of plugins or by name. For example:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;br /&gt;15:&#38;nbsp;&lt;br /&gt;16:&#38;nbsp;&lt;br /&gt;17:&#38;nbsp;&lt;br /&gt;18:&#38;nbsp;&lt;br /&gt;19:&#38;nbsp;&lt;br /&gt;20:&#38;nbsp;&lt;br /&gt;21:&#38;nbsp;&lt;br /&gt;22:&#38;nbsp;&lt;br /&gt;23:&#38;nbsp;&lt;br /&gt;24:&#38;nbsp;&lt;br /&gt;25:&#38;nbsp;&lt;br /&gt;26:&#38;nbsp;&lt;br /&gt;27:&#38;nbsp;&lt;br /&gt;28:&#38;nbsp;&lt;br /&gt;29:&#38;nbsp;&lt;br /&gt;30:&#38;nbsp;&lt;br /&gt;31:&#38;nbsp;&lt;br /&gt;32:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Christmas::Todo&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;read_plugin_config&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$self&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;@_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$seq&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Config::MVP::Reader::Finder&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;read_config&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;({&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;die&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;you must have a Chimney&#38;quot;&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;unless&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$seq&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;section_named&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;Chimney&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$section&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$seq&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;sections&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$plugin&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$section&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;package&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;      # the payload is a hashref of the actual&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;# vars set in the section&lt;br /&gt;&lt;/span&gt;      &lt;span class=&#34;symbol&#34;&gt;$section&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;payload&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$self&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add_plugin&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$section&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$plugin&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# Later...&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;decorate&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$self&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;@_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@plugins&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;grep&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;does&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;Christmas::Todo::Decorations&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$self&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;plugins&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$plugin&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;@plugins&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;die&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;error when decorating &#38;quot;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;.&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$plugin&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;name&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;unless&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$plugin&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;string_up&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$plugin&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;plug_in&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$plugin&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;turn_on&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;By establishing an explicit order, rather than using a hash, the user who writes the config file can always know in what order his plugins will act. By requiring unique names, we know that we can always get at any plugin by name and that we can identify sources of trouble unambiguously when things go pear shaped.&lt;/p&gt;

&lt;h2 id=&#34;Reading-Configuration&#34;&gt;Reading Configuration&lt;/h2&gt;

&lt;p&gt;Although the INI file reader is the only serious reader right now, writing more is made trivial by using the &lt;a href=&#34;https://metacpan.org/module/Config::MVP::Assembler&#34;&gt;Config::MVP::Assembler&lt;/a&gt; system... but let&#38;#39;s not focus on that. INI files are fine. Still, since there might be other really great offerings, there&#38;#39;s something like Config::Any for MVP: Config::INI::Reader::Finder, which looks for known types of MVP config files and tries to read any of them:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$sequence&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Config::MVP::Reader::Finder&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;read_config&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;({&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;root&lt;/span&gt;     &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;$ENV{HOME}/.christmas&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# I know, I know, unix-o-centric&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;basename&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;config&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;This will look for any kind of plugin it knows how, using the associated extensions. It will look for &lt;i&gt;config.ini&lt;/i&gt;, but it could also look for &lt;i&gt;config.json&lt;/i&gt; or &lt;i&gt;config.pl&lt;/i&gt; if readers were written.&lt;/p&gt;

&lt;p&gt;Config::MVP doesn&#38;#39;t make sense when a simple hashref is really all you need, but for many more complex systems it can save lots of time and make plugins much easier to manage. I&#38;#39;m looking forward to hearing about other people making MVP an important asset in their applications in the coming year.&lt;/p&gt;

&lt;h2 id=&#34;See-Also&#34;&gt;See Also&lt;/h2&gt;

&lt;ul&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Config::MVP&#34;&gt;Config::MVP&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/App::Addex::Config&#34;&gt;App::Addex::Config&lt;/a&gt; - the origin point of MVP&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Config::MVP::Assembler::WithBundles&#34;&gt;Config::MVP::Assembler::WithBundles&lt;/a&gt; - how plugin bundles work&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Config::Any&#34;&gt;Config::Any&lt;/a&gt; - yeah, I speak it; it just doesn&#38;#39;t do enough for me!&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;</summary><updated>2009-12-20T00:00:00-05:00</updated><category term="Perl"/><category term="RJBS"/></entry><entry><title>Restoring The Traditions of our Forefathers</title><link href="http://advent.rjbs.manxome.org/2009/2009-12-19.html"/><id>http://advent.rjbs.manxome.org/2009/2009-12-19.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h2 id=&#34;The-War-on-Finger&#34;&gt;The War on &#38;quot;Finger&#38;quot;&lt;/h2&gt;

&lt;p&gt;I&#38;#39;ll admit it: I am a traditionalist. I believe in honoring the protocols that were left to us by our forefathers. Maybe that makes me &#38;quot;old-fashioned&#38;quot; or &#38;quot;short sighted&#38;quot; or &#38;quot;terminally irrelevant,&#38;quot; but I see no reason I should have to abandon technologies that have existed for 30 years just because they are &#38;quot;horrible&#38;quot; and &#38;quot;obsolete&#38;quot; and &#38;quot;full of security holes.&#38;quot; What does HTTP really give us over Gopher? Why should I use BitTorrent instead of FTP? How is Wave any better than &lt;a href=&#34;http://en.wikipedia.org/wiki/Ytalk&#34;&gt;Ytalk&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;...and then there&#38;#39;s &lt;a href=&#34;http://www.faqs.org/rfcs/rfc742.html&#34;&gt;finger&lt;/a&gt;. People try to replace finger more than anything else. First &#38;quot;the home page&#38;quot; and then &#38;quot;MySpace&#38;quot; and &#38;quot;Classmates&#38;quot; and now I think the hot new thing is &#38;quot;Orkut.&#38;quot; Well, the &lt;i&gt;.plan&lt;/i&gt; file will live forever in my heart.&lt;/p&gt;

&lt;p&gt;I wanted to provide a suitable tribute to my favorite ancient protocol, and what better way than to pair it up with one of the trendy technologies that I &lt;i&gt;do&lt;/i&gt; enjoy. &lt;a href=&#34;http://git-scm.com/&#34;&gt;Git&lt;/a&gt; might only be relevant for a short while, but it&#38;#39;s giving us all kinds of good ideas to backport to &lt;a href=&#34;http://en.wikipedia.org/wiki/GNU_arch&#34;&gt;Arch&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&#34;Finger-My-Git&#34;&gt;Finger My Git&lt;/h2&gt;

&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Git::Fingerd&#34;&gt;Git::Fingerd&lt;/a&gt; is a &lt;a href=&#34;https://metacpan.org/module/Net::Finger::Server&#34;&gt;Net::Finger::Server&lt;/a&gt;-powered repository information delivery platform that allows you to easily access information about a server&#38;#39;s git repositories from any finger-enabled operating system like Mac OS X. Here you can see the result of fingering one of my git servers:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  ~$ finger @git.codesimply.com
  [zodiac.codesimply.com]
  Repository                          Description
  Acme-Canadian                       Canooks in your code, eh?
  Acme-Lingua-EN-Inflect-Modern       modernize Lingua::EN::Inflect rule&#38;#39;s
  Acme-ProgressBar                    a simple progress bar for the patient
  Acme-Studly                         convertBetween various_well_known Id...
  Amce-CNA                            a moer tolernat verison of mehtod lo...
  App-Addex                           generate mail tool configuration fro...
  App-Addex-AddressBook-Abook         use the &#38;quot;abook&#38;quot; program as the addex...
  [ ... ]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If I want to learn more about a repository, it&#38;#39;s easy:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  ~$ finger Rx@git.codesimply.com
  [zodiac.codesimply.com]
  Project  : Rx
  Desc.    : simple, extensible schemata
  Clone URL: git://git.codesimply.com/Rx.git

  [heads]
  master          = 38633c138f2c149ccbb7434a711975173f51a6ca
  struct-fail     = 4c8449e0693c4bac3033c8f093be6bf26a54ac34

  [tags]
  0.003           = b0ecc50fed4e6e84c6350cd12d9be33de926bebb
  0.004           = e625d75cfae4f43f51e43491b2b184a8396b8d50
  perl-0.001      = 602b746868d227e0a72144e6677b0d4a14a668cd
  perl-0.002      = 4b3102379609957b0ca2202f47a7a050ad6c42ee

  [README]
  Rx is really cool, yadda yadda, whatever...&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;The-Future-&#34;&gt;The Future!&lt;/h2&gt;

&lt;p&gt;As time goes on, we can forwardport more ancient protocols into the future, making sure that the future is just as technologically advanced as the past! Imagine using &lt;a href=&#34;https://metacpan.org/module/Net::GitHub&#34;&gt;Net::GitHub&lt;/a&gt; and &lt;a href=&#34;https://metacpan.org/release/Gopher-Server&#34;&gt;Gopher::Server&lt;/a&gt; to create a Gopher interface to &lt;a href=&#34;http://github.com/&#34;&gt;Github&lt;/a&gt;! &lt;code&gt;git push&lt;/code&gt; via UUCP, or &lt;code&gt;git clone&lt;/code&gt; across telnet! The future will be so bright that we&#38;#39;ll have to wear Wayfarers.&lt;/p&gt;

&lt;h2 id=&#34;See-Also&#34;&gt;See Also&lt;/h2&gt;

&lt;ul&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Git::Fingerd&#34;&gt;Git::Fingerd&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Net::Finger::Server&#34;&gt;Net::Finger::Server&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Net::Finger&#34;&gt;Net::Finger&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Git::PurePerl&#34;&gt;Git::PurePerl&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;</summary><updated>2009-12-19T00:00:00-05:00</updated><category term="Perl"/><category term="RJBS"/></entry><entry><title>Glory to Pod in the Highest</title><link href="http://advent.rjbs.manxome.org/2009/2009-12-18.html"/><id>http://advent.rjbs.manxome.org/2009/2009-12-18.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h2 id=&#34;Glory-To-Pod-&#34;&gt;Glory? To Pod?&lt;/h2&gt;

&lt;p&gt;Oh, I don&#38;#39;t know. I have really mixed feelings about Pod. It&#38;#39;s really easy to write, most of the time, and the toolchain for it is pretty fantastic. You can convert Pod to text, man pages, HTML, LaTeX, PDF, and all kinds of other formats. Then again, there&#38;#39;s too much vertical whitespace. Lists are a colossal pain to write. Beyond the annoyances of Pod itself, the Pod of Perl modules uploaded to the CPAN is expected to contain a bunch of boring filler that gets copied around.&lt;/p&gt;

&lt;p&gt;A number of other documentation systems tempted me with the idea of writing less and getting information, like &#38;quot;this bit of documentation associates with this method,&#38;quot; giving you things like Python&#38;#39;s &lt;code&gt;help&lt;/code&gt; builtin. I set about finding a way to write a lot less Pod that would tell me a lot more about my code and look indistinguishable to consumers. There were a few stops and starts and a lot of spun-off code, and a very motivating grant from The Perl Foundation. The end result was &lt;a href=&#34;https://metacpan.org/module/Pod::Weaver&#34;&gt;Pod::Weaver&lt;/a&gt;, which is something like a templating system for Pod.&lt;/p&gt;

&lt;h2 id=&#34;Pod-Templates-with-Pod::Weaver&#34;&gt;Pod Templates with Pod::Weaver&lt;/h2&gt;

&lt;p&gt;Like &lt;a href=&#34;https://metacpan.org/module/Email::MIME::Kit&#34;&gt;Email::MIME::Kit&lt;/a&gt;, though, Pod::Weaver doesn&#38;#39;t just take a document and fill in strings. It takes a description of the goal output and tries to build something matching that description. For example, here&#38;#39;s roughly the default template for Pod::Weaver:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;br /&gt;15:&#38;nbsp;&lt;br /&gt;16:&#38;nbsp;&lt;br /&gt;17:&#38;nbsp;&lt;br /&gt;18:&#38;nbsp;&lt;br /&gt;19:&#38;nbsp;&lt;br /&gt;20:&#38;nbsp;&lt;br /&gt;21:&#38;nbsp;&lt;br /&gt;22:&#38;nbsp;&lt;br /&gt;23:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;synSpecial&#34;&gt;[@CorePrep]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synSpecial&#34;&gt;[Name]&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;synSpecial&#34;&gt;[Version]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synSpecial&#34;&gt;[Region  / prelude]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synSpecial&#34;&gt;[Generic / SYNOPSIS]&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;synSpecial&#34;&gt;[Generic / DESCRIPTION]&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;synSpecial&#34;&gt;[Generic / OVERVIEW]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synSpecial&#34;&gt;[Collect / ATTRIBUTES]&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;synType&#34;&gt;command =&lt;/span&gt; attr&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synSpecial&#34;&gt;[Collect / METHODS]&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;synType&#34;&gt;command =&lt;/span&gt; method&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synSpecial&#34;&gt;[Leftovers]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synSpecial&#34;&gt;[Region  / postlude]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synSpecial&#34;&gt;[Authors]&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;synSpecial&#34;&gt;[Legal]&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;This describes the document to be created; every section of the configuration will try to produce a section in the output Pod, except for &lt;code&gt;@CorePrep&lt;/code&gt;, which is a &lt;i&gt;plugin bundle&lt;/i&gt;, which could provide a bunch of sections or other kinds of plugins. In the case of CorePrep, we&#38;#39;re adding plugins to ensure that we have an object tree that&#38;#39;s something like what we expect from a Pod document, as Pod::Elemental starts with a very bare-bones structure that can be tedious to work with.&lt;/p&gt;

&lt;p&gt;After that, we try to make sure there are NAME and VERSION sections, then we look for prelude region, and so on. The input document might look like this:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;br /&gt;15:&#38;nbsp;&lt;br /&gt;16:&#38;nbsp;&lt;br /&gt;17:&#38;nbsp;&lt;br /&gt;18:&#38;nbsp;&lt;br /&gt;19:&#38;nbsp;&lt;br /&gt;20:&#38;nbsp;&lt;br /&gt;21:&#38;nbsp;&lt;br /&gt;22:&#38;nbsp;&lt;br /&gt;23:&#38;nbsp;&lt;br /&gt;24:&#38;nbsp;&lt;br /&gt;25:&#38;nbsp;&lt;br /&gt;26:&#38;nbsp;&lt;br /&gt;27:&#38;nbsp;&lt;br /&gt;28:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;synStatement&#34;&gt;package&lt;/span&gt;&lt;span class=&#34;synType&#34;&gt; Tree::Christmas&lt;/span&gt;;&lt;br /&gt;&lt;span class=&#34;synComment&#34;&gt;# ABSTRACT: a binary tree decorated with baubles and popcorn&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;=begin&lt;/span&gt; &lt;span class=&#34;synIdentifier&#34;&gt;:prelude&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;=head1&lt;/span&gt;&lt;span class=&#34;synConstant&#34;&gt; WARNING&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This code may cause your home to smell like pine needles.&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;=end&lt;/span&gt; &lt;span class=&#34;synIdentifier&#34;&gt;:prelude&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;=head1&lt;/span&gt;&lt;span class=&#34;synConstant&#34;&gt; DESCRIPTION&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This library provides a framework for hanging tinsel, popcorn, and other&lt;br /&gt;forms of garland.  In some locales, pickles may also be nested in a&lt;br /&gt;Tree::Christmas.&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;=method&lt;/span&gt;&lt;span class=&#34;synConstant&#34;&gt; ignite_lights&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This method...&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;=method&lt;/span&gt;&lt;span class=&#34;synConstant&#34;&gt; new&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;=attr&lt;/span&gt;&lt;span class=&#34;synConstant&#34;&gt; pickle_jar&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This is an arrayref of pickles.&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;If we want to include things like a name, version, license, and author in the output, we&#38;#39;ll need to provide those. We&#38;#39;ll do that with something like this:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$input_pod&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Pod::Elemental&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;read_string&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$the_sample_above&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$weaver&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Pod::Weaver&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new_with_default_config&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$output_pod&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$weaver&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;weave_document&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;({&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;authors&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Ricardo Signes &#38;lt;rjbs@example.com&#38;gt;&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;license&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Software::License::Perl_5&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;({&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;})&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;version&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;1.234&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;pod_document&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$input_pod&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;ppi_document&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$input_ppi&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# (don&#39;t worry, keep reading)&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;That gets us a new Pod::Elemental::Document which, when turned into a Pod stirng, looks something like this:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;br /&gt;15:&#38;nbsp;&lt;br /&gt;16:&#38;nbsp;&lt;br /&gt;17:&#38;nbsp;&lt;br /&gt;18:&#38;nbsp;&lt;br /&gt;19:&#38;nbsp;&lt;br /&gt;20:&#38;nbsp;&lt;br /&gt;21:&#38;nbsp;&lt;br /&gt;22:&#38;nbsp;&lt;br /&gt;23:&#38;nbsp;&lt;br /&gt;24:&#38;nbsp;&lt;br /&gt;25:&#38;nbsp;&lt;br /&gt;26:&#38;nbsp;&lt;br /&gt;27:&#38;nbsp;&lt;br /&gt;28:&#38;nbsp;&lt;br /&gt;29:&#38;nbsp;&lt;br /&gt;30:&#38;nbsp;&lt;br /&gt;31:&#38;nbsp;&lt;br /&gt;32:&#38;nbsp;&lt;br /&gt;33:&#38;nbsp;&lt;br /&gt;34:&#38;nbsp;&lt;br /&gt;35:&#38;nbsp;&lt;br /&gt;36:&#38;nbsp;&lt;br /&gt;37:&#38;nbsp;&lt;br /&gt;38:&#38;nbsp;&lt;br /&gt;39:&#38;nbsp;&lt;br /&gt;40:&#38;nbsp;&lt;br /&gt;41:&#38;nbsp;&lt;br /&gt;42:&#38;nbsp;&lt;br /&gt;43:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;synStatement&#34;&gt;=head1&lt;/span&gt;&lt;span class=&#34;synConstant&#34;&gt; NAME&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Tree::Christmas - a binary tree decorated with baubles and popcorn&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;=head1&lt;/span&gt;&lt;span class=&#34;synConstant&#34;&gt; VERSION&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;version 1.234&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;=head1&lt;/span&gt;&lt;span class=&#34;synConstant&#34;&gt; WARNING&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This code may cause your home to smell like pine needles.&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;=head1&lt;/span&gt;&lt;span class=&#34;synConstant&#34;&gt; DESCRIPTION&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This library provides a framework for hanging tinsel, popcorn, and other&lt;br /&gt;forms of garland.  In some locales, pickles may also be nested in a&lt;br /&gt;Tree::Christmas.&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;=head1&lt;/span&gt;&lt;span class=&#34;synConstant&#34;&gt; ATTRIBUTES&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;=head2&lt;/span&gt;&lt;span class=&#34;synConstant&#34;&gt; pickle_jar&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This is an arrayref of pickles.&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;=head1&lt;/span&gt;&lt;span class=&#34;synConstant&#34;&gt; METHODS&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;=head2&lt;/span&gt;&lt;span class=&#34;synConstant&#34;&gt; ignite_lights&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This method...&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;=head2&lt;/span&gt;&lt;span class=&#34;synConstant&#34;&gt; new&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;=head1&lt;/span&gt;&lt;span class=&#34;synConstant&#34;&gt; AUTHORS&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synPreProc&#34;&gt;  Ricardo Signes &#38;lt;rjbs@example.com&#38;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;=head1&lt;/span&gt;&lt;span class=&#34;synConstant&#34;&gt; COPYRIGHT AND LICENSE&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This document is copyright (C) 1991, Ricardo Signes.&lt;br /&gt;&lt;br /&gt;This document is available under the blah blah blah.&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;Not bad! We avoid typing nearly half of the output document, by lines -- and that&#38;#39;s only part of the benefit. If we have five modules in our distribution, all that boilerplate is added everywhere for us, so multiply that savings across all our modules. Then, if ever we want to change our license or add an author or even change the overall layout of the output document, we only need to change our configuration in one place.&lt;/p&gt;

&lt;p&gt;If you&#38;#39;re wondering about the &lt;code&gt;ppi_document&lt;/code&gt; input above, it&#38;#39;s there because some sections can be built by analyzing the Perl content of the document, so you can automatically document things like included packages, defined subroutines, and so on. (You could also write something to compile the code and look at the symbol table or meta layer, although no one has done that yet!) Because &#38;quot;load a &lt;i&gt;.pm&lt;/i&gt; file, break it into Pod and Perl, rewrite the Pod, and write it back out&#38;quot; is such a common pattern, there&#38;#39;s even &lt;a href=&#34;https://metacpan.org/module/Pod::Elemental::PerlMunger&#34;&gt;Pod::Elemental::PerlMunger&lt;/a&gt;, which takes care of everything but the &#38;quot;rewrite the Pod&#38;quot; step for you, leaving you free to focus on configuring your weaver or other rewriting tool.&lt;/p&gt;

&lt;p&gt;That&#38;#39;s the interface on which &lt;a href=&#34;https://metacpan.org/module/Dist::Zila::Plugin::PodWeaver&#34;&gt;Dist::Zila::Plugin::PodWeaver&lt;/a&gt; is built. It gets all its inputs from your Dist::Zilla configuration and then rewrites all your Perl modules with Pod::Weaver. If you&#38;#39;re using Dist::Zilla, all you need to do to get all the rewriting seen above is add the line &lt;code&gt;[PodWeaver]&lt;/code&gt; into your &lt;i&gt;dist.ini&lt;/i&gt;.&lt;/p&gt;

&lt;h2 id=&#34;Extending-Pod::Weaver&#34;&gt;Extending Pod::Weaver&lt;/h2&gt;

&lt;p&gt;Pod::Weaver tries to make it easy to add new behavior. For example, a simple plugin to add an &#38;quot;Acknowledgements&#38;quot; section is only about a dozen lines of code. A plugin to integrate Pod::Weaver with &lt;a href=&#34;https://metacpan.org/module/Pod::WikiDoc&#34;&gt;Pod::WikiDoc&lt;/a&gt; is only about six lines of code. This allows the transformation of the easy to type:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;synStatement&#34;&gt;=for&lt;/span&gt; &lt;span class=&#34;synIdentifier&#34;&gt;wikidoc&lt;/span&gt;&lt;br /&gt;* bell&lt;br /&gt;* book&lt;br /&gt;* candle&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;...into the grumble-inducing:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;br /&gt;15:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;synStatement&#34;&gt;=over&lt;/span&gt; &lt;span class=&#34;synConstant&#34;&gt;2&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;=item&lt;/span&gt;&lt;span class=&#34;synConstant&#34;&gt; *&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;bell&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;=item&lt;/span&gt;&lt;span class=&#34;synConstant&#34;&gt; *&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;book&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;=item&lt;/span&gt;&lt;span class=&#34;synConstant&#34;&gt; *&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;candle&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;=back&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;A recurring theme of this set of articles has been my hatred for needless typing and boilerplate content, and Pod::Weaver has gone a long way to letting me avoid both. Hopefully you can use it to avoid them now, too, and spend more time solving problems.&lt;/p&gt;

&lt;h2 id=&#34;See-Also&#34;&gt;See Also&lt;/h2&gt;

&lt;ul&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Pod::Weaver&#34;&gt;Pod::Weaver&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Pod::Elemental&#34;&gt;Pod::Elemental&lt;/a&gt; - the Pod object model on which Weaver is built&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Pod::Eventual&#34;&gt;Pod::Eventual&lt;/a&gt; - the event-based parser behind Pod::Elemental&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Dist::Zilla::Plugin::PodWeaver&#34;&gt;Dist::Zilla::Plugin::PodWeaver&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Dist::Zilla::Plugin::PodPurler&#34;&gt;Dist::Zilla::Plugin::PodPurler&lt;/a&gt; - a pale imitation/prototype of PodWeaver&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Pod::Elemental::PerlMunger&#34;&gt;Pod::Elemental::PerlMunger&lt;/a&gt; - for writing your own Pod-in-Perl rewriter&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Pod::WikiDoc&#34;&gt;Pod::WikiDoc&lt;/a&gt; - David Golden&#38;#39;s excellent wiki-like Pod dialect&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Pod::Weaver::PluginBundle::RJBS&#34;&gt;Pod::Weaver::PluginBundle::RJBS&lt;/a&gt; - how I weave my Pod&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;what is pod weaver, &lt;a href=&#34;http://rjbs.manxome.org/rubric/entry/1808&#34;&gt;Part 1&lt;/a&gt;, &lt;a href=&#34;http://rjbs.manxome.org/rubric/entry/1809&#34;&gt;Part 2&lt;/a&gt; - blog post about Pod::Weaver&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;</summary><updated>2009-12-18T00:00:00-05:00</updated><category term="Perl"/><category term="RJBS"/></entry><entry><title>Rewrite Email Without Worrying</title><link href="http://advent.rjbs.manxome.org/2009/2009-12-17.html"/><id>http://advent.rjbs.manxome.org/2009/2009-12-17.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h2 id=&#34;Encoding-and-Email&#34;&gt;Encoding and Email&lt;/h2&gt;

&lt;p&gt;Talking about encoding is sort of tiresome, and I think everybody has heard enough of it. Talking is about email is pretty tiresome, too, and I know &lt;i&gt;I&lt;/i&gt; have had enough. So, here&#38;#39;s a very, very brief overview of why the two things are annoying together.&lt;/p&gt;

&lt;p&gt;There are many systems for picking a set of symbols and assigning them numerical values. These are &lt;i&gt;character sets&lt;/i&gt;. Unicode is the current favorite. In unicode, for example, the character numbered 0x2603 is a snowman (&#38;#x2603;). There are also systems for writing out strings of characters to bytes so you can put them in a file system. These are &lt;i&gt;encodings&lt;/i&gt;. UTF-8 is a popular way to do this for unicode, but not the only way. Some character sets already fit in 8-bit bytes, so they are their own encoding. Latin-1 is a good example. MacCyrillic is also an example.&lt;/p&gt;

&lt;p&gt;Rougly speaking, in email, character set and encoding are conflated and called charset. If you declare your message&#38;#39;s charset to be UTF-8, it means that it&#38;#39;s UTF-8 encoded Unicode. In general, this conflation does not lead to problems. The problem is that email has to be encoded to 7-bit octets -- that is, bytes where the high bit is always off. The process by which this is done is called encoding (content transfer encoding).&lt;/p&gt;

&lt;p&gt;So, say you&#38;#39;re operating a mailing list and you need to attach footers to a message. First you have to decode from 7-bit to 8-bit and then from 8-bit to characters. Then you can tack on your footer, then you have to do the reverse encoding dance.&lt;/p&gt;

&lt;h2 id=&#34;Hiding-the-Encoding-Process&#34;&gt;Hiding the Encoding Process&lt;/h2&gt;

&lt;p&gt;MIME::Visitor does its best to get rid of the whole mess.&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;comment&#34;&gt;# This example might be a bit naive, but it should make the point pretty&lt;br /&gt;# clearly:&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$mime_entity&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;get_email&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;MIME::Visitor&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;rewrite_parts&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$mime_entity&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$content_ref&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$part&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;@_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;cast&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$content_ref&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;.=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;footer_for&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$part&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;mime_type&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;So, with just a few lines of code, we hide all the annoying bits of encoding and decoding, letting you just focus on the content you want to play with. It has a number of other ways to handle messages, and it does work to ensure that it never rewrites parts that haven&#38;#39;t been changed.&lt;/p&gt;

&lt;p&gt;Unwrapped to code you&#38;#39;d have to write, the above is something like:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;br /&gt;15:&#38;nbsp;&lt;br /&gt;16:&#38;nbsp;&lt;br /&gt;17:&#38;nbsp;&lt;br /&gt;18:&#38;nbsp;&lt;br /&gt;19:&#38;nbsp;&lt;br /&gt;20:&#38;nbsp;&lt;br /&gt;21:&#38;nbsp;&lt;br /&gt;22:&#38;nbsp;&lt;br /&gt;23:&#38;nbsp;&lt;br /&gt;24:&#38;nbsp;&lt;br /&gt;25:&#38;nbsp;&lt;br /&gt;26:&#38;nbsp;&lt;br /&gt;27:&#38;nbsp;&lt;br /&gt;28:&#38;nbsp;&lt;br /&gt;29:&#38;nbsp;&lt;br /&gt;30:&#38;nbsp;&lt;br /&gt;31:&#38;nbsp;&lt;br /&gt;32:&#38;nbsp;&lt;br /&gt;33:&#38;nbsp;&lt;br /&gt;34:&#38;nbsp;&lt;br /&gt;35:&#38;nbsp;&lt;br /&gt;36:&#38;nbsp;&lt;br /&gt;37:&#38;nbsp;&lt;br /&gt;38:&#38;nbsp;&lt;br /&gt;39:&#38;nbsp;&lt;br /&gt;40:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$mime_entity&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;get_email&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$walk&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$walk&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$root&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$code&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;@_&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$root&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;is_multipart&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$walk&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$code&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$root&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;parts&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;unless&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;effective_type&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=~&lt;/span&gt; &lt;span class=&#34;regexp&#34;&gt;qr{\Atext/(?:html|plain)(?:$|;)}i&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$charset&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$entity&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;head&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;mime_attr&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;content-type.charset&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;operator&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;ISO-8859-1&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$charset&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;MacRoman&#39;&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;lc&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$charset&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;eq&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;macintosh&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;Carp::carp&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;interpolate&#34;&gt;qq{rewriting message in unknown charset &#38;quot;$charset&#38;quot;}&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;unless&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$known_charset&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Encode::find_encoding&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$charset&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$changed&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$got_set&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Variable::Magic::wizard&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;set&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$changed&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$body&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$known_charset&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;operator&#34;&gt;?&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Encode::decode&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$charset&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$entity&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;bodyhandle&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;as_string&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;operator&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$entity&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;bodyhandle&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;as_string&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;Variable::Magic::cast&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$body&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$got_set&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$code&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;cast&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$body&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$entity&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$changed&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$io&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$entity&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;open&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;w&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$io&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$known_charset&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;?&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Encode::encode&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$charset&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$body&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$body&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$walk&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$mime_entity&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$content_ref&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$part&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;@_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;cast&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$content_ref&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;.=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;footer_for&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$part&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;mime_type&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;h3 id=&#34;MIME::Entity-&#34;&gt;MIME::Entity!?&lt;/h3&gt;

&lt;p&gt;The most glaring problem with MIME::Visitor is that it works with MIME::Entity objects instead of Email::MIME objects, which are generally more common in my toolchain. When MIME::Visitor was written, access to get and set the Unicode content of a text part wasn&#38;#39;t very good. It&#38;#39;s better now, so this may get fixed soon!&lt;/p&gt;

&lt;h2 id=&#34;See-Also&#34;&gt;See Also&lt;/h2&gt;

&lt;ul&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/MIME::Visitor&#34;&gt;MIME::Visitor&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/MIME::BodyMunger&#34;&gt;MIME::BodyMunger&lt;/a&gt; - used by MIME::Visitor&#38;#39;s rewriting methods&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/MIME::Entity&#34;&gt;MIME::Entity&lt;/a&gt; - yet another email message representation&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;</summary><updated>2009-12-17T00:00:00-05:00</updated><category term="Perl"/><category term="RJBS"/></entry><entry><title>More Stuff I Stole from Catalyst (that they stole back)</title><link href="http://advent.rjbs.manxome.org/2009/2009-12-16.html"/><id>http://advent.rjbs.manxome.org/2009/2009-12-16.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h2 id=&#34;I-Hate-Typing&#34;&gt;I Hate Typing&lt;/h2&gt;

&lt;p&gt;It&#38;#39;s true. The only time that I &lt;i&gt;like&lt;/i&gt; typing is when I&#38;#39;m playing &lt;a href=&#34;http://en.wikipedia.org/wiki/Typing_of_the_Dead&#34;&gt;Typing of the Dead&lt;/a&gt;. (I try to get in a big dose of zombie video games every Yuletide; maybe I&#38;#39;ll bring the old Dreamcast up again this winter.) Apart from shooting zombies by typing quickly, typing stinks. It hurts my hands, and I live in perpetual dread of the day when I must find a new profession because my fingers no longer work. That&#38;#39;s why most of the code I write is meant to save keystrokes for when I write &lt;i&gt;other&lt;/i&gt; code.&lt;/p&gt;

&lt;p&gt;Catalyst lets you write something like this in your config for Holiday::Web:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$config&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;Model::GreetingCard&#39;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;View::TextTemplate&#39;&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;+Catalyst::Plugin::Kwanzaa&#39;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;The first two get rewritten to &#38;quot;Holiday::Web::Model::GreetingCard&#38;quot; and &#38;quot;Holiday::Web::View::TextTemplate&#38;quot; respectively. In the third, the &lt;code&gt;+&lt;/code&gt; means that it should be used literally -- so just the plus sign is dropped. There&#38;#39;s also a &lt;code&gt;~&lt;/code&gt; prefix for slightly more arcane uses. Obviously, this can save a lot of typing and, just as importantly, a lot of reading. I liked this!&lt;/p&gt;

&lt;p&gt;I really wanted to use this kind of rewriting for &lt;a href=&#34;https://metacpan.org/module/Dist::Zilla&#34;&gt;Dist::Zilla&lt;/a&gt;, and to make sure I could re-use this pattern whenever I wanted, I wrote String::RewritePrefix. Catalyst&#38;#39;s behavior could be written as:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;String::RewritePrefix&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;rewrite&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;prefixes&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;&#39;&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Holiday::Web::&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;+&#39;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;&#39;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;That&#38;#39;s using &lt;a href=&#34;https://metacpan.org/module/Sub::Exporter&#34;&gt;Sub::Exporter&lt;/a&gt;, of course, so we can import a few rewriting strategies:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;String::RewritePrefix&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;rewrite&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;-as&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;holiday_px&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;prefixes&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;&#39;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Holiday::Web::&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;+&#39;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;rewrite&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;-as&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;num_px&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;     &lt;span class=&#34;word&#34;&gt;prefixes&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;-&#39;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;negative &#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;+&#39;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;positive &#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@numbers&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;num_px&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;words&#34;&gt;qw( +40 -10 +18 0 )&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# ==&#38;gt; (positive 40, negative 10, positive 18, 0)&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@plugins&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;holiday_px&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;words&#34;&gt;qw(&lt;br /&gt;&#38;nbsp;&#38;nbsp;Model::GreetingCard&lt;br /&gt;&#38;nbsp;&#38;nbsp;View::TextTemplate&lt;br /&gt;&#38;nbsp;&#38;nbsp;+Catalyst::Plugin::Kwanzaa&lt;br /&gt;)&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# ==&#38;gt; (Holiday::Web::Mode::GreetingCard,&lt;br /&gt;#      Holiday::Web::View::TextTemplate, Catalyst::Plugin::Kwanzaa)&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;There isn&#38;#39;t much more to it, apart from one or two weird options. Still, think of all the typing and squinting you save in your config files!&lt;/p&gt;

&lt;p&gt;The prefix rewriting in &lt;a href=&#34;https://metacpan.org/module/Catalyst::Utils&#34;&gt;Catalyst::Utils&lt;/a&gt;, which inspired me to write String::RewritePrefix, now &lt;i&gt;uses&lt;/i&gt; String::RewritePrefix! It&#38;#39;s always a joy to find out that other people benefit from my attempt to be lazy and type less. It means &lt;i&gt;they&lt;/i&gt; have more time for Typing of the Dead, too.&lt;/p&gt;

&lt;h2 id=&#34;See-Also&#34;&gt;See Also&lt;/h2&gt;

&lt;ul&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/String::RewritePrefix&#34;&gt;String::RewritePrefix&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Catalyst::Utils&#34;&gt;Catalyst::Utils&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;</summary><updated>2009-12-16T00:00:00-05:00</updated><category term="Perl"/><category term="RJBS"/></entry><entry><title>Like FUSE, but Stupider</title><link href="http://advent.rjbs.manxome.org/2009/2009-12-15.html"/><id>http://advent.rjbs.manxome.org/2009/2009-12-15.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h2 id=&#34;From-Filename-to-Thing&#34;&gt;From Filename to Thing&lt;/h2&gt;

&lt;p&gt;A few years ago, my coworker &lt;a href=&#34;http://blog.weftsoar.net/&#34;&gt;Dieter&lt;/a&gt; and I were working on improving the componentization of some of our internal web applications. We wanted it to be easier to say &#38;quot;put a paginated table thing here&#38;quot; or &#38;quot;give me a link here.&#38;quot; We were pretty happy with &lt;a href=&#34;https://metacpan.org/module/HTML::Widget::Factory&#34;&gt;HTML::Widget::Factory&lt;/a&gt; for low-level use, and the rest could be done with &lt;a href=&#34;https://metacpan.org/module/HTML::Mason&#34;&gt;Mason&lt;/a&gt; components. We just didn&#38;#39;t like the way that you&#38;#39;d have to know whether a component was a method call on a widget factory object or a component call in Mason. I said something like, &#38;quot;I wish we could make it all look like Mason.&#38;quot; Totally blowing my mind for all time, Dieter said, &#38;quot;We can&#38;quot; and &lt;a href=&#34;https://metacpan.org/module/MasonX::Resolver::WidgetFactory&#34;&gt;made it happen&lt;/a&gt; &lt;a href=&#34;https://metacpan.org/module/MasonX::Resolver::Multiplex&#34;&gt;seamlessly&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The thing is that Mason&#38;#39;s system for resolving path-like things into a component is itself a thing that can customized or replaced. It&#38;#39;s the resolver, and you can write a new one.&lt;/p&gt;

&lt;p&gt;Many times after seeing the elegance of that solution, I wanted to be able to replace parts of all sorts of code that expected filenames. I looked a number of &#38;quot;emulate a filesystem in Perl&#38;quot; libraries, but they wanted to provide all kinds of stuff I didn&#38;#39;t care about -- like statting deleting files. Heck, I just wanted an entity!&lt;/p&gt;

&lt;p&gt;Finally my will broke and I wrote the crappiest thing I could think of that would still work. That was Path::Resolver version 0, and now we&#38;#39;re up to 3. It&#38;#39;s still pretty stupid, and that&#38;#39;s a feature. The simplest use is something like this:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$resolver&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Path::Resolver::Resolver::FileSystem&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;({&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;root&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;/tmp&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$content&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$resolver&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;entity_for&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;/baz/bar/quux.txt&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;content&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# or ...&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$resolver&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Path::Resolver::Resolver::Archive::Tar&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;({&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;archive&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;foo.tar.gz&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# or ...&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$resolver&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Path::Resolver::Resolver::DistDir&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;({&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;dist_name&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Christmas-App&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;The resolver is, of course, the thing that goes from a filename to an entity. The definition of an entity is pretty vague: it&#38;#39;s just a thing. Resolvers know what kind of things they&#38;#39;ll return, and you can give them a converter that will expect that kind of thing and return another kind. For example, the FileSystem resolver resolves things to absolute filenames. Then it can be converted to a &#38;quot;SimpleEntity,&#38;quot; which basically is just a thing with content. The tarball resolver produces SimpleEntities natively. By knowing what kind of entity things will find, and by having a means to convert them, it&#38;#39;s easy to put together a bunch of different kinds of resolvers and multiplex them.&lt;/p&gt;

&lt;h2 id=&#34;Multiplexing-Resolvers&#34;&gt;Multiplexing Resolvers&lt;/h2&gt;

&lt;p&gt;Multiplexing resolvers? It&#38;#39;s really simple. &#38;quot;Mux&#38;quot; resolvers just say &#38;quot;I have a bunch of resolvers that all return the same kind of thing, and I have a strategy for picking one of them.&#38;quot; There are two important muxers that come with Path::Resolver: Ordered and Prefix. The ordered resolver lets you set up things like the &lt;code&gt;$PATH&lt;/code&gt; environment variable. Imagine you did this:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$resolver&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Path::Resolver::Resolver::Mux::Ordered&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;({&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;resolvers&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;Path::Resolver::Resolver::FileSystem&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;({&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;root&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;/bin&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;})&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;Path::Resolver::Resolver::FileSystem&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;({&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;root&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;/usr/bin&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;})&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;Path::Resolver::Resolver::FileSystem&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;({&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;root&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;/usr/local/bin&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;})&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;Now you&#38;#39;d have something resembling the way your shell finds commands to run. Of course, there&#38;#39;s no reason that all the resolvers in there have to be filesystem resolvers. Maybe your web app installs its own templates, but they can be overridden by the user.&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$resolver&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Path::Resolver::Resolver::Mux::Ordered&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;({&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;resolvers&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;Path::Resolver::Resolver::FileSystem&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;({&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;root&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;./templates&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;})&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;Path::Resolver::Resolver::DistDir&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;({&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;dist_name&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;My-WebApp&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;})&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;If the file isn&#38;#39;t found in the &lt;i&gt;./templates&lt;/i&gt; directory, we&#38;#39;ll look in the files we installed when your webapp was installed.&lt;/p&gt;

&lt;p&gt;The prefix muxer is more complex. It represents a virtual directory where each subdirectory is handled by a different resolver. This is used in &lt;a href=&#34;https://metacpan.org/module/Email::MIME::Kit::KitReader::SWAK&#34;&gt;Email::MIME::Kit::KitReader::SWAK&lt;/a&gt; to make &lt;a href=&#34;http://advent.rjbs.manxome.org/2009-12-10.html&#34;&gt;Email::MIME::Kit&lt;/a&gt; easer to use. It sets up resolvers like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  file.txt      - looks in the mkit directory
  /kit/file.txt - looks in the mkit directory
  /dist/My-WebApp/header.html      - looks in dist ShareDir for My-WebApp
  /fs/usr/share/common/header.html - looks in /usr on the filesystem&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;Putting-it-to-Use&#34;&gt;Putting it to Use&lt;/h2&gt;

&lt;p&gt;A nice thing about Path::Resolver is that in general, you can use it without worrying about how it will get used later. If you have some part of your program that reads stuff from disk, you can just say, &#38;quot;Whatever, I&#38;#39;ll use a Path::Resolver here.&#38;quot; Then whenever anyone wants to make it do something wild and crazy, it&#38;#39;s much, much simpler for them to do so -- they just supply a new Path::Resolver object to replace your stock FileSystem resolver.&lt;/p&gt;

&lt;h2 id=&#34;See-Also&#34;&gt;See Also&lt;/h2&gt;

&lt;ul&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Path::Resolver&#34;&gt;Path::Resolver&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/HTML::Mason::Resolver&#34;&gt;HTML::Mason::Resolver&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Email::MIME::Kit::KitReader::SWAK&#34;&gt;Email::MIME::Kit::KitReader::SWAK&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;</summary><updated>2009-12-15T00:00:00-05:00</updated><category term="Perl"/><category term="RJBS"/></entry><entry><title>First-Class CLI Applications</title><link href="http://advent.rjbs.manxome.org/2009/2009-12-14.html"/><id>http://advent.rjbs.manxome.org/2009/2009-12-14.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h2 id=&#34;Scripts-are-Our-Friends&#34;&gt;Scripts are Our Friends&lt;/h2&gt;

&lt;p&gt;In my experience, it&#38;#39;s pretty common to find a large piece of functionality built into a command-line program (or &#38;quot;script&#38;quot; (and I am &lt;i&gt;totally&lt;/i&gt; not going to get into the &#38;quot;script&#38;quot; vs. &#38;quot;program&#38;quot; debate here)) and then to find that the program isn&#38;#39;t tested at all. When you say, &#38;quot;For the love of God, why are you not testing this vital program?&#38;quot; the answer is, &#38;quot;Well, scripts are really hard to test!&#38;quot;&lt;/p&gt;

&lt;p&gt;It&#38;#39;s true. Maybe they&#38;#39;re not as hard to test as people think, but it&#38;#39;s still a pain. They&#38;#39;re also full of too many standards for getopt or error messages. People just do whatever gets work done, and then later have to pay the price for making crazy decisions.&lt;/p&gt;

&lt;h2 id=&#34;A-Simple-App::Cmd-Program&#34;&gt;A Simple App::Cmd Program&lt;/h2&gt;

&lt;p&gt;App::Cmd is a simple framework for writing command-line applications that are easy to test, that have powerful and easy to use standard tools, and that can be extended easily.&lt;/p&gt;

&lt;p&gt;For example, here&#38;#39;s a simple command we might write, in two parts. First, the script that we put in our path, then the library that implements it.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;./bin/christmas&lt;/i&gt;:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Christmas::App&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;Christmas::App&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;&lt;i&gt;./lib/Christmas/App.pm&lt;/i&gt;:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;br /&gt;15:&#38;nbsp;&lt;br /&gt;16:&#38;nbsp;&lt;br /&gt;17:&#38;nbsp;&lt;br /&gt;18:&#38;nbsp;&lt;br /&gt;19:&#38;nbsp;&lt;br /&gt;20:&#38;nbsp;&lt;br /&gt;21:&#38;nbsp;&lt;br /&gt;22:&#38;nbsp;&lt;br /&gt;23:&#38;nbsp;&lt;br /&gt;24:&#38;nbsp;&lt;br /&gt;25:&#38;nbsp;&lt;br /&gt;26:&#38;nbsp;&lt;br /&gt;27:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Christmas::App&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;base&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;App::Cmd::Simple&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# ABSTRACT: an app for managing our christmas shopping&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;opt_spec&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;nice|n&#39;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;list only nice people&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;all|a&#39;&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;list even people for whom shopping is done&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;validate_args&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$self&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$opt&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$args&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;@_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$self&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;usage_error&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;double&#34;&gt;&#38;quot;no args expected&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$args&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;execute&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$self&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$opt&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$args&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;@_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@presents&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Christmas::Presents&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # In other words: use switches to build query:&lt;br /&gt;&lt;/span&gt;    &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$opt&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;all&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;?&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;done&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$opt&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;nice&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;?&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;nice&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;())&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$self&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;_list_presents&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;@presents&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# implementation left to imagination&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;So far, we&#38;#39;ve only added a little structure to our code, but it&#38;#39;s already a big help. The &lt;code&gt;opt_spec&lt;/code&gt; routine uses &lt;a href=&#34;https://metacpan.org/module/Getopt::Long::Descriptive&#34;&gt;Getopt::Long::Descriptive&lt;/a&gt; to not only process command line switches (with quite a lot of power), but also to generate helpful usage messages like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  Usage: christmas

  christmas [-an] [long options...]
    -n --nice   list only nice people
    -a --all    list even people for whom shopping is done&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We also get a phase before execution but after argument processing to decide whether the arguments we were given make any sense -- here we just ensure that we didn&#38;#39;t get any!&lt;/p&gt;

&lt;h2 id=&#34;Putting-it-to-the-Test&#34;&gt;Putting it to the Test&lt;/h2&gt;

&lt;p&gt;One of the big reasons to use App::Cmd was supposed to be its testability, so let&#38;#39;s see how that works.&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;br /&gt;15:&#38;nbsp;&lt;br /&gt;16:&#38;nbsp;&lt;br /&gt;17:&#38;nbsp;&lt;br /&gt;18:&#38;nbsp;&lt;br /&gt;19:&#38;nbsp;&lt;br /&gt;20:&#38;nbsp;&lt;br /&gt;21:&#38;nbsp;&lt;br /&gt;22:&#38;nbsp;&lt;br /&gt;23:&#38;nbsp;&lt;br /&gt;24:&#38;nbsp;&lt;br /&gt;25:&#38;nbsp;&lt;br /&gt;26:&#38;nbsp;&lt;br /&gt;27:&#38;nbsp;&lt;br /&gt;28:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Test::More&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;App::Cmd::Tester&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Christmas::App&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$result&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;test_app&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;Christmas::App&#39;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;words&#34;&gt;qw(--all)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;]);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;is&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$result&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;nothing to stderr&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;like&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$result&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;stdout&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;regexp&#34;&gt;qr/Ricardo Signes/&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;     &lt;span class=&#34;double&#34;&gt;&#38;quot;rjbs is in our list&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;like&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$result&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;stdout&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;regexp&#34;&gt;qr/Violet Beauregarde/&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;violet is, too&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$result&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;test_app&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;Christmas::App&#39;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;words&#34;&gt;qw(--all --nice)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;]);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;is&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$result&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;nothing to stderr&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;like&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$result&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;stdout&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;regexp&#34;&gt;qr/Ricardo Signes/&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;       &lt;span class=&#34;double&#34;&gt;&#38;quot;rjbs was nice&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;unlike&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$result&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;stdout&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;regexp&#34;&gt;qr/Violet Beauregarde/&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Violet was naughty&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$result&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;test_app&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;Christmas::App&#39;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;words&#34;&gt;qw(--nice)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;]);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;is&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$result&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;nothing to stderr&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;unlike&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$result&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;stdout&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;regexp&#34;&gt;qr/Ricardo Signes/&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;     &lt;span class=&#34;double&#34;&gt;&#38;quot;no rjbs w/o --all&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;unlike&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$result&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;stdout&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;regexp&#34;&gt;qr/Violet Beauregarde/&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Violet still naughty&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;This should be fairly straightforward: &lt;code&gt;test_app&lt;/code&gt; runs the application, using the passed arrayref as the value for &lt;code&gt;@ARGS&lt;/code&gt;. It doesn&#38;#39;t run in a subprocess, so there&#38;#39;s no weird issues with interprocess communication. Also, because it runs in process, you can replace hunks of the app with mocks if you want, and you&#38;#39;ll have them available for inspection after testing.&lt;/p&gt;

&lt;h2 id=&#34;Organizing-Complex-Interfaces&#34;&gt;Organizing Complex Interfaces&lt;/h2&gt;

&lt;p&gt;I didn&#38;#39;t write App::Cmd for simple programs, though, I wrote it for complex ones. I wanted to write programs that behave like &lt;code&gt;svn&lt;/code&gt; or &lt;code&gt;git&lt;/code&gt;, where the first thing you tell the command-line program is which of its subcommands you want to run. So, maybe the program we wrote above is meant to be run as &lt;code&gt;christmas list&lt;/code&gt;. We also want to have &lt;code&gt;christmas music&lt;/code&gt; to control our MP3 player and &lt;code&gt;christmas cards&lt;/code&gt; to assemble and send off some &lt;a href=&#34;http://advent.rjbs.manxome.org/2009-12-10.html&#34;&gt;mkit&lt;/a&gt; Christmas cards.&lt;/p&gt;

&lt;p&gt;This is easy, we do it like this:&lt;/p&gt;

&lt;ul&gt;

&lt;li&gt;&lt;p&gt;rename Christmas::App to Christmas::App::Command::list&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;replace its &lt;code&gt;use base &#38;#39;App::Cmd::Simple&#38;#39;&lt;/code&gt; with &lt;code&gt;use Christmas::App -command&lt;/code&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;create a new Christmas::App (shown below)&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;create Christmas::App::Command::music and ::cards&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Christmas::App is easy to write; here it is in its entirety:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Christmas::App&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;App::Cmd::Setup&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;-app&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;Extra commands just need those three original methods, for example:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Christmas::App::Command::music&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Christmas::App&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;-command&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;validate_args&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;opt_spec&lt;/span&gt;      &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;execute&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;That&#38;#39;s it. Now the new Christmas::App will be run, it will find all the command classes we&#38;#39;ve written, and it will decide which one to execute based on the first argument to the &lt;code&gt;christmas&lt;/code&gt; command.&lt;/p&gt;

&lt;h2 id=&#34;Other-Cool-Stuff&#34;&gt;Other Cool Stuff&lt;/h2&gt;

&lt;p&gt;When you write a &#38;quot;full&#38;quot; App::Cmd program -- that is, one that uses App::Cmd and not App::Cmd::Simple -- you get a bunch more features for free. For one thing, you get commands for &lt;code&gt;commands&lt;/code&gt; and &lt;code&gt;help&lt;/code&gt; that can list and describe the other available commands. (&lt;code&gt;commands&lt;/code&gt; is what happens by default if you were to run &lt;code&gt;christmas&lt;/code&gt; with no arguments, but you can change that by writing a &lt;code&gt;default_command&lt;/code&gt; method.)&lt;/p&gt;

&lt;p&gt;You get access to the plugins system, which is woefully underdocumented, but allows you to set up easy to use routines in all your commands, so that you could say, in Christmas::App:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Christmas::App&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;App::Cmd::Setup&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;-app&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;plugins&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;words&#34;&gt;qw(App::Cmd::Plugin::Prompt)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;...and then all your commands could use routines like &lt;code&gt;prompt_yn&lt;/code&gt; or &lt;code&gt;prompt_any_key&lt;/code&gt; without you having to waste keystrokes on ugly method calls to some object delegate.&lt;/p&gt;

&lt;h2 id=&#34;See-Also&#34;&gt;See Also&lt;/h2&gt;

&lt;ul&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/App::Cmd&#34;&gt;App::Cmd&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/App::Cmd::Tester&#34;&gt;App::Cmd::Tester&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/App::Cmd::Simple&#34;&gt;App::Cmd::Simple&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Getopt::Long::Descriptive&#34;&gt;Getopt::Long::Descriptive&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/App::CLI&#34;&gt;App::CLI&lt;/a&gt; - an alternative to App::Cmd (with almost no documentation)&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/MooseX::App::Cmd&#34;&gt;MooseX::App::Cmd&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;</summary><updated>2009-12-14T00:00:00-05:00</updated><category term="Perl"/><category term="RJBS"/></entry><entry><title>Valid Data to All Nations</title><link href="http://advent.rjbs.manxome.org/2009/2009-12-13.html"/><id>http://advent.rjbs.manxome.org/2009/2009-12-13.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h2 id=&#34;Params::Validate-is-Okay&#34;&gt;Params::Validate is Okay&lt;/h2&gt;

&lt;p&gt;The CPAN has quite a few data validation libraries on it. There&#38;#39;s &lt;a href=&#34;https://metacpan.org/module/Params::Validate&#34;&gt;Params::Validate&lt;/a&gt;, &lt;a href=&#34;https://metacpan.org/module/Data::FormValidator&#34;&gt;Data::FormValidator&lt;/a&gt;, and probably at least fifty others. Maybe a lot more. I&#38;#39;ve used a dozen or so of them. Some of them stink, some of them are pretty good. They are, unsurprisingly, pretty Perlocentric. It&#38;#39;s useful, in Perl, to be able to say &#38;quot;I&#38;#39;m expecting an instance of a class that does this interface&#38;quot; or &#38;quot;this part of the data should be a regular expression&#38;quot; or &#38;quot;test this data with a custom callback.&#38;quot;&lt;/p&gt;

&lt;p&gt;The problem with this kind of validator is that it leads to business rules that are only expressible in Perl, or that require substantial post-implementation analysis to translate them into other languages. A while ago, I started to really want to valdiate data in both Perl and JavaScript, specifically data that I was handing back and forth between a Perl web service and two clients, written in Perl and JavaScript. I wanted to be able to validate the I/O in JavaScript, but writing all my validation twice looked like a huge pain that would lead to not wanting to validate at all. I decided I&#38;#39;d look for schema languages.&lt;/p&gt;

&lt;p&gt;I found XML Schema and RELAX NG and a few others meant for XML, but they really didn&#38;#39;t make a lot of sense for the data structures common to the batch of dynamic programming languages I wanted to support. They were very XML oriented, which is fine, because they were supposed to be. I also found Kwalify and JSON Schema, neither of which seemed really well done to me, for one reason or another. After some token pleading with friends (&#38;quot;Please talk me out of writing a schema system!&#38;quot;) I decided to write my own.&lt;/p&gt;

&lt;h2 id=&#34;Rx-Schema&#34;&gt;Rx Schema&lt;/h2&gt;

&lt;p&gt;The Rx Schema system is very simple. It&#38;#39;s meant to be easy to extend with your own datatypes, but to guarantee only a small set of core types that map to core datatypes in many common languages. We can start with this data structure (shown here as Perl):&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$data&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;Armand Assante&#39;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;disposition&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;nice&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;present&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Wii&#39;&lt;/span&gt;   &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;Ricardo Signes&#39;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;disposition&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;nice&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;present&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Sleep&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;Violet Beauregarde&#39;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;disposition&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;naughty&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;We&#38;#39;ll make a slightly tortured schema for this, just to show off a few things. Here, I&#38;#39;m representing the schema in &lt;a href=&#34;http://yaml.org&#34;&gt;YAML&lt;/a&gt; for readability, but they&#38;#39;re really just data structures. You could write it in Perl. I usually use JSON.&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;synPreProc&#34;&gt;---&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;synIdentifier&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;:&lt;/span&gt; //map&lt;br /&gt;&lt;span class=&#34;synIdentifier&#34;&gt;values&lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;:&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;synIdentifier&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;:&lt;/span&gt; //any&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;synIdentifier&#34;&gt;of&lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;  :&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;synStatement&#34;&gt;- &lt;/span&gt;&lt;span class=&#34;synIdentifier&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;:&lt;/span&gt; //rec&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;synIdentifier&#34;&gt;required&lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;:&lt;/span&gt; disposition: &lt;span class=&#34;synSpecial&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;synIdentifier&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;:&lt;/span&gt; //str, &lt;span class=&#34;synIdentifier&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;synConstant&#34;&gt;&#39;naughty&#39;&lt;/span&gt; &lt;span class=&#34;synSpecial&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;synStatement&#34;&gt;- &lt;/span&gt;&lt;span class=&#34;synIdentifier&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;:&lt;/span&gt; //rec&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;synIdentifier&#34;&gt;required&lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;:&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;synIdentifier&#34;&gt;present&lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;:&lt;/span&gt; //str&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;synIdentifier&#34;&gt;disposition&lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;synSpecial&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;synIdentifier&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;:&lt;/span&gt; //str, &lt;span class=&#34;synIdentifier&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;synConstant&#34;&gt;&#39;nice&#39;&lt;/span&gt; &lt;span class=&#34;synSpecial&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;In other words, we require a hashref. Each value is a hashref with either one or two entries. One must be disposition. If it&#38;#39;s naughty, there will be no other entries. If it&#38;#39;s &#38;quot;nice&#38;quot; there must be an entry for present, which must be a string.&lt;/p&gt;

&lt;p&gt;It&#38;#39;s easy to use this schema to validate things:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Data::Rx&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$schema&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Data::Rx&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;make_schema&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$that_structure_above&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;unless&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$schema&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;check&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$input&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;die&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;invalid input!&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;But the whole point was to have this work in many languages, and it does:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;synIdentifier&#34;&gt;var&lt;/span&gt; rx = &lt;span class=&#34;synStatement&#34;&gt;new&lt;/span&gt; Rx;&lt;br /&gt;&lt;span class=&#34;synIdentifier&#34;&gt;var&lt;/span&gt; schema = Rx.makeSchema( structure );&lt;br /&gt;&lt;br /&gt;unless (schema.check( input )) &lt;span class=&#34;synIdentifier&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;synStatement&#34;&gt;throw&lt;/span&gt; &lt;span class=&#34;synConstant&#34;&gt;&#38;quot;invalid input!&#38;quot;&lt;/span&gt;;&lt;br /&gt;&lt;span class=&#34;synIdentifier&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;...or...&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;synPreProc&#34;&gt;require&lt;/span&gt; &lt;span class=&#34;synSpecial&#34;&gt;&#39;&lt;/span&gt;&lt;span class=&#34;synConstant&#34;&gt;Rx&lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;&#39;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;rx = &lt;span class=&#34;synType&#34;&gt;Rx&lt;/span&gt;.new&lt;br /&gt;schema = &lt;span class=&#34;synType&#34;&gt;Rx&lt;/span&gt;.make_schema( structure )&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;unless&lt;/span&gt; schema.check( input )&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;synStatement&#34;&gt;throw&lt;/span&gt; &lt;span class=&#34;synSpecial&#34;&gt;&#38;quot;&lt;/span&gt;&lt;span class=&#34;synConstant&#34;&gt;invalid input!&lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;&#38;quot;&lt;/span&gt;;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;There are other implementations, too.&lt;/p&gt;

&lt;p&gt;The Rx schema system is easy to extend. If you want to use regular expressions you can use the PCRE extension, which many language will be able to implement, then you can write:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;synPreProc&#34;&gt;---&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;synIdentifier&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;:&lt;/span&gt; /pcre/str&lt;br /&gt;&lt;span class=&#34;synIdentifier&#34;&gt;regex&lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;synConstant&#34;&gt;&#39;\A867-[5309]{4}\z&#39;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;h2 id=&#34;Coming-Features-or:-Missing-Features-&#34;&gt;Coming Features (or: Missing Features)&lt;/h2&gt;

&lt;p&gt;Right now, the various releases of Rx can only check whether or not something is valid. Obviously it&#38;#39;s much more useful to be able to know &lt;i&gt;why&lt;/i&gt; something isn&#38;#39;t valid, if it fails. This is being implemented (in the &lt;code&gt;struct-fail&lt;/code&gt; branch), although development has been on hold while I work on some other projects. Once that works, Rx Schema will be much more useful.&lt;/p&gt;

&lt;p&gt;I&#38;#39;ve often talked about other ideas that could built atop Rx like RPC, URI templating, and API library autogeneration. Although I&#38;#39;d love to work on them, I think it&#38;#39;s time to admit that I don&#38;#39;t see them happening in the near future unless somebody decides to really push for it. For now, a portable schema language is all I&#38;#39;m aiming for -- and I think that&#38;#39;s enough for me!&lt;/p&gt;

&lt;h2 id=&#34;See-Also&#34;&gt;See Also&lt;/h2&gt;

&lt;ul&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;http://rjbs.manxome.org/rx&#34;&gt;Rx Schema&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Data::Rx&#34;&gt;Data::Rx&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Data::Rx::TypeBundle::Perl&#34;&gt;Data::Rx::TypeBundle::Perl&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;</summary><updated>2009-12-13T00:00:00-05:00</updated><category term="Perl"/><category term="RJBS"/></entry><entry><title>E-mail Made Simple</title><link href="http://advent.rjbs.manxome.org/2009/2009-12-12.html"/><id>http://advent.rjbs.manxome.org/2009/2009-12-12.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h2 id=&#34;Okay-I-Lied&#34;&gt;Okay, I Lied&lt;/h2&gt;

&lt;p&gt;I got a decent amount of angry comments on &lt;a href=&#34;http://advent.rjbs.manxome.org/2009-12-10.html&#34;&gt;Thursday&#38;#39;s post&lt;/a&gt; about &lt;a href=&#34;https://metacpan.org/module/Email::MIME::Kit&#34;&gt;Email::MIME::Kit&lt;/a&gt;. It seems people are sick of my insistance that e-mail is really complicated and they want me to publicly admit that it&#38;#39;s simple.&lt;/p&gt;

&lt;p&gt;I admit it. E-mail is pretty much just a dumped hash, then a bunch of lines, and maybe some attached files at the end. I&#38;#39;ve written some code to show off how easy things can be, if you just accept that e-mail is simple. This code is the acme of simplicity and the acme of utility.&lt;/p&gt;

&lt;p&gt;It doesn&#38;#39;t use any objects or special variables or functions. It just lets you put data into a structured variable, and then you can send it.&lt;/p&gt;

&lt;h2 id=&#34;EMail::Acme&#34;&gt;E&#38;#39;Mail::Acme&lt;/h2&gt;

&lt;h3 id=&#34;Setting-up-the-Header&#34;&gt;Setting up the Header&lt;/h3&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;E&#39;Mail::Acme&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$e_mail&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;E&#39;Mail::Acme&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# Now we have our e-mail variable, so we can put some headers in it.&lt;br /&gt;# Headers are just a hash, remember?&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$e_mail&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;From&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;literal&#34;&gt;q&#38;lt;Ricardo Signes &#38;lt;rjbs@example.com&#38;gt;&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# ...and we can get multiple headers easily enough, just assign a few times:&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$e_mail&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;To&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;literal&#34;&gt;q&#38;lt;Santa Claus &#38;lt;santa@north-pole.mil&#38;gt;&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$e_mail&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;To&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;literal&#34;&gt;q&#38;lt;Kris Kringle &#38;lt;kk@macys.com&#38;gt;&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;So, easy! The header is just a hash, like you&#38;#39;d expect.&lt;/p&gt;

&lt;h3 id=&#34;Setting-up-the-Body&#34;&gt;Setting up the Body&lt;/h3&gt;

&lt;p&gt;The body is just a bunch of lines of text. In other words, an array. We can add lines easily enough.&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;word&#34;&gt;push&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$e_mail&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Dear Santa,&#38;quot;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;&#38;quot;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Here are some things I want:&#38;quot;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@things_i_want&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;&#38;quot;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Please gimme.&#38;quot;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;&#38;quot;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;-- &#38;quot;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;rjbs&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;Great. Of course, that looks pretty ridiculous. Probably we wanted to just do this:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;word&#34;&gt;push&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$e_mail&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;backtick&#34;&gt;`cat /tmp/mutt-terrordome-2608-9063-429`&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;And just to show that we&#38;#39;re not limited to the world of boring &#38;quot;single part&#38;quot; e-mails, we&#38;#39;ll attach a little incentive.&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;comment&#34;&gt;# first, we make an attachment&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$attach&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;E&#39;Mail::Acme&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$attach&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;content-type&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;image/jpeg&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;push&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$attach&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;backtick&#34;&gt;`cat amazon-giftcert.jpg`&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# then we attach it&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;push&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$e_mail&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$attach&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;h3 id=&#34;Sending-our-Message&#34;&gt;Sending our Message&lt;/h3&gt;

&lt;p&gt;Sure, we could bring in some modern, best-practice library like Email::Send:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;word&#34;&gt;Email::Send&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;send&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;double&#34;&gt;&#38;quot;$e_mail&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;...but we&#38;#39;d just be back to these ridiculous object-oriented interface that clutter up our simple e-mail handling. We set up our e-mail object, and now we want to do something with it. There&#38;#39;s only one thing we do with e-mail, right? We send it! All we have to do is tell Perl we want to do (that thing with) the e-mail:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;word&#34;&gt;do&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;&#38;amp;&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$e_mail&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;We could also have written &lt;code&gt;$e_mail-&#38;gt;()&lt;/code&gt;, but the arrow notation unnecessarily reminds me of objects, so I try to avoid it.&lt;/p&gt;

&lt;h2 id=&#34;Sane-Simple-Sensisble&#34;&gt;Sane, Simple, Sensisble&lt;/h2&gt;

&lt;p&gt;So, there you have it. E-mail handling made simple and straightforward, just like you&#38;#39;d like it. Use it everywhere!&lt;/p&gt;

&lt;h2 id=&#34;See-Also&#34;&gt;See Also&lt;/h2&gt;

&lt;ul&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/E&#38;#39;Mail::Acme&#34;&gt;E&#38;#39;Mail::Acme&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;http://www.perlfoundation.org/perl5/index.cgi?acme&#34;&gt;Acme::&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;</summary><updated>2009-12-12T00:00:00-05:00</updated><category term="Perl"/><category term="RJBS"/></entry><entry><title>Giving the Gift of Code</title><link href="http://advent.rjbs.manxome.org/2009/2009-12-11.html"/><id>http://advent.rjbs.manxome.org/2009/2009-12-11.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h2 id=&#34;I-Hate-Wrapping&#34;&gt;I Hate Wrapping&lt;/h2&gt;

&lt;p&gt;I like to give people things that they like. It&#38;#39;s nice for someone to open a present and find just the thing they wanted -- or better, something that they didn&#38;#39;t know they wanted, but that they&#38;#39;re elated to receive. It&#38;#39;s a nice feeling. I just don&#38;#39;t like wrapping presents. I have to pick wrapping paper, measure it, cut it, tape it, and try not to make it look like a five year-old did it. I generally fail at all of these tasks and hand people presents that are balled up in tape and crumpled paper.&lt;/p&gt;

&lt;p&gt;It&#38;#39;s the same feeling I get when I release code to the CPAN: I&#38;#39;m excited that people might find it useful, even if they hadn&#38;#39;t realized they&#38;#39;d wanted something like that -- but I&#38;#39;m annoyed at the idea of writing up all the stupid boilerplate: generic hunks of Pod, build files, the same tests I use everywhere else, license documents. It&#38;#39;s just a pain, and I still end up with a big red &#38;quot;You forgot the README!&#38;quot; light flashing at me on &lt;a href=&#34;http://cpants.perl.org&#34;&gt;CPANTS&lt;/a&gt;. At least, I used to.&lt;/p&gt;

&lt;p&gt;First, to fight this problem, I started using &lt;a href=&#34;https://metacpan.org/module/Module::Starter&#34;&gt;Module::Starter&lt;/a&gt;, and I contributed a number of changes to make it easier to extend. I didn&#38;#39;t get it very easy to extend though, just slightly more than it had been. In the end, too, it really only got you &lt;i&gt;started&lt;/i&gt;, as the name suggested. Every time you wanted to make a new release or add a file or change something you&#38;#39;d put in all the files, you realized that Module::Starter stopped being useful well before your first release.&lt;/p&gt;

&lt;p&gt;I tried to use &lt;a href=&#34;https://metacpan.org/module/Module::Install&#34;&gt;Module::Install&lt;/a&gt; to deal with this problem, and it helped a little. It could add a few files that I&#38;#39;d need generated like license documents or tests. It just didn&#38;#39;t do enough -- and it was such a pain to extend, being built with weird fundamental design decisions atop the ancient and insane &lt;a href=&#34;https://metacpan.org/module/ExtUtils::MakeMaker&#34;&gt;ExtUtils::MakeMaker&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&#34;My-Own-Private-Gift-Counter&#34;&gt;My Own Private Gift Counter&lt;/h2&gt;

&lt;p&gt;Finally I decided that all I really wanted was a way to make &lt;code&gt;make install&lt;/code&gt; way, way more powerful and hookable. I made a little flowchart of the steps I wanted to perform and then build a little skeleton of code to hang those steps on, and that skeleton was &lt;a href=&#34;https://metacpan.org/module/Dist::Zilla&#34;&gt;Dist::Zilla&lt;/a&gt;. Dist::Zilla, as the name suggests, is an absolute monster. It only needs to be run by maintainers of CPAN distribution, not installers, so it doesn&#38;#39;t shy away from demanding &lt;a href=&#34;http://deps.cpantesters.org/?module=Dist::Zilla;perl=latest&#34;&gt;all sorts of hefty prerequisites&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here&#38;#39;s how &lt;i&gt;I&lt;/i&gt; use Dist::Zilla, more or less, although there&#38;#39;s more than one way to do it:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  ~$ cd code
  ~/code$ dzil new My-Project
  will create new dist My-Project in /Users/rjbs/code/My-Project

  ~/code$ cd My-Project
  ~/code/My-Project$ vi dist.ini&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Most of my &lt;i&gt;dist.ini&lt;/i&gt;, the master configuration file, is set up for me already -- it&#38;#39;s only about five lines -- but I edit it a bit to make it look like this:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;synType&#34;&gt;name    =&lt;/span&gt; My-Project&lt;br /&gt;&lt;span class=&#34;synType&#34;&gt;author  =&lt;/span&gt; Ricardo Signes &#38;lt;rjbs@cpan.org&#38;gt;&lt;br /&gt;&lt;span class=&#34;synType&#34;&gt;license =&lt;/span&gt; Perl_5&lt;br /&gt;&lt;span class=&#34;synType&#34;&gt;copyright_holder =&lt;/span&gt; Ricardo Signes&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synSpecial&#34;&gt;[@RJBS]&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;synSpecial&#34;&gt;[@Git]&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;synSpecial&#34;&gt;[AutoPrereq]&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;Now I&#38;#39;m ready to start coding. I&#38;#39;ll make a &lt;i&gt;t/my-tests.t&lt;/i&gt; and &lt;i&gt;lib/My/Project.pm&lt;/i&gt;. My module might look something like this:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;br /&gt;15:&#38;nbsp;&lt;br /&gt;16:&#38;nbsp;&lt;br /&gt;17:&#38;nbsp;&lt;br /&gt;18:&#38;nbsp;&lt;br /&gt;19:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;strict&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;My::Project&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# ABSTRACT: our top-secret project for playing bowling against WOPR&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Games::Bowling::Scorecard&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Games::War::Nuclear::Thermonuclear::Global&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Path::Resolver&lt;/span&gt; &lt;span class=&#34;float&#34;&gt;2.012&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;pod&#34;&gt;=method play_a_game&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;$project-&#38;gt;play_a_game($num_of_players);&lt;br /&gt;&lt;br /&gt;This method starts a game.  It&#39;s a strange game.&lt;br /&gt;&lt;br /&gt;=cut&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;play_a_game&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;You can load up your &lt;i&gt;Changes&lt;/i&gt;, too, just adding the details of your release so the file looks like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  Revision history for {{$dist-&#38;gt;name}}

  {{$NEXT}}
            first release
            doesn&#38;#39;t handle zero players
            tends to destroy civilization&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That&#38;#39;s it.&lt;/p&gt;

&lt;p&gt;Now, when you run &lt;code&gt;dzil release&lt;/code&gt;, this happens:&lt;/p&gt;

&lt;ul&gt;

&lt;li&gt;&lt;p&gt;abort if you&#38;#39;re not all committed to git&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;determine all prereqs by finding &#38;quot;use&#38;quot; and similar statements&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;write out a README, LICENSE, Makefile.PL, MANIFEST, META.yml and META.json&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;decide on the next release&#38;#39;s version number&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;defined &lt;code&gt;$VERSION&lt;/code&gt; in all your packages&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;add a NAME, VERSION, LICENSE, and AUTHORS section to all the Pod&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;turn all &lt;code&gt;=method&lt;/code&gt; commands into grouped &#38;quot;normal&#38;quot; Pod&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;update the changelog with the new version and the current date/time&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;build a tarball and upload it to PAUSE (submit it for CPAN index)&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;commit the changes to the changelog file&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tag the release&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;push the changes and tags to the remote git repository&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I&#38;#39;ve actually left out a few steps that are very useful but harder to explain. All of those steps happen for each release, so you can reconfigure them all each time without having to update a lot of embedded boilerplate code -- the kind you&#38;#39;d end up with, with other distribution-creation systems.&lt;/p&gt;

&lt;p&gt;Finally, all those steps are configurable. I described the configuration that I showed, but you could use fewer plugins, or more plugins, or just different plugins. If you want to maintain your own list of prereqs, you can. If you want to write your own &lt;i&gt;MANIFEST&lt;/i&gt;, you can do that -- and there&#38;#39;s even a plugin to sanity-check it for you when you try to build a release.&lt;/p&gt;

&lt;p&gt;By making it so easy to wrap up and deliver your code, Dist::Zilla lets you just enjoy giving the gift itself -- so you&#38;#39;ll be eager to do it all the more often!&lt;/p&gt;

&lt;h2 id=&#34;See-Also&#34;&gt;See Also&lt;/h2&gt;

&lt;ul&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Dist::Zilla&#34;&gt;Dist::Zilla&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Dist::Zilla::PluginBundle::RJBS&#34;&gt;Dist::Zilla::PluginBundle::RJBS&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Dist::Zilla::PluginBundle::Git&#34;&gt;Dist::Zilla::PluginBundle::Git&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Module::Starter&#34;&gt;Module::Starter&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;</summary><updated>2009-12-11T00:00:00-05:00</updated><category term="Perl"/><category term="RJBS"/></entry><entry><title>MIME, Dreaming of a White Christmas</title><link href="http://advent.rjbs.manxome.org/2009/2009-12-10.html"/><id>http://advent.rjbs.manxome.org/2009/2009-12-10.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h2 id=&#34;Making-an-Email&#34;&gt;Making an Email&lt;/h2&gt;

&lt;p&gt;I maintain a lot of &lt;a href=&#34;http://emailproject.perl.org&#34;&gt;Perl email code&lt;/a&gt;, and one of the most popular modules I maintain is &lt;a href=&#34;https://metacpan.org/module/Email::Simple&#34;&gt;Email::Simple&lt;/a&gt;. It was written to make a very simple class for looking at email documents. It didn&#38;#39;t let you do much, and its implementation assumed that you wouldn&#38;#39;t even go very far using the interface it provided. That&#38;#39;s fine: it said, &#38;quot;here is a very simple tool for performing very simple operations on this very complicated thing, email.&#38;quot; Unfortunately, sometimes we latch onto the dream -- the other way to read Email::Simple&#38;#39;s name -- that email, itself, is simple. Sadly, it just isn&#38;#39;t.&lt;/p&gt;

&lt;p&gt;One of the most common kinds of email to send is a form letter. You want to send an invoice or welcome message, and you want to fill in the details for this purchase or customer. This is a simple thing to think about doing, and it&#38;#39;s something we do a lot, so it seems like it should be really straightforward. Frustratingly, this is about as simple as it gets:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;br /&gt;15:&#38;nbsp;&lt;br /&gt;16:&#38;nbsp;&lt;br /&gt;17:&#38;nbsp;&lt;br /&gt;18:&#38;nbsp;&lt;br /&gt;19:&#38;nbsp;&lt;br /&gt;20:&#38;nbsp;&lt;br /&gt;21:&#38;nbsp;&lt;br /&gt;22:&#38;nbsp;&lt;br /&gt;23:&#38;nbsp;&lt;br /&gt;24:&#38;nbsp;&lt;br /&gt;25:&#38;nbsp;&lt;br /&gt;26:&#38;nbsp;&lt;br /&gt;27:&#38;nbsp;&lt;br /&gt;28:&#38;nbsp;&lt;br /&gt;29:&#38;nbsp;&lt;br /&gt;30:&#38;nbsp;&lt;br /&gt;31:&#38;nbsp;&lt;br /&gt;32:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$html_template&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;heredoc&#34;&gt;&#38;lt;&#38;lt;&#39;END_HTML&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;heredoc_content&#34;&gt;&#38;lt;h1&#38;gt;Welcome to Yoyodyne, [% customer.realname %]!&#38;lt;/h1&#38;gt;&lt;br /&gt;&lt;br /&gt;&#38;lt;p&#38;gt;You signed up with the following address:&#38;lt;/p&#38;gt;&lt;br /&gt;&#38;lt;pre&#38;gt;[% customer.address.envelope_style %]&#38;lt;/pre&#38;gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;heredoc_terminator&#34;&gt;END_HTML&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$text_template&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;heredoc&#34;&gt;&#38;lt;&#38;lt;&#39;END_TEXT&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;heredoc_content&#34;&gt;Welcome to Yoyodyne, [% customer.realname %]!&lt;br /&gt;&lt;br /&gt;You signed up with this billing address:&lt;br /&gt;[% customer.address %]&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;heredoc_terminator&#34;&gt;END_TEXT&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$email&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Email::MIME&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;create&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;header&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;From&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Customer Service &#38;lt;noreply@example.com&#38;gt;&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;To&lt;/span&gt;   &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$customer&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;realname&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;.&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot; &#38;lt;&#38;quot;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;.&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$customer&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;email&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;.&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;&#38;gt;&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;Subject&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Welcome to Yoyodyne!&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;attributes&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;content_type&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;multipart/alternative&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;parts&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;Email::MIME&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;create&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;attributes&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;content_type&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;text/plain&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;body&lt;/span&gt;       &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;render_tt&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$text_template&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;customer&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$customer&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;})&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;Email::MIME&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;create&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;attributes&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;content_type&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;text/html&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;body&lt;/span&gt;       &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;render_tt&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$html_template&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;customer&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$customer&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;})&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;Yow! That&#38;#39;s a lot of code, and a lot of it looks stupid and boring. Also, there are a bunch of bugs. If the customer&#38;#39;s real name contains special characters (and I mean more than just 8-bit), the headers will be illegal. We probably made a mistake by stringifying the customer&#38;#39;s &#38;quot;address&#38;quot; attribute in the plain text template (but not in the HTML template). We didn&#38;#39;t specify any kind of encoding for the text parts, so there might be more bugs there.&lt;/p&gt;

&lt;p&gt;Email::Stuff is designed to make this a bunch simpler, replacing the &lt;code&gt;Email::MIME-&#38;gt;create&lt;/code&gt; call with:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$email&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Email::Stuff&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;to&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$customer&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;realname&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;.&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot; &#38;lt;&#38;quot;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;.&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$customer&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;email&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;.&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;&#38;gt;&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;from&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;Customer Service &#38;lt;noreply@example.com&#38;gt;&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;subject&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;Welcome to Yoyodyne!&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;text_body&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;render_tt&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$text_template&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;customer&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$customer&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}))&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;html_body&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;render_tt&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$html_template&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;customer&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$customer&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}))&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;email&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;That&#38;#39;s a lot better! Still, we&#38;#39;re going to end up with encoding bugs, our templates diverged, and there are other more subtle problems. For example, what if we accidentally pass in the wrong kind of object for &lt;code&gt;$customer&lt;/code&gt;? It might throw an exception when we try to call methods on it setting the &lt;code&gt;to&lt;/code&gt; header, but it might not happen until the Template Toolkit template, so that exception might just translate to missing data. It&#38;#39;s a mess.&lt;/p&gt;

&lt;h2 id=&#34;Making-Email-Simple&#34;&gt;Making Email Simple&lt;/h2&gt;

&lt;p&gt;Email::MIME::Kit is designed to make it easy to write templates that get constructed into one email, abstracting the boring details and making it as easy as possible to add new features.&lt;/p&gt;

&lt;p&gt;Here&#38;#39;s an example of a fully-loaded message kit (or mkit (pron. &#38;quot;em kit&#38;quot;), as we call them at work), both on disk and in the code that sends it. We&#38;#39;ll make a directory, &lt;i&gt;welcome.mkit&lt;/i&gt;, which is the mkit itself. In it, we&#38;#39;ll stick a bunch of files, starting with &lt;i&gt;manifest.yaml&lt;/i&gt; (often &lt;i&gt;manifest.json&lt;/i&gt; instead), which configures the kit as a whole:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;synIdentifier&#34;&gt;validator&lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;:&lt;/span&gt; Rx&lt;br /&gt;&lt;span class=&#34;synIdentifier&#34;&gt;renderer&lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt; :&lt;/span&gt; TT &lt;br /&gt;&lt;span class=&#34;synIdentifier&#34;&gt;assembler&lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;:&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;- &lt;/span&gt;Markdown&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;- &lt;/span&gt;&lt;span class=&#34;synIdentifier&#34;&gt;html_wrapper&lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;:&lt;/span&gt; wrapper.html&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;synIdentifier&#34;&gt;text_wrapper&lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;:&lt;/span&gt; wrapper.txt&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synIdentifier&#34;&gt;header&lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;:&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;- &lt;/span&gt;&lt;span class=&#34;synIdentifier&#34;&gt;From&lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;:&lt;/span&gt; Customer Service &#38;lt;noreply@example.com&#38;gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;- &lt;/span&gt;&lt;span class=&#34;synIdentifier&#34;&gt;To&lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;  :&lt;/span&gt; &lt;span class=&#34;synConstant&#34;&gt;&#39;[% customer.realname %] &#38;lt;[% customer.email %]&#38;gt;&#39;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;- &lt;/span&gt;&lt;span class=&#34;synIdentifier&#34;&gt;Subject&lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;:&lt;/span&gt; Welcome to Yoyodyne!&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synIdentifier&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;:&lt;/span&gt; body.mkdn&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;This file explains how the message will be built. It says we&#38;#39;ll validate the input using &lt;a href=&#34;http://rjbs.manxome.org/rx&#34;&gt;Rx&lt;/a&gt;, render templates using &lt;a href=&#34;http://template-toolkit.org/&#34;&gt;TT2&lt;/a&gt;, and then construct the message using the Markdown-style assembler. The Markdown assembler is the least straightforward bit of that, so let&#38;#39;s look at it first.&lt;/p&gt;

&lt;p&gt;It says: We&#38;#39;ve got a file, &lt;i&gt;body.mkdn&lt;/i&gt;, which is Markdown. We&#38;#39;ll render that Markdown as a TT2 template, wrap it up in some boilerplate, and use that as the plain text part. Then we&#38;#39;ll take that Markdown and render it into HTML, wrap that in some boilerplate, and use that as the HTML part.&lt;/p&gt;

&lt;p&gt;In other words, we&#38;#39;ll get a easy to read plain text part and a pretty HTML part, and they&#38;#39;ll have identical content. So, for the message we were sending, above, we might have this Markdown file:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;synSpecial&#34;&gt;#&lt;/span&gt; Welcome to Yoyodyne, [% customer.realname %]!&lt;br /&gt;&lt;br /&gt;You signed up with the following address:&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;[% customer.address.envelope_style %]&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;Unless told otherwise, Email::MIME::Kit assumes you&#38;#39;re working in Unicode with files stored in UTF-8 and takes care of encoding for you. Now you&#38;#39;ve got one template, identical across both alternatives, and all that remains is to validate the input. We declared we&#38;#39;d use the Rx schema system, and we&#38;#39;ll put a schema in &lt;i&gt;rx.json&lt;/i&gt; in our mkit directory.&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;synIdentifier&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;synConstant&#34;&gt;&#38;quot;type&#38;quot;&lt;/span&gt;: &lt;span class=&#34;synConstant&#34;&gt;&#38;quot;//rec&#38;quot;&lt;/span&gt;,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;synConstant&#34;&gt;&#38;quot;required&#38;quot;&lt;/span&gt;: &lt;span class=&#34;synIdentifier&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;synConstant&#34;&gt;&#38;quot;customer&#38;quot;&lt;/span&gt;: &lt;span class=&#34;synIdentifier&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;synConstant&#34;&gt;&#38;quot;type&#38;quot;&lt;/span&gt;: &lt;span class=&#34;synConstant&#34;&gt;&#38;quot;/perl/obj&#38;quot;&lt;/span&gt;,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;synConstant&#34;&gt;&#38;quot;does&#38;quot;&lt;/span&gt;: &lt;span class=&#34;synConstant&#34;&gt;&#38;quot;Yoyo::Customer&#38;quot;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;synIdentifier&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;synIdentifier&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;synIdentifier&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;Now we&#38;#39;ll refuse to even build an email unless we were given a valid customer object. How do we actually build the message? It&#38;#39;s easy.&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$kit&lt;/span&gt;   &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Email::MIME::Kit&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;({&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;source&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;./welcome.mkit&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$email&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$kit&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;assemble&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;({&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;customer&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$customer&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;At this point, we&#38;#39;ve written fewer total lines of code than we did in the very first example and have gotten a far superior result: fewer bugs are possible and all the &#38;quot;this email as a template&#38;quot; data are stored safely out of the way. This is also just the tip of the iceberg: mkits make it easy to write much more powerful templates and to share common components. They can also be used with fewer of their features, getting you fewer bug-preventing measures, but still plenty of benefit over other techniques.&lt;/p&gt;

&lt;p&gt;In almost all non-trivial cases, mkits are a win over other methods of sending form letters -- and Email::MIME::Kit is still getting better.&lt;/p&gt;

&lt;h2 id=&#34;See-Also&#34;&gt;See Also&lt;/h2&gt;

&lt;ul&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Email::MIME::Kit&#34;&gt;Email::MIME::Kit&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Email::MIME::Kit::Assembler::Markdown&#34;&gt;Email::MIME::Kit::Assembler::Markdown&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Email::MIME::Kit::Renderer::TT&#34;&gt;Email::MIME::Kit::Renderer::TT&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Email::MIME::Kit::Validator::Rx&#34;&gt;Email::MIME::Kit::Validator::Rx&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Email::MIME::Kit::KitReader::SWAK&#34;&gt;Email::MIME::Kit::KitReader::SWAK&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Email::MIME&#34;&gt;Email::MIME&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Email::Stuff&#34;&gt;Email::Stuff&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;</summary><updated>2009-12-10T00:00:00-05:00</updated><category term="Perl"/><category term="RJBS"/></entry><entry><title type="html">Like &#38;lt;DATA&#38;gt;, Only Less Stupid</title><link href="http://advent.rjbs.manxome.org/2009/2009-12-09.html"/><id>http://advent.rjbs.manxome.org/2009/2009-12-09.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h2 id=&#34;First-An-Alternative&#34;&gt;First, An Alternative&lt;/h2&gt;

&lt;p&gt;Data::Section was actually written when I realized I couldn&#38;#39;t use Inline::Files. I&#38;#39;d wanted to use that ages ago, but it had a number of little problems. The biggest problem, unfortunately, was that it just tried to be way, way too powerful.&lt;/p&gt;

&lt;p&gt;I like overpowered modules as much as the next guy, but here&#38;#39;s about where I draw the line: Inline::Files is a form of source filter, and includes this warning:&lt;/p&gt;



&lt;!-- This should really work with =over, but doesn&#39;t. - rjbs, 2009-11-23 --&gt;&lt;blockquote&gt; It is possible that this module may overwrite the source code in files that use it. To protect yourself against this possibility, you are strongly advised to use the -backup option described in &#34;Safety first&#34;.  &lt;/blockquote&gt;

&lt;h2 id=&#34;The-DATA-Section&#34;&gt;The DATA Section&lt;/h2&gt;

&lt;p&gt;Data::Section (and Inline::Files) are meant to make the &lt;code&gt;__DATA__&lt;/code&gt; section both more powerful and more reliable. For those of you who haven&#38;#39;t encountered it, Perl lets you access a virtual filehandle that reads non-code content at the end of your program file. In other words, if you write this program:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$total&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;readline&#34;&gt;&#38;lt;DATA&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;chomp&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;printf&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Got number: %u\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$total&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;+=&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;printf&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Total: %u\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$total&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;separator&#34;&gt;__DATA__&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;data&#34;&gt;2&lt;br /&gt;4&lt;br /&gt;6&lt;br /&gt;8&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;...then your program would output:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  Got number: 2
  Got number: 4
  Got number: 6
  Got number: 8
  Total: 20&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;Why-Data::Section-Beats-DATA&#34;&gt;Why Data::Section Beats DATA&lt;/h2&gt;

&lt;h3 id=&#34;No-Need-to-seek&#34;&gt;No Need to seek&lt;/h3&gt;

&lt;p&gt;There are a few problems with &lt;code&gt;DATA&lt;/code&gt;, though. The most annoying is that you can&#38;#39;t easily seek on it. Its read position is actually relative to the whole source file, so you&#38;#39;d need to try to &lt;code&gt;tell&lt;/code&gt; it first, then save that, and things get messy.&lt;/p&gt;

&lt;p&gt;Data::Section caches your data for you, so you can reread it any time you want.&lt;/p&gt;

&lt;h3 id=&#34;Multiple-Files-Per-Module&#34;&gt;Multiple &#38;quot;Files&#38;quot; Per Module&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;DATA&lt;/code&gt; filehandle is one big entity, but Data::Section lets you provide multiple virtual files in your data:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;br /&gt;15:&#38;nbsp;&lt;br /&gt;16:&#38;nbsp;&lt;br /&gt;17:&#38;nbsp;&lt;br /&gt;18:&#38;nbsp;&lt;br /&gt;19:&#38;nbsp;&lt;br /&gt;20:&#38;nbsp;&lt;br /&gt;21:&#38;nbsp;&lt;br /&gt;22:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Your::Package&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Data::Section&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;-setup&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$sections&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Your::Package&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;merged_section_data&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$filename&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;keys&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$sections&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;printf&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;== %s ==\n%s\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$filename&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Your::Package&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;section_data&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$filename&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;separator&#34;&gt;__DATA__&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;data&#34;&gt;___[ so-far.txt ]___&lt;br /&gt;Sub::Exporter&lt;br /&gt;Number::Nary&lt;br /&gt;Email::Pipemailer::DieHandler&lt;br /&gt;Pod::Coverage::TrustPod&lt;br /&gt;Games::Bowling::Scorecard&lt;br /&gt;__[ coming-up.txt ]__&lt;br /&gt;Mixin::Linewise&lt;br /&gt;App::Cronjob&lt;br /&gt;String::Formatter&lt;br /&gt;Data::Section&lt;br /&gt;Email::MIME::Kit&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;You&#38;#39;ll get two &#38;quot;filenames&#38;quot; and each one will have five lines in it.&lt;/p&gt;

&lt;p&gt;(By the way, that &lt;code&gt;use Data::Section&lt;/code&gt; line? Yeah, that&#38;#39;s all you have to do. Obviously, Data::Section uses Sub::Exporter, so you can rename its methods, and there are a few parameters you can use to customize them.)&lt;/p&gt;

&lt;h3 id=&#34;Inherited-Files&#34;&gt;Inherited Files&lt;/h3&gt;

&lt;p&gt;If you&#38;#39;re wondering what&#38;#39;s &#38;quot;merged&#38;quot; in the &lt;code&gt;merged_section_data&lt;/code&gt; method, it&#38;#39;s inherited files. In other words, if you wrote a subclass of the Your::Package code above, you could add new files in its &lt;code&gt;DATA&lt;/code&gt; section, but the old files would still be accessible -- unless you added a &lt;i&gt;so-far.txt&lt;/i&gt; definition to your subclass. It behaves very much like an overridden method, in that way.&lt;/p&gt;

&lt;h2 id=&#34;Practical-Uses&#34;&gt;Practical Uses&lt;/h2&gt;

&lt;p&gt;When is this useful? It&#38;#39;s great to use instead of here-docs for a lot of cases. It&#38;#39;s also a nice way to avoid having to install and manage text files. A package can store its own bundle of configuration or template files, and it will have methods to access them. Then if you want, you can specialize your pack of template files by subclassing the original one.&lt;/p&gt;

&lt;p&gt;Even without all its new features, the simple ability to never re-seek &lt;code&gt;DATA&lt;/code&gt; is a big one. (Please note that Data::Section caches the contents, it doesn&#38;#39;t magically take care of re-seeking. That ends up being a real problem.) &lt;code&gt;DATA&lt;/code&gt; is a global variable, and if code ever tries to read from it more than once, the second time will fail, and that is a really annoying bug to track down -- trust me, I&#38;#39;ve had to do so many times. So, forget about plain old &lt;code&gt;DATA&lt;/code&gt; sections and start using Data::Section. Your future self will thank you.&lt;/p&gt;

&lt;h2 id=&#34;See-Also&#34;&gt;See Also&lt;/h2&gt;

&lt;ul&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Data::Section&#34;&gt;Data::Section&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Inline::Files&#34;&gt;Inline::Files&lt;/a&gt; - interesting, but don&#38;#39;t use it&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;</summary><updated>2009-12-09T00:00:00-05:00</updated><category term="Perl"/><category term="RJBS"/></entry><entry><title>%{adj}s %s{holiday}s!</title><link href="http://advent.rjbs.manxome.org/2009/2009-12-08.html"/><id>http://advent.rjbs.manxome.org/2009/2009-12-08.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h2 id=&#34;sprintf-is-My-Favorite-Chainsaw&#34;&gt;&lt;code&gt;sprintf&lt;/code&gt; is My Favorite Chainsaw&lt;/h2&gt;

&lt;p&gt;There are a lot of horribly overcomplicated builtins, not just in Perl, but in many languages. Some people like Lisp&#38;#39;s &lt;code&gt;format&lt;/code&gt; best -- and why not? Like...&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;synSpecial&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;synStatement&#34;&gt;format&lt;/span&gt; &lt;span class=&#34;synStatement&#34;&gt;nil&lt;/span&gt; &lt;span class=&#34;synConstant&#34;&gt;&#38;quot;~4,&#39;0d-~2,&#39;0d-~2,&#39;0d&#38;quot;&lt;/span&gt; &lt;span class=&#34;synConstant&#34;&gt;2005&lt;/span&gt; &lt;span class=&#34;synConstant&#34;&gt;6&lt;/span&gt; &lt;span class=&#34;synConstant&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;synComment&#34;&gt;; ==&#38;gt; 2005-06-10&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synSpecial&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;synStatement&#34;&gt;format&lt;/span&gt; &lt;span class=&#34;synStatement&#34;&gt;nil&lt;/span&gt; &lt;span class=&#34;synConstant&#34;&gt;&#38;quot;~:(~a~)&#38;quot;&lt;/span&gt; &lt;span class=&#34;synConstant&#34;&gt;&#38;quot;tHe Quick BROWN foX&#38;quot;&lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;)&lt;/span&gt;  &lt;span class=&#34;synComment&#34;&gt;; ==&#38;gt; &#38;quot;The Quick Brown Fox&#38;quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synSpecial&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;synStatement&#34;&gt;format&lt;/span&gt; &lt;span class=&#34;synStatement&#34;&gt;nil&lt;/span&gt; &lt;span class=&#34;synConstant&#34;&gt;&#38;quot;~:r&#38;quot;&lt;/span&gt; &lt;span class=&#34;synConstant&#34;&gt;1234&lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;)&lt;/span&gt;  &lt;span class=&#34;synComment&#34;&gt;; ==&#38;gt; &#38;quot;one thousand two hundred thirty-fourth&#38;quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synSpecial&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;synStatement&#34;&gt;format&lt;/span&gt; &lt;span class=&#34;synStatement&#34;&gt;nil&lt;/span&gt; &lt;span class=&#34;synConstant&#34;&gt;&#38;quot;~:@r&#38;quot;&lt;/span&gt; &lt;span class=&#34;synConstant&#34;&gt;1234&lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;synComment&#34;&gt;; ==&#38;gt; &#38;quot;MCCXXXIIII&#38;quot;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;Right? That&#38;#39;s pretty awesome. Then there&#38;#39;s Perl&#38;#39;s &lt;code&gt;pack&lt;/code&gt;. It&#38;#39;s sort of like a &lt;code&gt;sprintf&lt;/code&gt; designed by an assembly programmer who hates you:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;word&#34;&gt;pack&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;n/a* w/a&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;hello,&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;world&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;   &lt;span class=&#34;comment&#34;&gt;# gives &#38;quot;\000\006hello,\005world&#38;quot;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;There are actually people who like that, and I have seen, with my own eyes, a guy who defended &lt;code&gt;format&lt;/code&gt;:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;synStatement&#34;&gt;format&lt;/span&gt; &lt;span class=&#34;synIdentifier&#34;&gt;STDOUT_TOP &lt;/span&gt;=&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Passwd File&lt;br /&gt;Name                Login    Office   Uid   Gid Home&lt;br /&gt;------------------------------------------------------------------&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;format&lt;/span&gt; &lt;span class=&#34;synIdentifier&#34;&gt;STDOUT &lt;/span&gt;=&lt;br /&gt;&lt;span class=&#34;synConstant&#34;&gt;@&#38;lt;&#38;lt;&#38;lt;&#38;lt;&#38;lt;&#38;lt;&#38;lt;&#38;lt;&#38;lt;&#38;lt;&#38;lt;&#38;lt;&#38;lt;&#38;lt;&#38;lt;&#38;lt;&#38;lt;&#38;lt;&lt;/span&gt; &lt;span class=&#34;synConstant&#34;&gt;@|||||||&lt;/span&gt; &lt;span class=&#34;synConstant&#34;&gt;@&#38;lt;&#38;lt;&#38;lt;&#38;lt;&#38;lt;&#38;lt;@&#38;gt;&#38;gt;&#38;gt;&#38;gt;&lt;/span&gt; &lt;span class=&#34;synConstant&#34;&gt;@&#38;gt;&#38;gt;&#38;gt;&#38;gt;&lt;/span&gt; &lt;span class=&#34;synConstant&#34;&gt;@&#38;lt;&#38;lt;&#38;lt;&#38;lt;&#38;lt;&#38;lt;&#38;lt;&#38;lt;&#38;lt;&#38;lt;&#38;lt;&#38;lt;&#38;lt;&#38;lt;&#38;lt;&#38;lt;&#38;lt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;synIdentifier&#34;&gt;$name&lt;/span&gt;,              &lt;span class=&#34;synIdentifier&#34;&gt;$login&lt;/span&gt;,  &lt;span class=&#34;synIdentifier&#34;&gt;$office&lt;/span&gt;,&lt;span class=&#34;synIdentifier&#34;&gt;$uid&lt;/span&gt;,&lt;span class=&#34;synIdentifier&#34;&gt;$gid&lt;/span&gt;, &lt;span class=&#34;synIdentifier&#34;&gt;$home&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;Well, &lt;code&gt;sprintf&lt;/code&gt; isn&#38;#39;t as awful as any of these, and that&#38;#39;s why I love it... at least if you ignore things like:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;comment&#34;&gt;# Vectors!&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;printf&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;%vd&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;AB\x{100}&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;           &lt;span class=&#34;comment&#34;&gt;# prints &#38;quot;65.66.256&#38;quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;printf&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;version is v%vd\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;$^V&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;     &lt;span class=&#34;comment&#34;&gt;# Perl&#39;s version&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# Put an asterisk &#38;quot;*&#38;quot; before the &#38;quot;v&#38;quot; to override the string to use to&lt;br /&gt;# separate the numbers:&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;printf&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;address is %*vX\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;:&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$addr&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;   &lt;span class=&#34;comment&#34;&gt;# IPv6 address&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;printf&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;%2\$*3\$d %d\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;12&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;34&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# will print &#38;quot; 34 12\n&#38;quot;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;h2 id=&#34;Enough-Settle-down-&#34;&gt;Enough! Settle down!&lt;/h2&gt;

&lt;p&gt;Sorry. I got distracted.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sprintf&lt;/code&gt; is the sweet middle ground between a double-quoted string and Template Toolkit. If you stick to the basics that most people use, it&#38;#39;s a nice simple way to put placeholders in a string, then stick values into it, doing just a little formatting as needed. Here&#38;#39;s how people &lt;i&gt;actually&lt;/i&gt; use &lt;code&gt;sprintf&lt;/code&gt;:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;word&#34;&gt;printf&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Product %s (%s) added for \$%0.2u.\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$product&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$product&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$product&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;price&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;Nice and simple, right? What I really wanted was a way to use these kinds of templates as templates, outside of code. So, for example, I could store the above string in a configuration file without worrying about the order of arguments:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;synSpecial&#34;&gt;[Purchasing]&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;synType&#34;&gt;format =&lt;/span&gt; Product %{id}s (%{name}s) added for $%&lt;span class=&#34;synConstant&#34;&gt;0.2&lt;/span&gt;{price}f&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;Then my program could call:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;word&#34;&gt;printf&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$config&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;purchasing&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$product&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/String::Formatter&#34;&gt;String::Formatter&lt;/a&gt; is all about building routines that make this possible. It&#38;#39;s very flexible, and can probably be tortured into doing all kinds of horrible things (although I hope nobody ever reimplements all of Perl&#38;#39;s &lt;code&gt;sprintf&lt;/code&gt;). Here are just a few simple examples of how you can put String::Formatter to use.&lt;/p&gt;

&lt;h3 id=&#34;object-specific-conversions&#34;&gt;object-specific conversions&lt;/h3&gt;

&lt;p&gt;You can set up format codes that correspond to methods, making a formatting routine that helps convert given objects to strings.&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;String::Formatter&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;method_stringf&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;-as&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;datetimef&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;codes&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;f&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;strftime&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;format_cldr&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;$_[0]&#38;quot;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;datetimef&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;double&#34;&gt;&#38;quot;%{%Y-%m-%d}f is the same as %{yyyy-MM-dd}c.&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;DateTime&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;now&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;h3 id=&#34;generic-method-calling-conversions:&#34;&gt;generic method-calling conversions:&lt;/h3&gt;

&lt;p&gt;You could write a formatter that just calls any method you want:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;String::Formatter&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;stringf&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;-as&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;objectf&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;string_replacer&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;method_call_replace&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# imaginary but easy&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;codes&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;$_&#38;quot;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;objectf&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;double&#34;&gt;&#38;quot;Product %{id}s (%{name}s) added for $%0.2{price}s&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$product&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;h3 id=&#34;custom-conversions&#34;&gt;custom conversions&lt;/h3&gt;

&lt;p&gt;You could write something meant to be used just like &lt;code&gt;sprintf&lt;/code&gt;, but with different conversion routines:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;br /&gt;15:&#38;nbsp;&lt;br /&gt;16:&#38;nbsp;&lt;br /&gt;17:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;String::Formatter&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;stringf&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;codes&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;     &lt;span class=&#34;comment&#34;&gt;# string itself&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;l&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;length&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# length of input string&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;e&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;match&#34;&gt;/[^\x00-\x7F]/&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;?&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;8bit&#39;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;7bit&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# ascii-safeness&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;stringf&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;double&#34;&gt;&#38;quot;My name is %s.  I am about %l feet tall.  I use an %e alphabet.\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;Ricardo&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;ffffff&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;abcchdefghijklmn&#241;opqrrrstuvwxyz&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# Output:&lt;br /&gt;# My name is Ricardo.  I am about 6 feet tall.  I use an 8bit alphabet.&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;h2 id=&#34;and-you-can-make-it-do-lots-more.&#34;&gt;...and you can make it do lots more.&lt;/h2&gt;

&lt;p&gt;String::Formatter does its job in a few phases, and you can replace each or all of those phases per formatter, so it&#38;#39;s easy to write very powerful custom formatting routines. Any time you need to a teeny tiny templating language, consider whether a slightly-improved &lt;code&gt;sprintf&lt;/code&gt; would be enough. You might be surprised how often it will be just right.&lt;/p&gt;

&lt;h2 id=&#34;See-Also&#34;&gt;See Also&lt;/h2&gt;

&lt;ul&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/String::Formatter&#34;&gt;String::Formatter&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/String::Formatter::Cookbook&#34;&gt;String::Formatter::Cookbook&lt;/a&gt; - more detailed examples than seen here&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/String::Format&#34;&gt;String::Format&lt;/a&gt; - String::Formatter&#38;#39;s less powerful ancestor&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Lisp::Fmt&#34;&gt;Lisp::Fmt&lt;/a&gt; - a Lisp-like formatter that you may not use&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;</summary><updated>2009-12-08T00:00:00-05:00</updated><category term="Perl"/><category term="RJBS"/></entry><entry><title>59 23 24 12 * /bin/celebrate</title><link href="http://advent.rjbs.manxome.org/2009/2009-12-07.html"/><id>http://advent.rjbs.manxome.org/2009/2009-12-07.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h2 id=&#34;Solaris-Aint-So-Bad&#34;&gt;Solaris Ain&#38;#39;t So Bad&lt;/h2&gt;

&lt;p&gt;We&#38;#39;ve been using Solaris for most of our servers for quite a while at work now, and there&#38;#39;s no question that it&#38;#39;s made our sysadmin&#38;#39;s life easier. Everybody wants the BOFH to be happy, but there&#38;#39;s often this idea that Solaris will make you, the programmer, miserable. Given the choice between a miserable me and a miserable sysadmin, I know which one I will pick. After all, if worse comes to worst, you can just replace the sysadmin with some more Perl, right?&lt;/p&gt;

&lt;p&gt;(I&#38;#39;m just kidding, Bryan, you&#38;#39;re great.)&lt;/p&gt;

&lt;p&gt;In reality, Solaris is fine. It almost never gets in my way, and that&#38;#39;s because one of the first things that happens to every new Solaris box we build is the installation of the GNU tools. I mean, ZFS and DTrace and zones are great, but Solaris grep is like a trip back to 1982. The one tool that just wasn&#38;#39;t quite easy enough to replace, though, was Solaris cron. In the beginning, as we got more and more servers onto Solaris, more and more of my &lt;code&gt;cron&lt;/code&gt; mailbox started to look like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  Subject: Output from &#38;quot;cron&#38;quot; command
  Subject: Output from &#38;quot;cron&#38;quot; command
  Subject: Output from &#38;quot;cron&#38;quot; command
  Subject: Output from &#38;quot;cron&#38;quot; command
  Subject: Output from &#38;quot;cron&#38;quot; command
  Subject: Output from &#38;quot;cron&#38;quot; command
  Subject: Output from &#38;quot;cron&#38;quot; command
  Subject: Output from &#38;quot;cron&#38;quot; command&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Yeah. That&#38;#39;s just fantastic. Thanks.&lt;/p&gt;

&lt;h2 id=&#34;Keep-the-crond-just-add-more-Perl&#34;&gt;Keep the crond, just add more Perl&lt;/h2&gt;

&lt;p&gt;So, as I said, replacing &lt;code&gt;crond&lt;/code&gt; wasn&#38;#39;t as simple as we wanted it to be, so instead we wrote a wrapper and used &lt;a href=&#34;http://reductivelabs.com/products/puppet/&#34;&gt;Puppet&lt;/a&gt; to make sure that every single cron job used it. The wrapper is &lt;i&gt;cronjob&lt;/i&gt;, which you get when you install &lt;a href=&#34;https://metacpan.org/module/App::Cronjob&#34;&gt;App::Cronjob&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You just replace &#38;quot;some-job&#38;quot; in your &lt;i&gt;crontab&lt;/i&gt; with:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  /usr/local/bin/cronjob -s &#38;#39;nightly llama maintenance&#38;#39; -E -c some-job&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;By default, &lt;code&gt;cronjob&lt;/code&gt; will get a lock for the job. Unless you tell it not to lock, no two jobs with the same subject can be run at once. The default subject is the command to be run, but we&#38;#39;ve overridden it with the &#38;quot;&lt;code&gt;-s&lt;/code&gt;&#38;quot; switch, above. If it gets a lock, it runs the job. Just like normal cron, it will send you the output of the command -- but sometimes that&#38;#39;s really annoying, so we&#38;#39;ve used &#38;quot;&lt;code&gt;-E&lt;/code&gt;&#38;quot; to tell it to only send mail if the command exits with an error condition.&lt;/p&gt;

&lt;p&gt;In addition to sending you the output of the command, it will include a summary of how the job went:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;synType&#34;&gt;From: &#38;quot;cron/lambda.example.com&#38;quot; &lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;&#38;lt;cron@lambda.example.com&#38;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;synType&#34;&gt;To: &lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;root@lambda.example.com&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;synType&#34;&gt;Date:&lt;/span&gt;&lt;span class=&#34;synStatement&#34;&gt; Thu, 19 Nov 2009 03:00:09 -0500&lt;/span&gt;&lt;br /&gt;Subject: FAIL: nightly llama maintenance&lt;br /&gt;&lt;span class=&#34;synStatement&#34;&gt;In-Reply-To: &lt;/span&gt;&lt;span class=&#34;synSpecial&#34;&gt;&#38;lt;73d2be0cc900096550bc3b159b4d86d4@lambda.example.com&#38;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Command: some-job&lt;br /&gt;Time   : 47.5708s&lt;br /&gt;Status : {{{&#38;quot;core&#38;quot;: 0, &#38;quot;exit&#38;quot;: 2, &#38;quot;signal&#38;quot;: 0, &#38;quot;status&#38;quot;: 512}}}&lt;br /&gt;&lt;br /&gt;Output :&lt;br /&gt;&lt;br /&gt;rm: cannot remove `&lt;span class=&#34;synSpecial&#34;&gt;/var/ram/foo@example_com_.3H6D8RyK&lt;/span&gt;&#39;: No such file or directory&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;We can see how long it took, what happened, and its output. The &#38;quot;FAIL&#38;quot; in the subject also lets us pick out jobs that failed from jobs that were merely noisy.&lt;/p&gt;

&lt;p&gt;Finally, see that message-id in the In-Reply-To header? That will be the same for every job with the same subject on the same host. That means your cronjob reports will form threads, and that means that you can tell &lt;code&gt;mutt&lt;/code&gt; (or Thunderbird or Mail.app, etc) to collapse all your threads and skim over the different error reports and their counts, rather than just seeing and endless stream of the same flapping service over and over.&lt;/p&gt;

&lt;p&gt;That&#38;#39;s it! App::Cronjob can help hide the pain of Solaris cron, but it isn&#38;#39;t just for Solaris. After all, cron might be better on most Linux systems than on Solaris, but its reports still can&#38;#39;t compare with App::Cronjob&#38;#39;s!&lt;/p&gt;

&lt;h2 id=&#34;See-Also&#34;&gt;See Also&lt;/h2&gt;

&lt;ul&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/App::Cronjob&#34;&gt;App::Cronjob&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;http://interglacial.com/~sburke/pub/crontab2english.html&#34;&gt;crontab2english&lt;/a&gt; -&lt;/p&gt;

&lt;p&gt;Sean M. Burke&#38;#39;s tool for making crontab schedules readable&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;http://en.wikipedia.org/wiki/cron&#34;&gt;Cron&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;</summary><updated>2009-12-07T00:00:00-05:00</updated><category term="Perl"/><category term="RJBS"/></entry><entry><title>Less Boilerplate, More Ice Cream</title><link href="http://advent.rjbs.manxome.org/2009/2009-12-06.html"/><id>http://advent.rjbs.manxome.org/2009/2009-12-06.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h2 id=&#34;Just-a-Little-Less-Work&#34;&gt;Just a Little Less Work&lt;/h2&gt;

&lt;p&gt;Let&#38;#39;s take it easy, it&#38;#39;s Sunday. This library is just a little timesaver, but it saves you from the worst kind of work: boring, stupid, repetitive work.&lt;/p&gt;

&lt;p&gt;Here&#38;#39;s some code I have written longhand way too many times:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;br /&gt;15:&#38;nbsp;&lt;br /&gt;16:&#38;nbsp;&lt;br /&gt;17:&#38;nbsp;&lt;br /&gt;18:&#38;nbsp;&lt;br /&gt;19:&#38;nbsp;&lt;br /&gt;20:&#38;nbsp;&lt;br /&gt;21:&#38;nbsp;&lt;br /&gt;22:&#38;nbsp;&lt;br /&gt;23:&#38;nbsp;&lt;br /&gt;24:&#38;nbsp;&lt;br /&gt;25:&#38;nbsp;&lt;br /&gt;26:&#38;nbsp;&lt;br /&gt;27:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;strict&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Character::Count&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;read_file&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$self&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$filename&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;@_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;open&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$fh&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;&#38;lt;&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$filename&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;or&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;die&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;drat: $!&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$self&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;read_handle&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$fh&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;read_handle&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$self&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$fh&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;@_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;local&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;$/&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$string&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;readline&#34;&gt;&#38;lt;$fh&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$self&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;read_string&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$string&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;read_string&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$self&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$string&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;@_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;%result&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$result&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;++&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;split&lt;/span&gt; &lt;span class=&#34;match&#34;&gt;//&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$string&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$result&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;Except when I wrote it the first way too many times, each implementation was a little different. Sometimes I forgot to check the result of opening a file. Sometimes I duplicated bits of code and only fixed bugs in one or the other. In the one above, I boiled everything down to working on a string, which is going to stink if my input is really big and now I&#38;#39;m holding it all in memory at once and copying it around... and all that boilerplate for just two useful lines of code!&lt;/p&gt;

&lt;p&gt;Mixin::Linewise deals with this by letting you just write the filehandle-based iterator:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;strict&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Character::Count&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Mixin::Linewise::Readers&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;-readers&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;read_handle&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$self&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$fh&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;@_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;%result&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;readline&#34;&gt;&#38;lt;$fh&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$result&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;++&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;split&lt;/span&gt; &lt;span class=&#34;match&#34;&gt;//&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$result&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;That cuts the amount of code roughly in half and ensures that any bugfixes apply to all your modules everywhere instead of just the methods in the modules you remember to go find and update.&lt;/p&gt;

&lt;p&gt;There&#38;#39;s also a Mixin::Linewise::Writers, which does just what you think: you write &lt;code&gt;write_handle&lt;/code&gt; and it gives you &lt;code&gt;write_file&lt;/code&gt; and &lt;code&gt;write_string&lt;/code&gt;. (&lt;code&gt;write_string&lt;/code&gt; returns the string it has produced.)&lt;/p&gt;

&lt;h3 id=&#34;and-because-its-Sub::Exporter...&#34;&gt;...and because it&#38;#39;s Sub::Exporter...&lt;/h3&gt;

&lt;p&gt;Mixin::Linewise uses Sub::Exporter, which means you can parameterize and rename its exports, which means you can do this:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;strict&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;ETL::System&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Mixin::Linewise::Readers&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;-readers&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;-suffix&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;_ini&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;method&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;read_handle_ini&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;-readers&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;-suffix&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;_dat&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;method&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;read_handle_dat&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;read_handle_ini&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;read_handle_dat&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# ...and then somewhere else ...&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$result&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;ETL::System&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;read_file_dat&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;datasource.dat&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;In other words, you can build a bunch of file and string reader methods with different names built on top of distinct handle-readers.&lt;/p&gt;

&lt;p&gt;So, Mixin::Linewise won&#38;#39;t revolutionize how you write Perl, and it won&#38;#39;t be useful all the time. It will be useful once in a while, and will let you stop writing boring boilerplate code and, what&#38;#39;s better, stop having to test it, too.&lt;/p&gt;

&lt;h2 id=&#34;See-Also&#34;&gt;See Also&lt;/h2&gt;

&lt;ul&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Mixin::Linewise::Readers&#34;&gt;Mixin::Linewise::Readers&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Mixin::Linewise::Writers&#34;&gt;Mixin::Linewise::Writers&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;</summary><updated>2009-12-06T00:00:00-05:00</updated><category term="Perl"/><category term="RJBS"/></entry><entry><title>The Other Kind of Turkey</title><link href="http://advent.rjbs.manxome.org/2009/2009-12-05.html"/><id>http://advent.rjbs.manxome.org/2009/2009-12-05.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h2 id=&#34;Its-Elf-Bowling-Time-Again&#34;&gt;It&#38;#39;s Elf Bowling Time Again&lt;/h2&gt;

&lt;p&gt;Every year, as Christmas approaches, it&#38;#39;s time once again to update our email filters to bitbucket all the &#38;quot;elf bowling!!!&#38;quot; emails from friends and family. I&#38;#39;ve never understood the appeal of &lt;i&gt;ELFBOWL.EXE&lt;/i&gt;, but I guess I can say one thing for it: it gets me thinking about bowling, again. I used to really enjoy bowling, but I haven&#38;#39;t gone out to the lanes in ages. Living in New England made me stop thinking about it much, because almost all bowling up there is of a &lt;a href=&#34;http://en.wikipedia.org/wiki/Candlepin_bowling&#34;&gt;strange, abominable variation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When the Nintendo Wii came out, though, I got hooked on bowling again, and realized that although I had always enjoyed the game, I really never understood how to score it. What better way to learn than to implement a CPAN module for tracking bowling scores? Probably many, but that&#38;#39;s the one I picked!&lt;/p&gt;

&lt;p&gt;Here&#38;#39;s the sort of scorecard I might get to fill out on a good day. (I said I liked bowling, not that I was good at it!)&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;br /&gt;15:&#38;nbsp;&lt;br /&gt;16:&#38;nbsp;&lt;br /&gt;17:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Games::Bowling::Scorecard&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$card&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Games::Bowling::Scorecard&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$card&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;record&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;6&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# slow start &lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$card&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;record&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;7&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# getting better&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$card&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;record&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;   &lt;span class=&#34;comment&#34;&gt;# strike! &lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$card&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;record&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;9&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# picked up a spare&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$card&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;record&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;..&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# turkey!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$card&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;record&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# clearly distracted by something&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$card&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;record&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# amazingly picked up 7-10 split&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$card&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;record&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;9&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# pick up a bonus spare&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;say&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$card&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;score&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# 156&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;If you&#38;#39;re a much better bowler, you might get to make this excellent invocation:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$card&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Games::Bowling::Scorecard&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$card&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;record&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;12&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;say&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$card&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;score&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# 300&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$alley&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;trigger_balloon_drop&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;h3 id=&#34;Displaying-Score-Cards&#34;&gt;Displaying Score Cards&lt;/h3&gt;

&lt;p&gt;Of course, printing a number to the screen isn&#38;#39;t very satisfying. Part of the joy of bowling is watching all the bizarre math and symbols get drawn on the big overhead screen. We could tack this onto my game above...&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Games::Bowling::Scorecard::AsText&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Games::Bowling::Scorecard::AsText&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;card_as_text&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$card&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;And we&#38;#39;ll get this extremely satisfying output:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  +-----+-----+-----+-----+-----+-----+-----+-----+-----+-------+
  | 6 1 | 7 2 | X   | 9 / | X   | X   | X   | - - | 8 / | X 9 / |
  |   7 |  16 |  36 |  56 |  86 | 106 | 116 | 116 | 136 |   156 |&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;Practical-Uses..-&#34;&gt;Practical Uses..?&lt;/h3&gt;

&lt;p&gt;If you know how to bowl, you probably know how to keep score, so you&#38;#39;re not going to be saving a lot of time by keying in your scores to a Perl program. You could easily enough throw together a ReadLine-based program to keep track of turns and scores, but I think those uses are never going to be big wins over transparencies and grease pencils.&lt;/p&gt;

&lt;p&gt;No, I think that the big hot application for Games::Bowling::Scorecard will come with the growing resurgence of &lt;a href=&#34;http://sdl.perl.org&#34;&gt;SDL Perl&lt;/a&gt;. Pretty soon, dozens of graphical bowling games written in Perl will be in the works, and they&#38;#39;ll all be easier to write thanks to Games::Bowling::Scorecard. I look forward to the day when the &lt;i&gt;ELFBOWL2.EXE&lt;/i&gt; that I angrily delete is compiled from Perl, using my own code.&lt;/p&gt;

&lt;h2 id=&#34;See-Also&#34;&gt;See Also&lt;/h2&gt;

&lt;ul&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Games::Bowling::Scorecard&#34;&gt;Games::Bowling::Scorecard&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;http://en.wikipedia.org/wiki/Ten-pin_bowling&#34;&gt;Real bowling&lt;/a&gt; (not candlepin!)&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;</summary><updated>2009-12-05T00:00:00-05:00</updated><category term="Perl"/><category term="RJBS"/></entry><entry><title>In Pod We Trust</title><link href="http://advent.rjbs.manxome.org/2009/2009-12-04.html"/><id>http://advent.rjbs.manxome.org/2009/2009-12-04.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h2 id=&#34;Testing-Pod-Coverage&#34;&gt;Testing Pod Coverage&lt;/h2&gt;

&lt;p&gt;Andy Lester&#38;#39;s fantastic &lt;a href=&#34;https://metacpan.org/module/Test::Pod::Coverage&#34;&gt;Test::Pod::Coverage&lt;/a&gt; makes it easy to check whether you&#38;#39;ve covered all your code. The standard usage is to make a file named something like &lt;i&gt;t/pod-coverage.t&lt;/i&gt;, with these contents:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Test::More&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;plan&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;skip_all&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Test::Pod::Coverage 1.08 required for this test&#38;quot;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;unless&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;eval&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;use Test::Pod::Coverage 1.08; 1&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;all_pod_coverage_ok&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;The test will find all the Perl libraries in your distribution, find all the public subroutines or methods, and then try to ensure that they&#38;#39;re documented. It does this by finding all defined subroutines, ignoring ones that it thinks are private (anything starting with an underscore and Perl-wide things like &lt;code&gt;import&lt;/code&gt; or &lt;code&gt;DESTROY&lt;/code&gt;). Then it looks for &lt;code&gt;=head&lt;i&gt;n&lt;/i&gt;&lt;/code&gt; or &lt;code&gt;=item&lt;/code&gt; entries. There&#38;#39;s even a mechanism to supply your own &lt;code&gt;coverage_class&lt;/code&gt; to, for example, allow documentation in parent classes to suffice -- that way you don&#38;#39;t have to document &lt;code&gt;new&lt;/code&gt; in every subclass you write.&lt;/p&gt;

&lt;p&gt;Sometimes, though, you want to note that a symbol doesn&#38;#39;t need to be checked. Maybe it&#38;#39;s documented without having its own header, or maybe it&#38;#39;s from a documented source more complex than an is-a relationship, like a role or trait. With Test::Pod::Coverage&#38;#39;s default behavior, this is sort of a mess. You can either specify global options:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;word&#34;&gt;all_pod_coverage_ok&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;({&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;trustme&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;words&#34;&gt;qw( weird_doc_sub )&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;...but this will trust that symbol to be documented in &lt;i&gt;all&lt;/i&gt; your modules. So instead, you could test libraries one by one, expanding that &lt;code&gt;all_pod_coverage&lt;/code&gt; call into a bunch of single-module calls with the right arguments:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;word&#34;&gt;pod_coverage_ok&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;Library::Alpha&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;trustme&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;words&#34;&gt;qw( weird_doc_sub )&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;pod_coverage_ok&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;Library::Beta&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;trustme&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;words&#34;&gt;qw( weird_doc_method )&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;pod_coverage_ok&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;words&#34;&gt;qw(Library::Gamma Library::Epsilon)&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;...but this is a bunch more work, and you won&#38;#39;t realize until it&#38;#39;s too late that you forgot to add Library::Delta to the list of &#38;quot;no special treatment&#38;quot; routines.&lt;/p&gt;

&lt;h2 id=&#34;Putting-Trust-Where-it-Belongs&#34;&gt;Putting Trust Where it Belongs&lt;/h2&gt;

&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Pod::Coverage::TrustPod&#34;&gt;Pod::Coverage::TrustPod&lt;/a&gt; is built on the idea that the best place to make a note about things already documented is in the documentation itself. You don&#38;#39;t need to write a bunch of documentation for &lt;code&gt;weird_doc_method&lt;/code&gt;, but you can make a note about it in the Pod. That way, every file has its own list of routines to consider already documented, but you can still call &lt;code&gt;all_pod_coverage_ok&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When you write your library, you&#38;#39;d write something like this:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;br /&gt;15:&#38;nbsp;&lt;br /&gt;16:&#38;nbsp;&lt;br /&gt;17:&#38;nbsp;&lt;br /&gt;18:&#38;nbsp;&lt;br /&gt;19:&#38;nbsp;&lt;br /&gt;20:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Library::Alpha&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;parent&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Library::Common&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;pod&#34;&gt;=for Pod::Coverage&lt;br /&gt;&#38;nbsp;&#38;nbsp;new&lt;br /&gt;&#38;nbsp;&#38;nbsp;weird_doc_method&lt;br /&gt;&lt;br /&gt;=cut&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;weird_doc_method&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;pod&#34;&gt;=head2 documented_method&lt;br /&gt;&lt;br /&gt;This method is really documented!&lt;br /&gt;&lt;br /&gt;=cut&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;documented_method&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;And you&#38;#39;d write your &lt;i&gt;t/pod-coverage.t&lt;/i&gt; file like this:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;word&#34;&gt;all_pod_coverage_ok&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;({&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;coverage_class&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Pod::Coverage::TrustPod&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;That&#38;#39;s it! Now all your documentation&#38;#39;s coverage is easy to test, and exceptions are easy to maintain by putting the exceptions right where they belong: in the Pod document itself.&lt;/p&gt;

&lt;h2 id=&#34;A-final-request...&#34;&gt;A final request...&lt;/h2&gt;

&lt;p&gt;Having Pod coverage tests is great. It helps you make sure that you documented things. What isn&#38;#39;t great is when you let those tests run on the computer of anybody who&#38;#39;s installing your code and they fail for some stupid reason. It prevents the user from installing your code just because it thinks you forgot to write enough documentation.&lt;/p&gt;

&lt;p&gt;So, always write this &lt;i&gt;t/pod-coverage.t&lt;/i&gt;&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Test::More&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;plan&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;skip_all&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;author test only&#38;quot;&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;unless&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$ENV&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;RELEASE_TESTING&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;plan&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;skip_all&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Test::Pod::Coverage 1.08 required for this test&#38;quot;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;unless&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;eval&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;use Test::Pod::Coverage 1.08; 1&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;all_pod_coverage_ok&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;({&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;coverage_class&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Pod::Coverage::TrustPod&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;That way, the tests will only be run when you&#38;#39;re testing your distribution before release.&lt;/p&gt;

&lt;h2 id=&#34;See-Also&#34;&gt;See Also&lt;/h2&gt;

&lt;ul&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Pod::Coverage::TrustPod&#34;&gt;Pod::Coverage::TrustPod&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Pod::Coverage&#34;&gt;Pod::Coverage&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Test::Pod::Coverage&#34;&gt;Test::Pod::Coverage&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Pod::Eventual&#34;&gt;Pod::Eventual&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;</summary><updated>2009-12-04T00:00:00-05:00</updated><category term="Perl"/><category term="RJBS"/></entry><entry><title>The Little Deferral Boy</title><link href="http://advent.rjbs.manxome.org/2009/2009-12-03.html"/><id>http://advent.rjbs.manxome.org/2009/2009-12-03.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h2 id=&#34;Avoid-Unwanted-Returns&#34;&gt;Avoid Unwanted Returns&lt;/h2&gt;

&lt;p&gt;I write a whole lot of code that takes a piece of mail and does something with it. Some of these are SMTP servers, some process mailboxes on disk, but at least half of them are &lt;i&gt;pipemailers&lt;/i&gt;. A pipemailer reads a message on STDIN and exits with a code that lets the calling program know what happened. To grossly simplify, the possible exit values are:&lt;/p&gt;

&lt;ul&gt;

&lt;li&gt;&lt;p&gt;&lt;code&gt;0&#38;nbsp;&lt;/code&gt; - everything is okay; the message has been handled&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;75&lt;/code&gt; - we couldn&#38;#39;t handle the message right now, try again later&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;anything else - something is wrong; report failure and never try again&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why does this matter? Well, say you&#38;#39;re using &lt;a href=&#34;https://metacpan.org/module/Email::Filter&#34;&gt;Email::Filter&lt;/a&gt; or &lt;a href=&#34;https://metacpan.org/module/Mail::Audit&#34;&gt;Mail::Audit&lt;/a&gt; or some other Perl library for delivering your mail. I mean, you&#38;#39;re not using &lt;i&gt;&lt;a href=&#34;http://www.procmail.org/&#34;&gt;procmail&lt;/a&gt;&lt;/i&gt; are you? One day you decide you&#38;#39;re going to start checking your mail with SpamAssassin, so you copy this blurb from the documentation:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;symbol&#34;&gt;$mail&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;&#8722;&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;exit&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$mail&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;&#8722;&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;simple&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;Email::Simple&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;&#8722;&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$mail&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;&#8722;&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;pipe&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;double&#34;&gt;&#38;quot;spamassassin&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)));&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$mail&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;&#8722;&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;exit&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;It&#38;#39;s in the documentation, so it should be fine... but you&#38;#39;ve copied and pasted from &lt;i&gt;perldoc&lt;/i&gt; and you&#38;#39;re getting bitten by its stupid use of &lt;code&gt;&#38;lt;U+2122&#38;gt;&lt;/code&gt; instead of a hyphen in the arrow operator. (This gets me about once a week.) Unfortunately, you don&#38;#39;t notice, and now your program dies because &lt;code&gt;perl&lt;/code&gt; has no idea what to do with that fake hyphen. Your program exits 9 (or something else seemingly random) and your mail server starts bouncing absolutely all your mail.&lt;/p&gt;

&lt;p&gt;A test suite would help, and so would lots of other things, but Email::Pipemailer::DieHandler is dead simple, and a good first line of defense. When you install its &#38;quot;&lt;code&gt;SIGDIE&lt;/code&gt;&#38;quot; handler, any fatal exception outside of an eval will be logged and will cause the program to exit 75. Your mail might not get delivered, but at least it won&#38;#39;t get bounced. Hopefully you&#38;#39;ll notice before it all times out!&lt;/p&gt;

&lt;p&gt;Email::Pipemailer::DieHandler is a pretty tiny module. It&#38;#39;s so short that I can reproduce all of its effective code right here:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;br /&gt;15:&#38;nbsp;&lt;br /&gt;16:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Email::Pipemailer::DieHandler&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$self&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$install&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$arg&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;@_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;unless&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$install&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$install&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;eq&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;-install&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$arg&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;||=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{};&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$logger&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$arg&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;logger&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$SIG&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;__DIE__&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;$^S&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# don&#39;t interfere with evals&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$e&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;@_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;core&#34;&gt;defined&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;$^S&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;eval&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$logger&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$e&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;magic&#34;&gt;$!&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;75&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;die&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$e&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;It might be the shortest module I&#38;#39;ve published on the CPAN, but don&#38;#39;t let that fool you: this module has saved me quite a lot of embarassment by converting stupid bounces into errors that only I needed to see.&lt;/p&gt;

&lt;h2 id=&#34;See-Also&#34;&gt;See Also&lt;/h2&gt;

&lt;ul&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Email::Pipemailer::DieHandler&#34;&gt;Email::Pipemailer::DieHandler&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Email::Filter&#34;&gt;Email::Filter&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Mail::Audit&#34;&gt;Mail::Audit&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;http://use.perl.org/~perrin/journal/36161&#34;&gt;Perrin Harkins speaks for us all&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;</summary><updated>2009-12-03T00:00:00-05:00</updated><category term="Perl"/><category term="RJBS"/></entry><entry><title>Making a List, Checking it 0b10 Times...</title><link href="http://advent.rjbs.manxome.org/2009/2009-12-02.html"/><id>http://advent.rjbs.manxome.org/2009/2009-12-02.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h2 id=&#34;Beyond-Hex-and-Octal&#34;&gt;Beyond Hex and Octal&lt;/h2&gt;

&lt;p&gt;It&#38;#39;s sort of easy to convert between decimal, hexadecimal, and octal in Perl. &lt;code&gt;sprintf&lt;/code&gt; can produce decimal, hexadecimal, octal, or binary digit strings, and the &lt;code&gt;oct&lt;/code&gt; built-in can read those strings back into numbers. For example, to convert from hex to binary strings, we might do the following:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$hex&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;99&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$num&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;oct&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;double&#34;&gt;&#38;quot;0x$hex&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# or we could use hex($hex);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$bin&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;sprintf&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;%b&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$num&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# ...and we get 10011001&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;This is a little inconsistent, but fast and easy. Unfortunately, sometimes we need to work with really weird digit sets. Fortunately, &lt;a href=&#34;https://metacpan.org/module/Number::Nary&#34;&gt;Number::Nary&lt;/a&gt; makes these really easy to work with. For example, if we need to convert from sexagesimal to trinary (presumably because we are writing a Star Trek script) we can just create routines using Number::Nary like this:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Number::Nary&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;-codec_pair&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;-suffix&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;_3&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;digits&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;012&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;-codec_pair&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;-suffix&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;_60&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;digits&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;map&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;sprintf&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;%02u&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;..&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;59&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# 00 through 59&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;Now we have four routines for converting between our numbering systems. Given the number 102012012 in trinary, we can easily convert it to sexagesimal:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$trinary&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;102012012&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$number&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;decode_3&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$trinary&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$sexa&lt;/span&gt;    &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;encode_60&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$number&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# &#38;quot;021559&#38;quot;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;Neat, but is it ever practical? Yes! For one thing, it can be used to fix numbers into weird character sets. I&#38;#39;ve used it to cram several large numbers into email addresses by using the valid email address characters as a digit set. There&#38;#39;s also Jesse Vincent&#38;#39;s &lt;a href=&#34;https://metacpan.org/module/Number::RecordLocator&#34;&gt;Number::RecordLocator&lt;/a&gt;, which &#38;quot;encodes integers into a short and easy to read and pronounce locator strings.&#38;quot; Using Number::Nary, we can re-implement that module in about four lines:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Number::Nary&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;-codec_pair&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;digits&lt;/span&gt;    &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;  &lt;span class=&#34;number&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;..&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;9&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;A&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;C&#39;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;..&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;R&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;T&#39;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;..&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Z&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;predecode&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$s&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$s&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=~&lt;/span&gt; &lt;span class=&#34;transliterate&#34;&gt;tr/01SBsb/OIFPFP/&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$s&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# We silently replace some digits with others to keep things easy to read.&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;ok&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;decode&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;1234&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;decode&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;I234&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;));&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# 513430&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;ok&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;decode&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;10SB&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;decode&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;IOFP&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;));&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# 491554&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;Number::Nary is slower than &lt;code&gt;sprintf&lt;/code&gt; and &lt;code&gt;oct&lt;/code&gt; are, but since they can only handle a few different digit sets, they&#38;#39;re not always going to solve the problem at hand. Having Number::Nary in the wings when you need it can be a real time-saver.&lt;/p&gt;

&lt;p&gt;Finally, here&#38;#39;s a quick bit of Christmas spirit:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;br /&gt;15:&#38;nbsp;&lt;br /&gt;16:&#38;nbsp;&lt;br /&gt;17:&#38;nbsp;&lt;br /&gt;18:&#38;nbsp;&lt;br /&gt;19:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Number::Nary&lt;/span&gt; &lt;span class=&#34;float&#34;&gt;0.107&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;-codec_pair&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;digits&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;ho &#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;postencode&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$s&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;core&#34;&gt;shift&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=~&lt;/span&gt; &lt;span class=&#34;substitute&#34;&gt;s/ \z//&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;double&#34;&gt;&#38;quot;Merry Christmas, $s!&#38;quot;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;predecode&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$s&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;lc&lt;/span&gt; &lt;span class=&#34;core&#34;&gt;shift&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$s&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=~&lt;/span&gt; &lt;span class=&#34;substitute&#34;&gt;s/\Amerry christmas, //&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$s&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=~&lt;/span&gt; &lt;span class=&#34;substitute&#34;&gt;s/!\z/ /&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$s&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# Appropriate:&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;say&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;encode&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# Not:&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;say&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;encode&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;h2 id=&#34;See-Also&#34;&gt;See Also&lt;/h2&gt;

&lt;ul&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Number::Nary&#34;&gt;Number::Nary&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/UDCode&#34;&gt;UDCode&lt;/a&gt; - to determine if a set of digits will produce unambiguous strings&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Math::BaseCalc&#34;&gt;Math::BaseCalc&lt;/a&gt; - another take on the problem (but I don&#38;#39;t recommend it)&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;</summary><updated>2009-12-02T00:00:00-05:00</updated><category term="Perl"/><category term="RJBS"/></entry><entry><title>Built in Our Workshop, Delivered in Your Package</title><link href="http://advent.rjbs.manxome.org/2009/2009-12-01.html"/><id>http://advent.rjbs.manxome.org/2009/2009-12-01.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h2 id=&#34;Exporting&#34;&gt;Exporting&lt;/h2&gt;

&lt;p&gt;In Perl, we organize our subroutines (and other stuff) into namespaces called packages. This makes it easy to avoid having to think of unique names for functions you write, and it means you don&#38;#39;t have &lt;a href=&#34;http://php.net/quickref.php&#34;&gt;thousands of core functions&lt;/a&gt; to remember. Traditionally, exports were provided by the &lt;a href=&#34;https://metacpan.org/module/Exporter&#34;&gt;Exporter&lt;/a&gt; module, included with &lt;code&gt;perl5&lt;/code&gt; since its first release.&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;comment&#34;&gt;# You use Exporter in your module...&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Gift::Dispatch&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Exporter&lt;/span&gt; &lt;span class=&#34;words&#34;&gt;qw(import)&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;our&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@EXPORT_OK&lt;/span&gt;   &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;words&#34;&gt;qw(wrap label send)&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;our&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;%EXPORT_TAGS&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;all&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;@EXPORT_OK&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;wrap&lt;/span&gt;  &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;label&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;send&lt;/span&gt;  &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;Now when someone says &lt;code&gt;use Gift::Dispatch &#38;#39;:all&#38;#39;&lt;/code&gt; the three exported routines become available in their package. This is a useful tool, and most Perl programmers interact with Exporter all the time. Unfortunately, it&#38;#39;s not very flexible. For example, here&#38;#39;s our attempt to use Gift::Dispatch:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Gift::Giver&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Gift::Dispatch&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;:all&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# for physical presents&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Email::Send&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;            &lt;span class=&#34;comment&#34;&gt;# for online gift codes&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$gift&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@physical_presents&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;send&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$gift&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;carrier&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;UPS&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$gift&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@gift_codes&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;Email::Send&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;send&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;email_for&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$gift&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;Email::Send exports a &lt;code&gt;send&lt;/code&gt; routine by default, which will clobber the one from Gift::Dispatch. This is obviously a contrived example, but this problem happens in real life, too, and generally ends up being more obnoxious to track down. Subroutines installed by Exporter also stick around forever, so when somebody ends up trying to call &lt;code&gt;Gift::Giver-&#38;gt;send&lt;/code&gt;, forgetting that the right method is &lt;code&gt;give&lt;/code&gt;, they get one of your imported routines instead of a &#38;quot;no such method&#38;quot; exception.&lt;/p&gt;

&lt;h2 id=&#34;Sub::Exporter-and-Naming&#34;&gt;Sub::Exporter and Naming&lt;/h2&gt;

&lt;p&gt;Sub::Exporter (sometimes affectionately referred to as S&#38;#39;Ex) makes it easy to fix this problem. First, we update Gift::Dispatch:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;comment&#34;&gt;# You use Exporter in your module...&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Gift::Dispatch&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Sub::Exporter&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;-setup&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;words&#34;&gt;qw(wrap label send)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;wrap&lt;/span&gt;  &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;label&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;send&lt;/span&gt;  &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;And then we update Gift::Giver to muck around with the names (unrelated code omitted):&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Gift::Giver&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Gift::Dispatch&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;:all&#39;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;-prefix&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;_&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;-suffix&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;_gift&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$gift&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@physical_presents&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;_send_gift&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$gift&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;carrier&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;UPS&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;h2 id=&#34;Sub::Exporter-and-Code-Customization&#34;&gt;Sub::Exporter and Code Customization&lt;/h2&gt;

&lt;p&gt;We got to muck about with the names under which things are imported. This is only the tip of the iceberg. Sub::Exporter can let you customize not just the names of imported routines, but also other facets of their operation. For example, we might not want to require the &#38;quot;carrier&#38;quot; parameter for our shipment above, if we can provide a default. It&#38;#39;s easy to let Sub::Exporter handle an import like this:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Gift::Giver&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Gift::Dispatch&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;send&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;-as&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;_send_gift&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;carrier&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;UPS&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$gift&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@physical_presents&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;_send_gift&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$gift&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;With arguments like that, we can build routines with built-in defaults, overridden behavior, and all kinds of customization, wrapped up in a simple name that we choose.&lt;/p&gt;

&lt;p&gt;Over next few weeks, quite a few of the libraries that will be discussed will either use Sub::Exporter to provide exported functions or will use Sub::Exporter to provide powerful customizable interfaces. To really learn how these work, you should go to the &lt;a href=&#34;https://metacpan.org/module/Sub::Exporter::Tutorial&#34;&gt;Sub::Exporter::Tutorial&lt;/a&gt;, but here&#38;#39;s a quick non-trivial sample using the canonical closure example of a &#38;quot;counter&#38;quot;:&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;br /&gt;15:&#38;nbsp;&lt;br /&gt;16:&#38;nbsp;&lt;br /&gt;17:&#38;nbsp;&lt;br /&gt;18:&#38;nbsp;&lt;br /&gt;19:&#38;nbsp;&lt;br /&gt;20:&#38;nbsp;&lt;br /&gt;21:&#38;nbsp;&lt;br /&gt;22:&#38;nbsp;&lt;br /&gt;23:&#38;nbsp;&lt;br /&gt;24:&#38;nbsp;&lt;br /&gt;25:&#38;nbsp;&lt;br /&gt;26:&#38;nbsp;&lt;br /&gt;27:&#38;nbsp;&lt;br /&gt;28:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Counter&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Sub::Exporter&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;-setup&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;groups&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;counter&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;_gen_counter&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;_gen_counter&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$class&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$name&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$arg&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;@_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$cb&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$arg&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;callback&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@log&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;%sub&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$sub&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;record&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$value&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;@_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$cb&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$value&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$cb&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;@_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;push&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@log&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$value&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$sub&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@log&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$sub&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;scalar&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@log&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;%sub&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;Then we put it to use...&lt;/p&gt;



&lt;table class=&#39;code-listing&#39;&gt;&lt;tr&gt;&lt;td class=&#39;line-numbers&#39;&gt;&lt;br /&gt;&lt;code&gt;1:&#38;nbsp;&lt;br /&gt;2:&#38;nbsp;&lt;br /&gt;3:&#38;nbsp;&lt;br /&gt;4:&#38;nbsp;&lt;br /&gt;5:&#38;nbsp;&lt;br /&gt;6:&#38;nbsp;&lt;br /&gt;7:&#38;nbsp;&lt;br /&gt;8:&#38;nbsp;&lt;br /&gt;9:&#38;nbsp;&lt;br /&gt;10:&#38;nbsp;&lt;br /&gt;11:&#38;nbsp;&lt;br /&gt;12:&#38;nbsp;&lt;br /&gt;13:&#38;nbsp;&lt;br /&gt;14:&#38;nbsp;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;br /&gt;&lt;code&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Counter&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;-counter&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;-suffix&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;_receipt&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;callback&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;sending thankyou note for $_[0]\n&#38;quot;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;-counter&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;-suffix&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;_gift&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;record_receipt&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@presents_we_got&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;record_gift&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt;    &lt;span class=&#34;word&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@presents_we_gave&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;die&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;life isn&#39;t fair&#38;quot;&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;count_gift&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;&#38;gt;&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;count_receipt&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&#38;nbsp;&lt;/td&gt;&lt;/table&gt;

&lt;p&gt;Sub::Exporter is easier to use than Exporter and in its most trivial configuration provides much more utility. Learning how to make the most of Sub::Exporter can make very complex code generation quite simple and can reduce the amount of code you must write significantly.&lt;/p&gt;

&lt;h2 id=&#34;See-Also&#34;&gt;See Also&lt;/h2&gt;

&lt;ul&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Sub::Exporter&#34;&gt;Sub::Exporter&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Sub::Exporter::Tutorial&#34;&gt;Sub::Exporter::Tutorial&lt;/a&gt; - a more thorough tutorial on the basics&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Sub::Exporter::Cookbook&#34;&gt;Sub::Exporter::Cookbook&lt;/a&gt; - stupid Sub::Exporter tricks&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Sub::Exporter::Lexical&#34;&gt;Sub::Exporter::Lexical&lt;/a&gt; - imports that only last for your scope&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Sub::Import&#34;&gt;Sub::Import&lt;/a&gt; - treat Exporter-using packages as if they used Sub::Exporter&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;</summary><updated>2009-12-01T00:00:00-05:00</updated><category term="Perl"/><category term="RJBS"/></entry></feed>