<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Perlblogs &#187; perl5</title>
	<atom:link href="http://perlblogs.com/category/perl5/feed/" rel="self" type="application/rss+xml" />
	<link>http://perlblogs.com</link>
	<description>Posts from selected Perl bloggers</description>
	<lastBuildDate>Fri, 18 May 2012 19:03:44 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
<atom:link rel="hub" href="http://pubsubhubbub.appspot.com"/><atom:link rel="hub" href="http://superfeedr.com/hubbub"/>		<item>
		<title>use_ok() is Broken Because require() is Broken</title>
		<link>http://www.modernperlbooks.com/mt/2012/04/use-ok-is-broken-because-require-is-broken.html</link>
		<comments>http://www.modernperlbooks.com/mt/2012/04/use-ok-is-broken-because-require-is-broken.html#comments</comments>
		<pubDate>Wed, 11 Apr 2012 17:30:09 +0000</pubDate>
		<dc:creator>chromatic</dc:creator>
				<category><![CDATA[bugs]]></category>
		<category><![CDATA[languagedesign]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[perl5]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://perlblogs.com/?guid=476f6a88daba3457743ffd99bb0861b4</guid>
		<description><![CDATA[Ovid's post on avoiding Test::More's use_ok() is good advice. There's almost no reason to use use_ok() from Test::More in existing code. It probably doesn't do what you think it does, and it doesn't really help against most of the failures...]]></description>
			<content:encoded><![CDATA[
        <p>Ovid's post on <a
href="http://blogs.perl.org/users/ovid/2012/04/avoiding-use-ok-in-t00-loadt.html">avoiding
Test::More's use_ok()</a> is good advice. There's almost no reason to use
<code>use_ok()</code> from <a
href="http://search.cpan.org/perldoc?Test::More">Test::More</a> in existing
code. It probably doesn't do what you think it does, and it doesn't really help
against most of the failures you probably care about.</p>

<p>Worse, it can give you a false sense of security and mislead you into
debugging the wrong thing.</p>

<p>Why? Because it turns what ought to be a fatal, program-killing exceptional
condition ("Hey, I couldn't load this module! I'd better stop now. Things are
certainly not going to work the way anyone expects!") into a simple failed test
("Oopsie! Better check your assumptions! I'll keep going though, because
hopefully you just made a typo in your test assertion!").</p>

<p>The problem really isn't with <code>use_ok()</code> though. The problem's
with Perl 5's <a
href="http://perldoc.perl.org/functions/require.html">require</a>.</p>

<p><code>require</code> does one thing. It searches the filesystem for the
named file, compiles it, and caches the success or failure of compilation.
(Make that three things.)</p>

<p>Here's the problem: what if compilation fails? What of compilation fails
halfway through the file? What if compilation fails on the very last line of
the file because the module doesn't return a true value? Try it yourself:</p>

<pre><code>package FalseReturnValue;

sub demo { 'demo' }
sub demo2 { 2 }

0;</code></pre>

<p>... and the test:</p>

<pre><code>use Test::More;

use lib 'lib';
use_ok( 'FalseReturnValue' );

is FalseReturnValue::demo(), 'demo', 'Declared functions exist';
is FalseReturnValue::demo2(), 2,     '... all of them';

done_testing;</code></pre>

<p>The problem is that failing to load a module should never leave your system
in an inconsistent state.</p>

<p>Getting this right is very, very difficult. Getting this right means not
committing anything to globally visible symbols until you're certain that the
module compiled correctly. For a module like <code>FalseReturnValue</code>,
that's easy. For a module which itself uses something like Catalyst or
DBIx::Class with several dependencies, this is tricky.</p>

<p>The best approach I can think of is to maintain some sort of transactional
system (yes, I know it sounds awfully complex, but you asked for correctness
first, so humor me through at least this sentence) where you build up a set of
changes to globally visible symbols and then only apply that delta if that
compilation as a whole&mdash;the top-level module and all of its
dependencies&mdash;succeeds.</p>

<p>The second best solution is to do that for each module. It's all or nothing
for each <code>use</code> statement on its own, regardless of how far down the
dependency tree you are.</p>

<p>(You could go one step further and make everything anonymous by default,
such that the only way you can access package global symbols in another
namespace is by binding to that namespace explicitly, but that's a bigger
change with implications on code reuse and the cross cutting concerns of an
object system, even though it does have the potential to clean up things like
accidental exports.)</p>

<p>Of course, if your worldview has already said that failing to load a
dependency with <code>use</code> should abort the program with red flashing
klaxon lights and a siren, you don't have to do that much work.</p>

<p>(... but <code>require</code> errors are exceptions you can catch with
<code>eval { ... }</code>, so the problem remains with
<code>require</code>.)</p>
        
    ]]></content:encoded>
			<wfw:commentRss>http://perlblogs.com/2012/04/11/use_ok-is-broken-because-require-is-broken/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Defending Against Its Dynamic Scope</title>
		<link>http://www.modernperlbooks.com/mt/2012/04/defending-against-its-dynamic-scope.html</link>
		<comments>http://www.modernperlbooks.com/mt/2012/04/defending-against-its-dynamic-scope.html#comments</comments>
		<pubDate>Mon, 09 Apr 2012 18:37:06 +0000</pubDate>
		<dc:creator>chromatic</dc:creator>
				<category><![CDATA[bugs]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[modernperl]]></category>
		<category><![CDATA[perl5]]></category>

		<guid isPermaLink="false">http://perlblogs.com/?guid=e265d13e3a65e0c61169bf7d14968d95</guid>
		<description><![CDATA[A lot of the advice given in Modern Perl: the Book is advice learned the hard way, whether through making my own mistakes, debugging code written on my teams, or reviewing code written by other people to help novices become...]]></description>
			<content:encoded><![CDATA[
        <p>A lot of the advice given in <a
href="http://onyxneon.com/books/modern_perl">Modern Perl: the Book</a> is
advice learned the hard way, whether through making my own mistakes, debugging
code written on my teams, or reviewing code written by other people to help
novices become better programmers. After a decade-plus of this experience, I
think I've developed a good sense of what people find confusing and what
problems rarely occur in practice.</p>

<p>The pervasive use of global variables? It'll eventually catch up to you.
Variables popping into existence upon use, not declaration? It'll cause
problems far sooner than you ever expect.</p>

<p>Clobbering <code>$_</code> at a distance inside a <code>map</code> block? It happened to me the other day. Yes, it surprised me too.</p>

<p>I've been attaching the Perl search bindings <a
href="http://search.cpan.org/perldoc?Lucy">Lucy</a> to a document processing
engine. As part of the processing stage, my code adds documents to the search
index. The index schema keeps track of specific fields, and it's denormalized
slightly to decouple the document database from the search index. The code to
add a document to the index creates a hash from method calls on each document
object. That's where things started to go wrong:</p>

<pre><code>sub add_entries
{
    my ($self, $entries) = @_;
    my $index            = $self-&gt;index;

    for my $entry (@$entries)
    {
        my $fields =
        {
            <strong>map { $_ =&gt; scalar $entry-&gt;$_() } keys %index_fields</strong>
        };

        $index-&gt;add_doc( $fields );
    }

    $index-&gt;commit;
    $self-&gt;clear_index;
}</code></pre>

<p>I noticed things went wrong when my test bailed out with strange errors.
Lucy was complaining about getting a hash key of <code>''</code>, the empty
string. I was certain that <code>%index_fields</code> was correct.</p>

<p>While most of the methods called are simply accessors for simple object properties, these document objects have a method called <code>short_content()</code>:

<pre><code>sub short_content
{
    my $self    = shift;
    my $meth    = length $self-&gt;content &gt; $MIN_LENGTH ? 'content' : 'summary';
    my $content = $self-&gt;$meth();

    return unless defined $content;

    my $splitter     = Lingua::Sentence-&gt;new( 'en' );
    my $total_length = 0;
    my @sentences;

    for my $sentence ($splitter-&gt;split_array( $content ))
    {
        push @sentences, $sentence;
        $total_length += length $sentence;

        # must be a big mess, if this is true
        return $self-&gt;summary
            if  @sentences    == 1
            and $total_length &gt; $MAX_SANE_LENGTH;
        last if $total_length &gt; 0.65 * $MAX_LENGTH;
    }

    if (@sentences)
    {
        my $text = join ' ', @sentences;
        return $text if length $text &gt; $MAX_SENTENCE_LENGTH && $text =~ /\S/;
    }

    return substr $content, 0, $MAX_SHORT_CONTENT_LENGTH;
}</code></pre>

<p>A document may have a summary. It has content. <code>short_content()</code>
returns a slice of the first significant portion of either, depending on which
exists. While it's not the most detailed portion of the document, it's the
earliest significant portion of the document, and it's demonstrably the best
portion to index as a summary. (Thank you, <a
href="http://voices.yahoo.com/using-inverted-pyramid-write-news-articles-212793.html">inverted
pyramid</a>.)</p>

<p>The rest of this method attempts to break the short content at a sentence
boundary, so as not to cut it off in the middle of a word or thought.</p>

<p>Nothing in that method obviously clobbers <code>$_</code>, but something
called from it apparently does. (I wonder if <a
href="http://search.cpan.org/perldoc?Lingua::Sentence">Lingua::Sentence</a> or
one of its dependencies reads from a file or performs a substitution.)
Regardless, I protected my precious hash key with a little defensive
programming:</p>

<pre><code>        my $fields =
        {
            map { <strong>my $field = $_; $field =&gt; scalar $entry-&gt;$field()</strong> }
                keys %index_fields
        };
</code></pre>

<p>... and all was well.</p>

<p>While this has been a very rare occurrence in 13+ years of Perl 5 programming, the trap is particularly insidious. The more work Perl does within that <code>map</code> block, the greater the potential for action at a distance. Furthermore, the better my abstractions&mdash;the more behavior hidden behind that simple method call&mdash;the greater my exposure to this type of bug.</p>

<p>Throw in things like <a
href="http://www.modernperlbooks.com/mt/2011/08/youre-already-using-dependency-injection.html">dependency
injection</a> and <a
href="http://www.modernperlbooks.com/mt/2012/02/the-memoization-of-lazy-attributes.html">Moose
lazy attributes</a> where you don't have to manage the dependency graph of your
data initialization and flow yourself (generally a good thing) and you can't
tell what's going to happen where or when.</p>

<p>If my instincts are correct, and something reads from a file somewhere such
that only the <em>first</em> call to construct a <code>Lingua::Sentence</code>
object clobbers <code>$_</code>, the point is doubly true.</p>

<p>(Sure, changing <code>map</code> to autolexicalize <code>$_</code> would fix
this problem, but it has backwards compatibility concerns for people who
<em>rely</em> on this action at a distance&mdash;remember, it's only a problem
if you <em>write</em> to <code>$_</code>&mdash;and it's too late to get such a
change into Perl 5.16, even if it were only enabled with <code>use
5.016;</code>. Meanwhile, a variable assignment fixes it for me right now, and
that will have to suffice.)</p>
        
    ]]></content:encoded>
			<wfw:commentRss>http://perlblogs.com/2012/04/09/defending-against-its-dynamic-scope/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Consistency, CPAN, and Captiousness</title>
		<link>http://www.modernperlbooks.com/mt/2012/03/consistency-cpan-and-captiousness.html</link>
		<comments>http://www.modernperlbooks.com/mt/2012/03/consistency-cpan-and-captiousness.html#comments</comments>
		<pubDate>Tue, 27 Mar 2012 19:15:35 +0000</pubDate>
		<dc:creator>chromatic</dc:creator>
				<category><![CDATA[cpan]]></category>
		<category><![CDATA[languagedesign]]></category>
		<category><![CDATA[modernperl]]></category>
		<category><![CDATA[perl5]]></category>

		<guid isPermaLink="false">http://perlblogs.com/?guid=7be7a53dd7c6d05ed4a8c4426938514d</guid>
		<description><![CDATA[Once in a while, an innocent looking change to bleadperl (the version of Perl 5 under current development) causes changes which ripple through the CPAN. As the CPAN is a graph of dependencies, any such change which causes tests to...]]></description>
			<content:encoded><![CDATA[
        <p>Once in a while, an innocent looking change to bleadperl (the version of Perl 5 under current development) causes changes which ripple through the CPAN. As the CPAN is a graph of dependencies, any such change which causes tests to fail could have dramatic effects on user applications.</p>

<p>(Once I almost released a change which would have made half of CPAN uninstallable. Then Schwern slapped my hand metaphorically.)</p>

<p>Sometimes the fault isn't in bleadperl.</p>

<p>Consider <a href="https://rt.perl.org/rt3//Public/Bug/Display.html?id=106538">RT #106538</a>, which laments the inconsistency between the output of the builtin <code>die</code> and <a href="http://search.cpan.org/perldoc?Carp">Carp</a>'s <code>croak()</code>. From the bug report:</p>

<pre><code>$ <strong>perl -e 'die'</strong>
Died at -e line 1.
$ <strong>perl -MCarp -e 'croak Died'</strong>
Died at -e line 1</code></pre>

<p>If your eyes don't immediately catch the missing period, you're in good
company.</p>

<p>Consistency suggests that the output of both error messages should be
identical. After all, <code>Carp</code> exists to enhance Perl 5's core
exception mechanisms.</p>

<p>Yet as you might expect, <a
href="http://www.modernperlbooks.com/mt/2010/08/the-stringceptional-difficulty-of-changing-error-messages.html">changing
error messages breaks buggy code that attempts to parse unstructured text too
strictly</a>. Adding a single dot to an error message makes several important
CPAN modules fail their tests.</p>

<p>I can't blame CPAN developers for performing exact matches against string error messages&mdash;it's quick and easy and unlikely to change, and it's reasonably easy to fix... until you get a fix that looks like:</p>

<pre><code>$pattern .= $Carp::VERSION gt "1.24" ? "." :"";</code></pre>

<p>... which <em>knows</em> that the period is present but <em>persist in
hard-coding specific formatting details of the output</em>.</p>

<p>The right solution, of course, is to stop emitting only unstructured text
(from the core side) and to stop testing the exact details of unstructured text
(on the CPAN side). The interim solution is to stop testing the exact details
of unstructured text on the CPAN side.</p>

<p>Despite all of the effort around what could have been a simple change, the
entire process of developing Perl 5 is a huge improvement over its past. Making
this change and identifying its effects was reasonably easy, when you consider
the size of the task and its consequences. Sure, the entire Perl community has
to pay off some of the technical debt for well-established choices and design
decisions that turned out to have been less than perfect, but this is a good
opportunity to see how much better things are than they were even five years
ago and to reflect on how to improve processes and tools to make them better as
early as next year.</p>

<p>Do keep in mind, however, that if you're performing exact string matches
against the results of things the core has never promised not to change, you
are writing risky code.</p>
        
    ]]></content:encoded>
			<wfw:commentRss>http://perlblogs.com/2012/03/27/consistency-cpan-and-captiousness/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Inadvertent Inconsistencies: Aggregate Autoderef in 5.14</title>
		<link>http://www.modernperlbooks.com/mt/2012/03/inadvertent-inconsistencies-aggregate-autoderef-in-514.html</link>
		<comments>http://www.modernperlbooks.com/mt/2012/03/inadvertent-inconsistencies-aggregate-autoderef-in-514.html#comments</comments>
		<pubDate>Wed, 21 Mar 2012 19:18:58 +0000</pubDate>
		<dc:creator>chromatic</dc:creator>
				<category><![CDATA[languagedesign]]></category>
		<category><![CDATA[modernperl]]></category>
		<category><![CDATA[perl5]]></category>

		<guid isPermaLink="false">http://perlblogs.com/?guid=3ca6c579d034c55837cb35477d785526</guid>
		<description><![CDATA[Perl 5's dereferencing syntax has always been ugly. It's perhaps the ugliest part of the language's syntax. (Some people think regular expressions are ugly. They are, but they have a long history of being ugly. You don't blame the human...]]></description>
			<content:encoded><![CDATA[
        <p>Perl 5's dereferencing syntax has always been ugly. It's perhaps the ugliest
part of the language's syntax. (Some people think regular expressions are ugly.
They are, but they have a long history of being ugly. You don't blame the human
knee for being unattractive when it does what it does as effectively as it
does, but you also don't reproduce its ugliness when you design an entirely new
lifeform.)</p>

<p>Perl 5's aggregate operators (such as <code>push</code> and
<code>shift</code>) have traditionally required dereferencing when used on
aggregate operands. In other words, through most of Perl 5's lifespan you had
to write:</p>

<pre><code>my $diversions = [ 'Halo', 'LoTR Pinball', 'Cat Herding', 'Mario Galaxy' ];

my $evening_event = <strong>shift @$diversions</strong>;
# or <strong>shift @{ $diversions }</strong></code></pre>

<p>The same goes for hash operators:</p>

<pre><code>my $pet_nicknames =
{
    Lucky  => 'Stinkerbell',
    Rodney => 'Robot Parade',
    Choco  => 'Destructo Junior',
};

my @nicknames = values <strong>%$pet_nicknames</strong>;
# or values <strong>%{ $pet_nicknames }</strong></code></pre>

<p>Although Perl can warn you when you mention the wrong variable if you use
first-class aggregates (writing <code>keys %not_a_hash</code> when there's no
hash called <code>%not_a_hash</code> in scope, for example), you have no such
protection at the point of compilation when you dereference aggregate
references. If <code>$pet_nicknames</code> turns out not to be a hash, you get
a runtime error.</p>

<p>That's all well and good; we've lived with that through Perl 5's lifespan
and we know how to deal with that. Keep that in mind, though.</p>

<p>Perl 5.14 added a feature by which Perl will do what you mean when you
provide a scalar as the operand to one of these aggregate operators. In other
words:</p>

<pre><code>my @nicknames = values <strong>$pet_nicknames</strong>;
my $evening_event = <strong>shift $diversions</strong>;</code></pre>

<p>Because it's unambiguous that <code>shift</code> must operate on an array,
Perl will happily now dereference <code>$diversions</code> as if it were an
array. If it isn't an array, you get the same error that you'd have received if
you'd written <code>@{ $diversions }</code> or <code>@$diversions</code> on
something that isn't an array.</p>

<p>Removing extraneous superfluous bletcherous syntax is generally a good
thing, if it's truly unnecessary and unambiguous. In the case of array
operators, it is.</p>

<p><a
href="http://www.modernperlbooks.com/mt/2012/03/inadvertent-inconsistencies-each-in-perl-512.html">Then
we come to hashes</a>.</p>

<p>As of Perl 5.12, the hash operators work also on arrays. Again, that's
usually okay. If you write <code>each $diversions</code> or <code>values
$diversions</code> or even <code>keys $diversions</code> (though why would you
do either of the latter? <a
href="http://web.cn.edu/kwheeler/gram_parallelism.html">rhetoric
parallelism</a> in Perl poetry?), you'll get something sensible back...</p>

<p>... except that you don't get the protection you'd get if you'd written
<code>%{ $diversions }</code> or <code>%$diversions</code> when
<code>$diversions</code> is an array reference.</p>

<p>Obviously making <code>shift</code> and <code>push</code> autodereference
aggregates implies making the other array operators autodereference aggregates,
and making the array operators autodereference aggregate implies making the
hash operators autodereference aggregates. Consistency is a good thing.</p>

<p>Yet the combination of these two features in two Perl releases has produced
an inadvertent inconsistency such that using these features together is a
little bit less safe than not using them.</p>

<p>This isn't the worst of it; the next post will explain how things can go
worse, how to avoid these problems in your code, and how they could have been
avoided at the design and implementation levels&mdash;and why they weren't.</p>

        
    ]]></content:encoded>
			<wfw:commentRss>http://perlblogs.com/2012/03/21/inadvertent-inconsistencies-aggregate-autoderef-in-5-14/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Upgrading User Password Hashes in Place</title>
		<link>http://www.modernperlbooks.com/mt/2012/02/upgrading-user-password-hashes-in-place.html</link>
		<comments>http://www.modernperlbooks.com/mt/2012/02/upgrading-user-password-hashes-in-place.html#comments</comments>
		<pubDate>Mon, 20 Feb 2012 21:17:39 +0000</pubDate>
		<dc:creator>chromatic</dc:creator>
				<category><![CDATA[hacks]]></category>
		<category><![CDATA[modernperl]]></category>
		<category><![CDATA[perl5]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://perlblogs.com/?guid=9949481428f2e7ef5e558acc892268fc</guid>
		<description><![CDATA[If you allow users to log in to your system, you need to hash their passwords with a cryptographically secure mechanism. That means not MD5 or basic Unix crypt(3) (though credit goes to OpenBSD for allowing the use of Blowfish...]]></description>
			<content:encoded><![CDATA[
        <p>If you allow users to log in to your system, you need to <a
href="http://unixwiz.net/techtips/iguide-crypto-hashes.html">hash their
passwords</a> with a cryptographically secure mechanism. That means not MD5 or
basic Unix <a
href="http://www.openbsd.org/cgi-bin/man.cgi?query=crypt&sektion=3&apropos=0">crypt(3)</a>
(though credit goes to OpenBSD for allowing the use of Blowfish with their
<code>crypt(3)</code>.</p>

<p>It's obvious why hashing passwords is necessary: storing passwords in plain
text offers an attack vector by which you can inadvertently expose private user
data to the wild world. Even if an attacker somehow gets access to hashed
passwords, extracting the plain text password (or its cryptographic equivalent)
from the hash is an expensive operation.</p>

<p>Yet the quality of the hash matters. Faster computers can perform brute
force attacks against simpler hashing functions. DES and RSA aren't sufficient.
MD5 is not sufficient. Even SHA-1&mdash;which worked really well until a couple
of years ago&mdash;isn't sufficient. The modern consensus seems to prefer the
Blowfish algorithm as sufficiently secure.</p>

<p>Yet I had deployed code which used SHA-1 to hash sensitive user
information.</p>

<p>Upgrading passwords in place is reasonably simple, though. (Here's the part
where posting code about a security issue has the potential to expose a really
silly bug, in which case thank you for helping me fix my code.)</p>

<p>I have a user model built with <a href="http://search.cpan.org/perldoc?DBIx::Class">DBIx::Class</a>. Its <code>check_password()</code> function (slightly misnamed, but misnamed to integrate with other components) verifies that the given plaintext password hashes to the stored hash value. If so&mdash;and if the user has the <code>is_active</code> flag set to a true value&mdash;the login can continue. Otherwise, the login fails.</p>

<p>I'd previously extracted the hashing function into a single module which
exports a <code>hash()</code> function. This turned out to be a wise approach;
it's one and only one place in the code where I can change the underlying
hashing mechanism.</p>

<p>That abstraction meant that switching new users to use Blowfish could happen
automatically. Upgrading existing users took a little more work:</p>

<pre><code>sub check_password
{
    my ($self, $attempt) = @_;
    my $password         = $self-&gt;password;

    # upgrade existing passwords to Bcrypt passwords
    if (old_hash($attempt) eq $password)
    {
        # crypt with blowfish
        $password = hash($attempt);
        $self-&gt;update({ password =&gt; $password });

        return $self-&gt;is_active;
    }

    return unless hash($attempt, $password) eq $password;
    return $self-&gt;is_active;
}</code></pre>

<p>When a user attempts to log in, first compare with the old hashing
mechanism. If <em>that</em> matches, update the user's password in the database
with the new hashing mechanism. Otherwise, use the new hashing mechanism.</p>

<p>This code could be even easier; <a
href="http://search.cpan.org/perldoc?Crypt::Eksblowfish::Bcrypt">Crypt::Eksblowfish::Bcrypt</a>
returns a hashed password encoded in Base-64 with a special string prepended
which contains the password hashing settings. Those magic characters never
appear in the encoding mechanism I used for SHA-1 passwords, so only encoded
passwords which start with that sequence can use the new hash. Everything else
should attempt to match against the old hash.</p>

<p>One drawback of this technique is that it makes what would normally be a
read-only operation (compare passwords) perform a write (update passwords), but
this is a temporary workaround. When all of the users have logged in (and had
their passwords update transparently), I can remove this workaround. Detecting
that is easy: check the first few characters of each password for the special
prefix.</p>

<p>This technique isn't particularly original or difficult, but it's worked
very well for me so far. Better yet, my users haven't noticed at all. They get
more security for free with no work on their part. That's a good tradeoff.</p>
        
    ]]></content:encoded>
			<wfw:commentRss>http://perlblogs.com/2012/02/20/upgrading-user-password-hashes-in-place/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Templating with Widgets, Not Primitives</title>
		<link>http://www.modernperlbooks.com/mt/2012/02/templating-with-widgets-not-primitives.html</link>
		<comments>http://www.modernperlbooks.com/mt/2012/02/templating-with-widgets-not-primitives.html#comments</comments>
		<pubDate>Thu, 09 Feb 2012 18:52:50 +0000</pubDate>
		<dc:creator>chromatic</dc:creator>
				<category><![CDATA[languagedesign]]></category>
		<category><![CDATA[modernperl]]></category>
		<category><![CDATA[perl5]]></category>
		<category><![CDATA[templating]]></category>
		<category><![CDATA[webprogramming]]></category>

		<guid isPermaLink="false">http://perlblogs.com/?guid=39c0fa5cf1f6b54db8631ed41e9215c0</guid>
		<description><![CDATA[After a disastrous attempt to write my own templating language as about the third program I ever wrote in Perl (it was the dot-com boom of the '90s, not that that's any excuse), I moved to Template::Toolkit and have been...]]></description>
			<content:encoded><![CDATA[
        <p>After a disastrous attempt to write my own templating language as about the
third program I ever wrote in Perl (it was the dot-com boom of the '90s, not
that that's any excuse), I moved to <a
href="http://search.cpan.org/perldoc?Template">Template::Toolkit</a> and have
been relatively happy with it ever since.</p>

<p>My first real paid programming job was a little GUI app for a customer
service group at HP. Customer service agents who needed to escalate to second
line support would click on the button for the printer line about which they
had to ask a question, and the program recorded the vote, then printed a nice
report at the end of the day. It solved a problem. As far as I know, it was
still running when I left HP a couple of years later.</p>

<p>A couple of years later, I took a job where we refactored, maintained, and
extended a GUI point of sale system.</p>

<p>Since then, I've avoided most graphical programming. Sure, I put together
websites for clients once in a while, but most of my work has been emitting the
most basic semantically-useful HTML possible such that a Real Designer can
manipulate things with CSS (CSS being, of course, one of those
so-horrible-it's-almost-good things in that it's the only way to get things
done, but you always want to take a shower after you use it, lest you think you
start to appreciate it for anything other than its efficacy. See also
JavaScript and PHP.).</p>

<p>Most of this meant dropping a big blob of content in a Template Toolkit
wrapper in the middle of some HTML, or maybe templatizing some repeated HTML
element while iterating over a collection in the toolkit.</p>

<p>Then I decided to redesign a site.</p>

<p>Twitter has its problems (I hope never to understand how or why someone
would take a perfectly functional website then try to make it work like a buggy
phone app in the same way that I never understood why the first Harry Potter
movie hewed so closely to the book it was as boring as a Merchant and Ivory
movie and it had <em>wizards</em> in it), but <a
href="http://twitter.github.com/bootstrap/">Twitter's Bootstrap</a> CSS
framework actually made sense to me, and it let me put together a couple of
pages that looked good&mdash;far better than the Frankenstein's monster I
cobbled together from the "Hey, everything's a blog now, right?" OSWD designs I
liked.</p>

<p>(Bootstrap has its problems too, but the worst one is that the <a
href="http://lesscss.org/">Less CSS</a> abstraction layer of CSS is intricately
tied to the Lovecraftian bonepile of crazy that is Node.js, because if there's
anything I want to do in JavaScript less than write a templating system to
perform text substitutions in a cooperative multitasking system, I don't know
what it is. It probably involves sharks, skydiving, live volcanoes, and dental
work. Yet even only being able to extract repeated <em>colors</em> into named
variables and build a static CSS file is a <em>huge</em> improvement, so I put
on protective eyeware.)</p>

<p>The experience turned out relatively enjoyable. I had a nice looking wrapper
and a decent framework for displaying and managing content.</p>

<p>Then I wanted to change the way I displayed certain elements.</p>

<p>Here's the thing about web programming, or at least the way I'm doing this
project. I don't think in terms of pages. I think in terms of components of
pages. I have a <em>templates/components/</em> directory full of reusable
Template Toolkit components processed with <code>INCLUDE</code> and
<code>PROCESS</code>. The big blurbs of marketing text and instructions and
explanations on various pages all live in individual components. Sure, it's a
little bit of work to figure out the layout, but this separation of concerns
makes editing the site much easier.</p>

<p>It also makes revising the layout more difficult&mdash;if changing the
layout requires modifying lots of templates with the wrong
<code>&lt;div&gt;</code> names and classes and such.</p>

<p>It's possible to write more TT components to abstract away these changes,
but the point of diminishing returns appears quickly: TT's syntax and semantics
just aren't strong enough to define functions and manage parameters.</p>

<p>Good thing Perl is.</p>

<p>Fewer than 20 minutes after I realized I needed a custom plugin, I had it
written:</p>

<pre><code>package MyProject::Template::Plugin::Bootstrap;
# ABSTRACT: basic Bootstrap helpers for the Template system

use Modern::Perl;

use parent 'Template::Plugin';

sub new
{
    my ($class, $context, @params) = @_;

    $class-&gt;add_functions( $context );

    return $class-&gt;SUPER::new( $context, @params );
}

sub add_functions
{
    my ($class, $context) = @_;
    my $stash             = $context-&gt;stash;

    for my $function (qw( row sidebar sideblock maincontent fullcontent span ))
    {
        $stash-&gt;set( $function, $class-&gt;can( $function ) );
    }

    $stash-&gt;set( process =&gt; sub { $context-&gt;process( @_ ) } );
}

sub row
{
    return &lt;&lt;END_HTML;
&lt;div class="row"&gt;
    @_
&lt;/div&gt;
END_HTML
}

sub sidebar
{
    return &lt;&lt;END_HTML;
&lt;div class="span4"&gt;
    @_
&lt;/div&gt;
END_HTML
}

sub sideblock
{
    return &lt;&lt;END_HTML;
&lt;div class="well"&gt;
    @_
&lt;/div&gt;
END_HTML
}

sub maincontent
{
    return &lt;&lt;END_HTML
&lt;div class="span8 maincontent"&gt;
    &lt;div class="hero-unit"&gt;
        @_
    &lt;/div&gt;
&lt;/div&gt;
END_HTML
}

sub fullcontent
{
    return &lt;&lt;END_HTML
&lt;div class="maincontent"&gt;
    &lt;div class="hero-unit"&gt;
        @_
    &lt;/div&gt;
&lt;/div&gt;
END_HTML
}

sub span
{
    my $cols = shift;
    return &lt;&lt;END_HTML;
&lt;div class="span$cols"&gt;
    @_
&lt;/div&gt;
END_HTML
}

1;</code></pre>

<p>This turned my templates into:</p>

<pre><code>
[% USE Bootstrap %]

[% row(
    maincontent( process( 'components/content/home_text.tt' ) ),
    sidebar(
        sideblock( process( 'components/forms/login_box.tt' )),
        sideblock( process( 'components/boxes/top_recommendation.tt' ) ),
        sideblock( process( 'components/content/newsletter_text.tt' ) ),
    ),
) %]</code></pre>

<p>This reminds me a bit of <a
href="http://www.seaside.st/documentation/generating-html">Generating HTML from
Smalltalk's Seaside</a> or <a href="http://haml-lang.com/">Ruby HAML</a>,
except it's less "Wow, lots of tags here!" than Seaside and "So cute people
hate you for saying how ugly it is!" than HAML.</p>

<p>I haven't convinced myself I have the right abstractions yet&mdash;it's not
quite to the point of the semantics I like, it produces its own repetitions,
and the idea of returning strings of HTML from a template plugin feels a little
wrong to me, but the big advantage is that it's taken a lot of repetitive
niggly code and turned it into less code that's much more declarative. The
repetition is in the <em>structure</em> of the <em>semantics</em> of the site
and not the mechanics of how to produce those semantics.</p>

<p>In other words, this is a step toward thinking in widgets rather than UI
primitives.</p>

        
    ]]></content:encoded>
			<wfw:commentRss>http://perlblogs.com/2012/02/09/templating-with-widgets-not-primitives/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Practical Use for Macros in Perl</title>
		<link>http://www.modernperlbooks.com/mt/2012/02/a-practical-use-for-macros-in-perl.html</link>
		<comments>http://www.modernperlbooks.com/mt/2012/02/a-practical-use-for-macros-in-perl.html#comments</comments>
		<pubDate>Fri, 03 Feb 2012 20:46:43 +0000</pubDate>
		<dc:creator>chromatic</dc:creator>
				<category><![CDATA[languagedesign]]></category>
		<category><![CDATA[perl5]]></category>
		<category><![CDATA[refactoring]]></category>

		<guid isPermaLink="false">http://perlblogs.com/?guid=5cffcd700874d4b530e9c045dc4412b1</guid>
		<description><![CDATA[People occasionally ask for practical examples of macros when I lament the lack of macros in Perl 5. While I'm usually pleased at the degree to which Perl lets me design code to get and stay out of my way,...]]></description>
			<content:encoded><![CDATA[
        <p>People occasionally ask for practical examples of macros when I lament <a
href="http://www.modernperlbooks.com/mt/2011/11/what-the-perl-5-compiler-modules-could-have-been.html">the
lack of macros in Perl 5</a>. While I'm usually pleased at the degree to which
Perl lets me design code to get and stay out of my way, sometimes its
abstractions just aren't quite <em>enough</em> enough to remove all of the
duplication available.</p>

<p>(I've been refactoring one of our business projects in preparation for another round of deployment in the next couple of weeks. We could launch without these improvements, but administrative work took almost two weeks longer than the afternoon I'd planned for it, so I decided it was worth my time to <a href="http://www.modernperlbooks.com/mt/2011/11/on-technical-friction.html">reduce technical friction</a> so that further improvements are easier. More users means more work, so why not accelerate that work while I have the chance? I have another longer technical post to write to praise the use of Moose roles for a plugin system and to show off the stupidly-great task launcher, but that's for later.)</p>

<p>I found myself writing two code couplets that were similar enough they
triggered my "Hey, refactor away this duplication!" alert. It's extra
sensitive, because I <em>know</em> I'll have a few more couplets like this in
the very near future:</p>

<pre><code>while (my $stock = $stock_rs-&gt;next)
{
    my $pe_update = $self-&gt;analyze_pe( $stock );
    $stock_txn-&gt;add( $pe_update ) if $pe_update;

    my $cash_yield_update = $self-&gt;analyze_cash_yield( $stock );
    $analysis_txn-&gt;add( $cash_yield_update ) if $cash_yield_update;
}</code></pre>

<p>The <code>*_txn</code> variables contain objects representing deferred and
scoped SQL updates. I'll talk about that at <a
href="http://act.yapcna.org/2012/">YAPC::NA 2012</a> in <a
href="http://act.yapcna.org/2012/talk/50">When Wrong is Better</a>.</p>

<p>The general pattern is this: for every stock in the appropriate resultset,
call a method in this plugin. The method will return nothing if it fails (or
has nothing to do) or it will return data to be added to the appropriate
transaction. I have at least two types of transactions available here at the
moment, and may have more later: one transaction updates stock data and the
other updates analysis data.</p>

<p>I have several options. I could rework the data model so that this stage
always only updates one transaction, in which the loop body could instead look
like:</p>

<pre><code>{
    for my $method (qw( analyze_pe analyze_cash_yield ))
    {
        next unless my $result = $self->$method( $stock );
        $txn->add( $result );
    }
}</code></pre>

<p>This technique of hoisting the variants into an ad hoc data structure and
using existing looping techniques works well sometimes. (I use it in other
parts of the system.) It's relatively easy to expand, even though it moves
interesting information ("I'm calling the <code>analyze_pe</code> method!") to
a place where tools have more trouble finding it. (I search for
<code>&gt;analyze_pe</code> when I want to find method calls.) You may have used something similar to define several parametric methods at <code>BEGIN</code> time. It's the same type of pattern, and while Perl 5 provides most of the tools necessary to allow this, it doesn't natively express this pattern well.</p>

<p>I could also change the transaction object's <code>add()</code> method to do
nothing when it receives an empty list of arguments. I like that in some ways,
but I don't like it in others. I've come down on the side of keeping its
invariant (it always takes only one scalar as an object) pure for now. If I
change it to take a list of updates, that might be the right time to reconsider
this.</p>

<p>What I notice in the code as it stands right now is that the individual
variables <code>$pe_update</code> and <code>$cash_yield_update</code> are
synthetic variables. They only exist to support the code as written; they're
not necessary for the algorithm. If I were to modify this code but only this code, I'd really rather write:</p>

<pre><code>{
    ADD_TXN_WITH( $self, analyze_pe,         $stock, $stock_txn    );
    ADD_TXN_WITH( $self, analyze_cash_yield, $stock, $analysis_txn );
}</code></pre>

<p>... though that syntax doesn't thrill me either. The clearest possibility I
see right now is:</p>

<pre><code>{
    $stock_txn-&gt;add(    SKIP unless $self-&gt;analyze_pe( $stock )         );
    $analysis_txn-&gt;add( SKIP unless $self-&gt;analyze_cash_yield( $stock ) );
}</code></pre>

<p>... where <code>SKIP</code> does some magic to move to the next statement,
not the next loop iteration. (I have some ideas how to write XS to make this
work, but that creepy yak needs a shave and some mouthwash.)</p>

<p>The second best option right now is adding a function or method as
indirection to encapsulate the synthetic code. I'd rather avoid synthetic code,
but at least it reduces the possibility of copy and paste bugs.</p>

<p>For now, with only two steps in this analysis, I'm leaving it as it is. Two
repetitions of something this similar set off my refactoring alarm, but I
resist the urge for refactorings this small until I see three instances of
near-duplicate code.</p>

        
    ]]></content:encoded>
			<wfw:commentRss>http://perlblogs.com/2012/02/03/a-practical-use-for-macros-in-perl/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Speed up Perlbrew with Test Parallelism</title>
		<link>http://www.modernperlbooks.com/mt/2012/01/speed-up-perlbrew-with-test-parallelism.html</link>
		<comments>http://www.modernperlbooks.com/mt/2012/01/speed-up-perlbrew-with-test-parallelism.html#comments</comments>
		<pubDate>Fri, 27 Jan 2012 21:20:46 +0000</pubDate>
		<dc:creator>chromatic</dc:creator>
				<category><![CDATA[modernperl]]></category>
		<category><![CDATA[perl5]]></category>
		<category><![CDATA[perlbrew]]></category>
		<category><![CDATA[productivity]]></category>

		<guid isPermaLink="false">http://perlblogs.com/?guid=cbc7696535dd728de1ef9d6b55e34b5a</guid>
		<description><![CDATA[Steven Haryanto's Perl First World Problems #1 reminded me of something I've taken for granted lately. You may have read my Controlling Test Parallelism with prove and Parallelism and Test Suites. I still have Test::Harness parallelism enabled by default on...]]></description>
			<content:encoded><![CDATA[
        <p>Steven Haryanto's <a href="http://blogs.perl.org/users/steven_haryanto/2012/01/perl-first-world-problems-1.html">Perl First World Problems #1</a> reminded me of something I've taken for granted lately.</p>

<p>You may have read my <a
href="http://www.modernperlbooks.com/mt/2011/12/controlling-test-parallelism-with-prove.html">Controlling
Test Parallelism with prove</a> and <a
href="http://www.modernperlbooks.com/mt/2011/11/parallelism-and-test-suites.html">Parallelism
and Test Suites</a>. I still have <code>Test::Harness</code> parallelism
enabled by default on most of the machines where I install my own Perls. While
I haven't yet filed tickets and tried to write patches for modules which need a
little help to run tests in parallel, I've only found a few lately that need
work. That's nice&mdash;having a module install through <code>cpanm</code> in
five seconds is a lot better than ten seconds or more. (I like
<code>cpanm</code> because it's <em>fast</em> and quiet, and part of its speed
comes from not printing to the console.)</p>

<p>I like instant feedback.</p>

<p>Like Steven, I noticed quite a while that installing a custom Perl through <a href="http://perlbrew.org/">perlbrew</a> takes a while, but then I remembered that a lot of work went into the Perl 5 test suite to make tests run in parallel. (We did something similar with Parrot several years ago, and it changed the way I work forever.)</p>

<p>To run core tests in parallel, set the environment variable
<code>TEST_JOBS=<em>n</em></code>, where <em>n</em> depends on your computer. I
use a value of 9 on a quad-core machine; in practice, that tends to keep the
CPU busy while not blocking anything too long on IO. You can set it globally in
your shell's configuration file or create an alias or wrapper for
<code>perlbrew</code>.</p>

<p>As most of the time spent compiling and installing Perl 5 through perlbrew
goes to running the test suite, this has saved me a measurable amount of
time.</p>
        
    ]]></content:encoded>
			<wfw:commentRss>http://perlblogs.com/2012/01/27/speed-up-perlbrew-with-test-parallelism/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Avoiding The Vendor Perl Fad Diet</title>
		<link>http://www.modernperlbooks.com/mt/2012/01/avoiding-the-vendor-perl-fad-diet.html</link>
		<comments>http://www.modernperlbooks.com/mt/2012/01/avoiding-the-vendor-perl-fad-diet.html#comments</comments>
		<pubDate>Wed, 25 Jan 2012 19:46:20 +0000</pubDate>
		<dc:creator>chromatic</dc:creator>
				<category><![CDATA[distributions]]></category>
		<category><![CDATA[p5p]]></category>
		<category><![CDATA[packaging]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[perl5]]></category>

		<guid isPermaLink="false">http://perlblogs.com/?guid=c76c09804e86429f483ba7aab2bb1fe7</guid>
		<description><![CDATA[Here we go again. It looks like Red Hat is distributing Perl without the core library ExtUtils::MakeMaker. If you're not familiar with the details of the Perl 5 build chain, all you need to know is this: without MakeMaker, you're...]]></description>
			<content:encoded><![CDATA[
        <p>Here we go again.</p>

<p>It looks like <a
href="http://www.nntp.perl.org/group/perl.perl5.porters/2012/01/msg182360.html">Red
Hat is distributing Perl without the core library
<code>ExtUtils::MakeMaker</code></a>. If you're not familiar with the details
of the Perl 5 build chain, all you need to know is this: without MakeMaker,
you're not installing anything from the CPAN.</p>

<p>Ostensibly Red Hat and other OS distribution vendors split up Perl 5 into
separate packages to save room on installation media. Core Perl 5 is large and
includes many, many things that not everyone uses all the time... but <a
href="http://www.nntp.perl.org/group/perl.perl5.porters/2012/01/msg182376.html">the
obvious reaction to defining a core subset of Perl 5 that a vendor can call
"perl"</a> is another of those recurring discussions which never quite goes
anywhere.</p>

<p>For example, who needs the documentation just to run code? (Except that the
<code>diagnostics</code> pragma relies on the existence of
<em>perldiag.pod</em> to run.) Who needs the huge Unicode encoding tables for
ideographic languages such as you might find in Japan, China, Korea, and other
Asian locals? (Answer: Asia.) Who needs the ability to install code from the
CPAN? (Answer: users.)</p>

<p>While there's a lot of stuff in the core that probably doesn't need to be in
the core, or at least installed by default (a LaTex formatter for POD, the <a
href="http://search.cpan.org/perldoc?Switch">deprecated Switch module</a>, Perl
5.005 <a href="http://search.cpan.org/perldoc?Thread">Thread</a> emulation),
one thing is both clear and almost never said.</p>

<p>I'll give you a moment to think about it.</p>

<p>Here's a hint: you're usually better off compiling and installing your own
Perl 5 under your complete control such that you can compile in options you
want (64-bit integers, for example) and out options you don't (threading
imposes a 15% performance penalty even in the single-threaded case) and so that
you can manage your own library paths without changing the behavior of the
system). <a href="http://perlbrew.org/">perlbrew</a> changes the game. Learn
it, like it, love it.</p>

<p>The perpetual discussion misses one important point:</p>

<p>The vendor <code>perl</code>&mdash;especially on installation media&mdash;is
not for general purpose Perl programming. It's there only to support basic
administrative programs provided with the system as a whole. <em>That's</em>
why you don't replace the system Perl. <em>That's</em> why you don't mess with
the system CPAN modules. That's why you fence off whatever's in
<em>/usr/bin/perl</em> like it's Yucca Mountain and you're stuck with a '50s
reactor design instead of something safe and clean.</p>

<p>Vendors can tune and tweak that Perl to their satisfaction to provide just
what they need to install and configure a working system. They can keep it as
crufty and out of date as they like. When it breaks, they get to keep all of
the pieces and sew them back together like some sort of Fedorastein's monster.
They just can't let it out of the lab.</p>

<p>This of course means that they need to provide packages of Perl 5 Actual for
users and developers such that it's the full core of Perl 5. (It'd be nice if
they called not-a-perl as such, but one thing at a time.)</p>

<p>You can't predict what users will and won't do. That's why you code
defensively. The moment distributions started carving up Perl to install just
the little bits they needed in the hopes that their guesses as to what users
wanted were right, they put everyone in a bind.</p>

<p>Certainly Perl 5 could benefit from a thorough review of what's in core and
why, but I suspect that even if p5p came up with packaging guidelines for all
of the imaginable use cases and combinations of distributor needs and user
wants, it still wouldn't solve the real problem.</p>

<p>(Credit Allison Randal for pointing out the real problem <em>years</em> ago. We've discussed several times the idea of a stripped-down VM for a real language&mdash;something with better abstraction and reuse than Bash&mdash;with easy access to libraries and a very small footprint, but it's a bigger job than either of us could accomplish. It's still a righter approach than bowdlerizing an upstream distribution.)</p>
        
    ]]></content:encoded>
			<wfw:commentRss>http://perlblogs.com/2012/01/25/avoiding-the-vendor-perl-fad-diet/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Imagine if caller() Returned Stack-Capturing Objects</title>
		<link>http://www.modernperlbooks.com/mt/2012/01/imagine-if-caller-returned-stack-capturing-objects.html</link>
		<comments>http://www.modernperlbooks.com/mt/2012/01/imagine-if-caller-returned-stack-capturing-objects.html#comments</comments>
		<pubDate>Wed, 18 Jan 2012 22:13:36 +0000</pubDate>
		<dc:creator>chromatic</dc:creator>
				<category><![CDATA[features]]></category>
		<category><![CDATA[modernperl]]></category>
		<category><![CDATA[perl5]]></category>

		<guid isPermaLink="false">http://perlblogs.com/?guid=47fb4f1abad1303711ce188263f3f9a5</guid>
		<description><![CDATA[Imagine if Perl 5's caller returned an object which represented the call chain to the point of the object's creation. I want to inspect the call stack within a helper module, but I don't care about the call stack within...]]></description>
			<content:encoded><![CDATA[
        <p>Imagine if Perl 5's <a
href="http://perldoc.perl.org/perlfunc.html#caller"><code>caller</code></a>
returned an object which represented the call chain to the point of the
object's creation.</p>

<p>I want to inspect the call stack within a helper module, but I don't care about the call stack <em>within</em> the module. I want to use lots of little helper functions, because that's good design, but <code>caller</code> works against that. Looking up the stack means keeping track of the magic number of call frames within my module I currently use, and that's one more thing to update when I change things.</p>

<p>That's structural code highly coupled to the arrangement of other code, and
if that doesn't wrinkle your nose with the subtle aroma of fragility and peril,
I don't know what will.</p>

<p>Imagine if instead:</p>

<pre><code>my $caller_object = capture_caller_state();

while (my $call_frame = $caller_object-&gt;next)
{
    next if $call_frame-&gt;is_eval;
    say $call_frame-&gt;location_as_string;
    my $next_frame = $call_frame-&gt;previous;
    ...
}</code></pre>

<p>Imagine if you could <em>pass this object around</em>.</p>

<p>I know things get complicated if you pass this object up the call chain, but
stack unwinding is a solved problem in that anyone capable of recognizing the
problem should be able to figure out cheap and easy ways to fix it.</p>

<p>Alas, Perl 5.14 doesn't have this feature, and it's probably too late for
5.16 to get it, so for today I'm stuck imagining what might be.</p>

<p>(If you've never thought about this sort of thing before, you owe it to yourself to learn more about <a href="http://c2.com/cgi/wiki?ContinuationPassingStyle">Continuation Passing Style</a>, which is at least an order of magnitude more mind-bending at the start and at least two orders of magnitude more useful.)</p>

        
    ]]></content:encoded>
			<wfw:commentRss>http://perlblogs.com/2012/01/19/imagine-if-caller-returned-stack-capturing-objects/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

