<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Modern Perl Books for modern Perl programming</title>
    <link rel="alternate" type="text/html" href="http://www.modernperlbooks.com/mt/" />
    <link rel="self" type="application/atom+xml" href="http://www.modernperlbooks.com/mt/atom.xml" />
    <id>tag:www.modernperlbooks.com,2009-01-23:/mt//1</id>
    <updated>2012-02-03T21:25:54Z</updated>
    <subtitle>To solve a problem now, reach for Perl. To solve a problem right, reach for Modern Perl.
</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type 4.23-en</generator>

<entry>
    <title>A Practical Use for Macros in Perl</title>
    <link rel="alternate" type="text/html" href="http://www.modernperlbooks.com/mt/2012/02/a-practical-use-for-macros-in-perl.html" />
    <id>tag:www.modernperlbooks.com,2012:/mt//1.408</id>

    <published>2012-02-03T20:46:43Z</published>
    <updated>2012-02-03T21:25:54Z</updated>

    <summary>People occasionally ask for practical examples of macros when I lament the lack of macros in Perl 5. While I&apos;m usually pleased at the degree to which Perl lets me design code to get and stay out of my way,...</summary>
    <author>
        <name>chromatic</name>
        <uri>http://www.wgz.org/~chromatic</uri>
    </author>
    
    <category term="languagedesign" label="language design" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl5" label="perl 5" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="refactoring" label="refactoring" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.modernperlbooks.com/mt/">
        <![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>
</entry>

<entry>
    <title>Why I Run Tests on Install</title>
    <link rel="alternate" type="text/html" href="http://www.modernperlbooks.com/mt/2012/01/why-i-run-tests-on-install.html" />
    <id>tag:www.modernperlbooks.com,2012:/mt//1.407</id>

    <published>2012-01-31T18:41:08Z</published>
    <updated>2012-01-31T19:13:46Z</updated>

    <summary>Jonathan Swartz makes a polemic statement: cpanm and perlbrew should not run tests by default. His points are reasonable, but his complaints are mostly about side effects and not the real problem. (I should clarify: the real problem I encounter.)...</summary>
    <author>
        <name>chromatic</name>
        <uri>http://www.wgz.org/~chromatic</uri>
    </author>
    
    <category term="cpan" label="cpan" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="modernperl" label="modern perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="testing" label="testing" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.modernperlbooks.com/mt/">
        <![CDATA[<p>Jonathan Swartz makes a polemic statement:</p>

<blockquote><em><a href="http://www.openswartz.com/2012/01/31/stop-running-tests-on-install/">cpanm and perlbrew should not run tests by default.</a></em></blockquote>

<p>His points are reasonable, but his complaints are mostly about side effects
and not the real problem. (I should clarify: the real problem <em>I</em>
encounter.)</p>

<p>If running tests slow down installs, speed up the tests. (Do you want to get the wrong answer faster? Easy: it's 42. No need for a quantum computer to do the calculation in constant time. This algorithm is O(0).)</p>

<p>If running tests exposes the fragility of the dependency chain, improve the dependency chain.</p>

<p>If dependency test failures prevent the installation of downstream
clients... this <em>is</em> a weakness of the CPAN toolchain. A well-written
test suite for a downstream client should reveal whether bugs or other sources
of test failures in a dependency affect the correctness of the client.</p>

<p>Note the assumptions in that sentence.</p>

<p>Anyone who's experienced the flash of enlightenment that comes from working
with well tested code and who's shared that new zeal with co-workers has
undoubtedly heard the hoary old truism that testing cannot prove the complete
absence of bugs. It's no less true for its age, though it's also true that
<em>good</em> testing only improves our confidence in the correctness and
efficacy of our code.</p>

<p>For me, a 95% certainty that my code works and continues to work for the
things to which I've tested it is more than sufficient. I focus on testing the
things I'm most likely to get wrong and the things which need to keep working
correctly. (I don't care much about pixel-perfect placement, but I do care that
a book's index uses the right escapes for its data and markup.)</p>

<p>Without tests running on the machines themselves in the environments
themselves where I expect my code to run, I don't have that confidence.</p>

<p>Put another way, I'm either not smart enough or far too lazy to want to
attempt to debug code without good tests. That's why I write tests, and that's
why I run them obsessively. That's good for me as a developer, and you're
getting the unvarnished developer perspective.</p>

<p><a href="http://www.modernperlbooks.com/mt/2011/10/in-search-of-minimum-viable-utility.html">I also care about the perspective of mere users</a>. (Without users, we're amusing ourselves, and I can think of better ways to amuse myself than by writing software no one uses.).</p>

<p>Yes, an excellent test suite can help a user help a developer debug a
problem. Many (most?) CPAN authors have had the wonderful experience of
receiving a bug report with a failing test case. Sometimes this even includes a
code patch.</p>

<p>Not all users are developers of that sort, nor should they be.</p>

<p>The CPAN ecosystem has improved greatly at automated testing and dependency tracking, but we can improve further. What if we could identify the severity of test failures? (We have TODO and SKIP, but they don't convey semantic meaning.) What if we could identify buggy or fragile tests? (My current favorite is <a href="https://rt.cpan.org/Ticket/Display.html?id=69540">XML::Feed tests versus DateTime::Format::Atom</a> because it catches me far too often, it doesn't affect the operation of the code, and it's a stupid fix that's lingered for a few months.) What if the failures are transient (Mechanize relying on your ISP <em>not</em> ruining DNS lookups for you) or specific to your environment (a test suite written without parallelism in mind).</p>

<p>As Jonathan rightly implies, how do you expect an end-user to understand or
care about or debug those things?</p>

<p>I'm still reluctant to agree that disabling tests for end-user installations
is the right solution. I <em>want</em> to know about failures in the wild wider
world. I want that confidence, but I can't bring myself to trade away that
confidence for the sake of a little more speed of installation.</p>

<p>Yet his point about lingering points of fragility in the ecosystem are true
and important, even if the proposed solution of skipping tests isn't right.
Fortunately, improving dependency management and tracking and use and testing
can help solve both issues: perhaps to the point where we can run only those
tests users most care about and identify and report material failures in
dependencies.</p>
]]>
        
    </content>
</entry>

<entry>
    <title>Speed up Perlbrew with Test Parallelism</title>
    <link rel="alternate" type="text/html" href="http://www.modernperlbooks.com/mt/2012/01/speed-up-perlbrew-with-test-parallelism.html" />
    <id>tag:www.modernperlbooks.com,2012:/mt//1.406</id>

    <published>2012-01-27T21:20:46Z</published>
    <updated>2012-01-27T21:41:11Z</updated>

    <summary>Steven Haryanto&apos;s Perl First World Problems #1 reminded me of something I&apos;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...</summary>
    <author>
        <name>chromatic</name>
        <uri>http://www.wgz.org/~chromatic</uri>
    </author>
    
    <category term="modernperl" label="modern perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl5" label="perl 5" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perlbrew" label="perlbrew" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="productivity" label="productivity" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.modernperlbooks.com/mt/">
        <![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>
</entry>

<entry>
    <title>Avoiding The Vendor Perl Fad Diet</title>
    <link rel="alternate" type="text/html" href="http://www.modernperlbooks.com/mt/2012/01/avoiding-the-vendor-perl-fad-diet.html" />
    <id>tag:www.modernperlbooks.com,2012:/mt//1.405</id>

    <published>2012-01-25T19:46:20Z</published>
    <updated>2012-01-25T20:07:31Z</updated>

    <summary>Here we go again. It looks like Red Hat is distributing Perl without the core library ExtUtils::MakeMaker. If you&apos;re not familiar with the details of the Perl 5 build chain, all you need to know is this: without MakeMaker, you&apos;re...</summary>
    <author>
        <name>chromatic</name>
        <uri>http://www.wgz.org/~chromatic</uri>
    </author>
    
    <category term="distributions" label="distributions" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="p5p" label="p5p" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="packaging" label="packaging" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl5" label="perl 5" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.modernperlbooks.com/mt/">
        <![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>
</entry>

<entry>
    <title>A Decades-Old Technique to Improve Programming Languages</title>
    <link rel="alternate" type="text/html" href="http://www.modernperlbooks.com/mt/2012/01/a-decades-old-technique-to-improve-programming-languages.html" />
    <id>tag:www.modernperlbooks.com,2012:/mt//1.404</id>

    <published>2012-01-23T20:22:23Z</published>
    <updated>2012-01-23T23:27:51Z</updated>

    <summary>I promised in Testing Your Templates to explain how to solve the problem of the divergence between testable, debuggable code in your host language and a big wad of logic in a template language. This problem is an example of...</summary>
    <author>
        <name>chromatic</name>
        <uri>http://www.wgz.org/~chromatic</uri>
    </author>
    
    <category term="languagedesign" label="language design" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="lisp" label="lisp" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="modernperl" label="modern perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.modernperlbooks.com/mt/">
        <![CDATA[<p>I promised in <a
href="http://www.modernperlbooks.com/mt/2012/01/testing-your-templates-and-why-it-doesnt-always-work.html">Testing
Your Templates</a> to explain how to solve the problem of the divergence
between testable, debuggable code in your host language and a big wad of logic
in a template language.</p>

<p>This problem is an example of the pattern of Why Writing Your Own DSL is
More Difficult Than You Think. Certainly Template Toolkit is among the better
templating systems (I've written a couple myself), but it exhibits problems
endemic to the process. (Then again, so does PHP. Now multiply that by the fact
that some people use templating systems <em>written in PHP</em> and if you have
to lie down for a while before the feeling passes, please accept my
apologies.)</p>

<p>The semantics of Template Toolkit are great, when they work, but then
everything's great when it works the way you expect. Robust software handles
the cases you don't expect with aplomb, or at least without a boom.</p>

<p>A simple workaround for Template Toolkit is to avoid the fallback from potential method lookup to keyed hash access when dealing with an object. In other words, if <code>$blessed_hash-&gt;do_something()</code> fails, try <code>$blessed_hash-&gt;{do_something}</code>.</p>

<p>... except that that doesn't work when you want to call virtual methods on
unblessed references, such as calling methods on arrays or hashes.</p>

<p>Another option is to change the syntax such that calling a method is visibly different from accessing a member of an aggregate. Perl 5 does this. It works pretty well, in the sense that if you use the right operator (access element versus invoke method), you've expressed your intent in a visually unambiguous fashion).</p>

<p>... except that people complain about the Perl 5 dereferencing arrow quite a
bit. (Okay, you don't <em>need</em> an arrow to do this; as the <a
href="http://onyxneon.com/books/modern_perl/index.html">Modern Perl book</a>
explains, the postfix indexed access or postfix keyed operators of
<code>{}</code> and <code>[]</code> determine the type of operation
effectively.)</p>

<p>... and except that one of the design goals of Template Toolkit was to be
robust in the face of changing values provided to the template, such that it
provides a loosely coupled interface for the data it expects. That's a fine
goal, but it isn't free.</p>

<p>Here's the thing, though. The last time I looked, Template Toolkit compiles
templates into Perl 5 code as an optimization. (The last template system I
wrote did the same thing, but not as well. We should have used TT, but in our
defense, TT didn't exist then.) This transliteration/compilation stage must be
very, very cautious to allow standard Perl debugging and introspection tools to
treat this generated code correctly. That is to say, I don't want to debug a
big wad of generated code. I want to debug the code I actually wrote.</p>

<p>As usual, the solution is another layer of abstraction.</p>

<p>Perl 5 exists in two forms. The first is the source code you and I write.
The second is the optree which the Perl 5 VM executes. There's nothing in
between. You have one or the other. When your code runs, you have the optree,
and the optree has references to the relevant location in the source code it
came from, but the correspondence is often less useful than you might like.</p>

<p>While the generated code from Template Toolkit could include the correct
file and line positions from templates, that's again less useful than you might
like. (It's useful, but it doesn't solve every problem.)</p>

<p>If Perl 5 had instead an intermediate form separate from raw code and raw
optrees, something more suitable to introspection and manipulation, we could
produce tools which worked with this intermediate form to improve debugging,
introspection, and better code generation.</p>

<p>We could even <em>inject</em> new code to add features (fall back to
attribute access; prevent the fallback to attribute access) to code, even
within lexical scopes. That is to say, we could manipulate how libraries behave
from the outside in, and ensure that our changes would not leak out from our
desired scopes.</p>

<p>It's certainly possible to replace the Perl 5 opcodes yourself, if you're
comfortable reading Perl 5 source code, writing XS, relying on black magic, and
dealing with strange issues of thread safety and manipulating global or at
least interpreter-global values in a lexical fashion (while dealing with the
fact that <code>use</code> is recursive in a sense)&mdash;but isn't Perl about
<em>not</em> making people write C to do interesting things?</p>

<p>Certainly this isn't a technique you'd use every day, and it's not obviously
a way to make Perl 5 run faster (though many optimizations become much easier),
but the possibility for better abstraction and extension and correctness has
much to recommend it.</p>

<p>And, yes, Lisp demonstrated this idea <em>ages</em> ago.</p>]]>
        
    </content>
</entry>

</feed>

