<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Perl.com</title>
    <link rel="alternate" type="text/html" href="http://www.perl.com/pub/" />
    <link rel="self" type="application/atom+xml" href="http://www.perl.com/pub/atom.xml" />
    <id>tag:www.perl.com,2010-07-21:/pub//2</id>
    <updated>2012-02-03T01:38:25Z</updated>
    
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type Pro 5.12</generator>

<entry>
    <title>Perl in Plat_Forms 2012 Web Development Contest</title>
    <link rel="alternate" type="text/html" href="http://www.perl.com/pub/2012/02/perl-in-plat-forms-2012-web-development-contest.html" />
    <id>tag:www.perl.com,2012:/pub//2.1976</id>

    <published>2012-02-03T01:33:35Z</published>
    <updated>2012-02-03T01:38:25Z</updated>

    <summary>Thanks to Lars Dɪᴇᴄᴋᴏᴡ for coordinating entries into the Plat_Forms 2012 web development contest. This annual contest pits some of the best developers of frameworks and languages against each other to solve real problems. Perl developers have participated for several...</summary>
    <author>
        <name>chromatic</name>
        <uri>http://www.modernperlbooks.com/</uri>
    </author>
    
    <category term="webdevelopment" label="web development" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.perl.com/pub/">
        <![CDATA[<p>Thanks to <a href="http://search.cpan.org/~daxim/">Lars Dɪᴇᴄᴋᴏᴡ</a> for coordinating entries into the <a href="http://www.plat-forms.org/platforms-2012-announcement#overview">Plat_Forms 2012</a> web development contest. This annual contest pits some of the best developers of frameworks and languages against each other to solve real problems. Perl developers have participated for several years. Teams using Catalyst, Dancer, and Mojolicious have all demonstrated their platform strengths and weaknesses.</p>

<p>No Perl team has won the contest&mdash;yet. With the rise of modern Perl 5, the extra energy from competition between all of the great platforms, and (of course) the power of the CPAN, we all expect great things. Consider entering and showing what we can do.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Building Telephony Applications with Perl and TwiML</title>
    <link rel="alternate" type="text/html" href="http://www.perl.com/pub/2011/12/building-telephony-applications-with-perl-and-twiml.html" />
    <id>tag:www.perl.com,2011:/pub//2.1974</id>

    <published>2011-12-12T14:00:01Z</published>
    <updated>2011-12-13T19:30:40Z</updated>

    <summary>Scott Wiersdorf shows how to write a little bit of Perl to build an automated voice mail menu with Twilio&apos;s API.</summary>
    <author>
        <name>Scott Wiersdorf</name>
        <uri>http://perlcode.org/</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://www.perl.com/pub/">
        <![CDATA[<p>Perl makes writing Twilio telephony applications simple and enjoyable. My
previous article, <a href="http://www.perl.com/pub/2011/09/automating-telephony-with-perl-and-twilio.html">Automating Telephony with Perl and
Twilio</a>
showed how to use
<a href="http://search.cpan.org/perldoc?WWW::Twilio::API">WWW::Twilio::API</a> to make a
phone survey using Twilio's text-to-speech synthesizer as well as send an SMS
message to a phone number of your choice.</p>

<p>This article builds an easy phone menu application using Twilio's
<a href="http://www.twilio.com/docs/api/twiml/">TwiML</a> application language,
<a href="http://search.cpan.org/perldoc?WWW::Twilio::TwiML">WWW::Twilio::TwiML</a>, and
<a href="http://mojolicio.us/">Mojolicious</a>.</p>

<h2><strong>Installation and Twilio account creation</strong></h2>

<p>To begin, install WWW::Twilio::TwiML and Mojolicious using your <a href="http://www.cpan.org/modules/INSTALL.html">favorite
method</a> (see the previous article for
more ideas). You'll need a <a href="http://www.twilio.com/">Twilio</a> account (it's free
to create an account, plus Twilio gives new users US $30 for calls--plenty for
several weeks of testing). The previous article covers installation and getting
setup with a Twilio account in more detail.  With WWW::Twilio::TwiML and
Mojolicious installed and a Twilio account active, it's a great time to get a
little more familiar with Twilio's Dashboard.</p>

<h2><strong>Twilio Dashboard</strong></h2>

<p>The <a href="https://www.twilio.com/user/account">Twilio Dashboard</a> is where to find
your Twilio sandbox information. The sandbox section of the dashboard is
located below the fold of the dashboard page:</p>

<p><img src="/pub/2011/12/12/dashboard.png" alt="Twilio Dashboard" title="" /></p>

<p>You should see the sandbox number and pin. You can set our inbound voice and
inbound SMS handler URLs there (I'll explain those soon.) First, a primer on
how Twilio works.</p>

<h2><strong>TwiML in the Twilio flow</strong></h2>

<p>Twilio's basic flow goes something like:</p>

<p><figure>
<img src="/pub/2011/12/12/twilio-inbound-full.png" alt="Handling an inbound call to Twilio" title="" />
<figcaption>(This diagram is not an official Twilio diagram; it merely describes the author's mental model of how Twilio works and may differ wildly from Twilio's actual implementation.)</figcaption>
</figure></p>

<ol>
<li><p>The caller dials (or sends an SMS to) "555-867-5309" on their phone--this is your Twilio sandbox or purchased number. Twilio's inbound call dispatcher receives the call or text.</p></li>
<li><p>Once the connection is made, the dispatcher makes an HTTP <code>GET</code> or <code>POST</code> to
the Voice or SMS URL specified given for this number. Remember the Voice URL in
the Sandbox App of the Twilio Dashboard shown above? That's the one. For
purchased Twilio numbers, you set the voice and SMS URLs under the "Numbers"
tab in the Dashboard.</p></li>
<li><p>The Voice or SMS URL specified in the Sandbox App responds to the Twilio
request with a <em>TwiML document</em>. Twilio's TwiML parser reads this document,
then executes the "verbs" specified in the TwiML document. For example, if the
TwiML document contained a <code>&lt;Say&gt;</code> verb, Twilio's
text-to-speech synthesizer would "read" the text to the caller. If the document
specified a <code>&lt;Dial&gt;</code> verb and number, Twilio would dial the
number and connect the caller to it. <code>&lt;Redirect&gt;</code> verbs tell
Twilio to fetch another TwiML document.</p></li>
</ol>

<p>You may recall an example in the previous article which used Twilio's
<a href="http://labs.twilio.com/twimlets/voicemail">voicemail TwiML handler</a> to conduct
a brief phone survey. While you can sometimes manipulate third-party TwiML
applications to do what you want, TwiML is so simple to use that you'll find
it's often easier to write your own.</p>

<h2><strong>TwiML basics</strong></h2>

<p>TwiML is a subset of XML. Here is a TwiML document that when read by Twilio's
parser, will say to the caller, "Foosball at 10 o'clock!" using the
text-to-speech synthesizer:</p>

<pre><code>&lt;?xml version="1.0" encoding="UTF-8" ?&gt;
&lt;Response&gt;
  &lt;Say voice="man"&gt;Foosball at 10 o&amp;apos;clock!&lt;/Say&gt;
&lt;/Response&gt;
</code></pre>

<p>Some TwiML verbs are nestable:</p>

<pre><code>&lt;?xml version="1.0" encoding="UTF-8" ?&gt;
&lt;Response&gt;
  &lt;Gather action="/menu.cgi" numDigits="1" method="GET"&gt;
    &lt;Say voice="man"&gt;
      Ping pong at high noon!
      Hit 1 if you&amp;apos;re with me.
      Hit 2 if you&amp;apos;re a loser.
    &lt;/Say&gt;
  &lt;/Gather&gt;

  &lt;Say&gt;You must make a choice!&lt;/Say&gt;
&lt;/Response&gt;
</code></pre>

<p>The <code>&lt;Gather&gt;</code> verb tells Twilio to start gathering key
presses. Meanwhile, Twilio will hand off the contents of the
<code>&lt;Say&gt;</code> verb to the text-to-speech handler. Nesting the
<code>&lt;Say&gt;</code> inside of the <code>&lt;Gather&gt;</code> lets the
caller push a key anytime during the <code>&lt;Say&gt;</code> verb to interrupt
it and process your choice. The final <code>&lt;Say&gt;</code> element only
executes if the <code>&lt;Gather&gt;</code> fails (e.g., the caller doesn't
press a key).</p>

<p>Twilio's excellent documentation details <a href="http://www.twilio.com/docs/api/twiml/">all of the available TwiML
verbs</a>. Armed with a little knowledge,
you're dangerouly close to making something useful.</p>

<h2><strong>Simple phone menu</strong></h2>

<p>You've been asked to build a phone menu system for a young urban professional
and his family. The application should accept an incoming call, prompt the
caller with a numeric menu, and connect the caller with the number of their
choice.</p>

<p>No problem. Start with a simple static TwiML document called <em>menu.xml</em>:</p>

<pre><code>&lt;?xml version="1.0" encoding="UTF-8" ?&gt;
&lt;Response&gt;
  &lt;Gather method="GET" action="/menu_handler" numDigits="1"&gt;
    &lt;Say&gt;Press 1 for Ryan&lt;/Say&gt;
    &lt;Say&gt;Press 2 for Liz&lt;/Say&gt;
    &lt;Say&gt;Press 3 for Jason&lt;/Say&gt;
    &lt;Say&gt;Press 4 for Erin&lt;/Say&gt;
    &lt;Say&gt;Press 5 for Rachel&lt;/Say&gt;
    &lt;Say&gt;Press 6 for Gilligan&lt;/Say&gt;
    &lt;Say&gt;Press 7 for Potsie&lt;/Say&gt;
  &lt;/Gather&gt;
&lt;/Response&gt;
</code></pre>

<p>You can put this file on the web and update the URL in the "Voice URL" field of
the Sandbox section of the Dashboard. Anyone who dials the sandbox number, will
hear a Twilio's text-to-speech voice reading the menu options. Anybody remember
the "S.A.M." speech synthesizer from the mid 80's (Commodore 64 or Atari 800)?
You've come a long way, baby!</p>

<p>While this static TwiML file would work, it does mean you'll have two files to
update when a phone number changes. Fix that by consolidating the
<code>/menu</code> and <code>/menu_handler</code> "routes" (the Mojolicious
word for URL handlers) into a single program to generate TwiML dynamically.</p>

<h2><strong>WWW::Twilio::TwiML, briefly</strong></h2>

<p>WWW::Twilio::TwiML is a special-purpose XML generator and supports several
programming styles. For example, the following two code snippets create this
TwiML document:</p>

<pre><code>&lt;?xml version="1.0" encoding="UTF-8" ?&gt;
&lt;Response&gt;
    &lt;Say voice="man"&gt;Kilroy was here&lt;/Say&gt;
&lt;/Response&gt;
</code></pre>

<p>Snippet number 1:</p>

<pre><code>my $say = WWW::Twilio::TwiML-&gt;new();
$say−&gt;name('Say');
$say−&gt;content("Kilroy was here");
$say−&gt;attributes({voice =&gt; "man"});

my $resp = WWW::Twilio::TwiML-&gt;new();
$resp−&gt;name('Response');
$resp−&gt;content($say);

my $tw = WWW::Twilio::TwiML-&gt;new();
$tw−&gt;content($resp);
print $tw−&gt;to_string;
</code></pre>

<p>And snippet number 2:</p>

<pre><code>my $tw = WWW::Twilio::TwiML-&gt;new();
$tw−&gt;Response−&gt;Say({voice =&gt; "man"}, "Kilroy was here");
print $tw−&gt;to_string;
</code></pre>

<p>The second snippet uses a technique called "method chaining"; if you've used
the jQuery module for Javascript, you may already know how powerful chaining
object methods can be in certain contexts. <code>WWW::Twilio::TwiML</code> makes chaining
possible because each TwiML verb method is a constructor of another
<code>WWW::Twilio::TwiML</code> object.</p>

<p>When you chain TwiML objects like this:</p>

<pre><code>$tw-&gt;Response-&gt;Say("Eat at Joe&amp;apos;");
</code></pre>

<p>The <code>Response</code> object is created as a child of the top
<code>$tw</code> object. The <code>Say</code> object is created as the child of
the <code>Response</code> object. When the <code>$tw</code> object's
<code>to_string</code> method is invoked, like this:</p>

<pre><code>print $tw-&gt;to_string;
</code></pre>

<p><code>WWW:Twilio::TwiML</code> crawls down <code>$tw</code>'s list of children,
recursively invoking <code>to_string</code> until the last child. The whole
process creates this output:</p>

<pre><code>&lt;?xml version="1.0" encoding="UTF-8" ?&gt;
&lt;Response&gt;
    &lt;Say&gt;Eat at Joe&amp;apos;&lt;/Say&gt;
&lt;/Response&gt;
</code></pre>

<p>It's may look a little foreign, but it makes for concise and readable TwiML.</p>

<h2><strong>Getting your mojo on</strong></h2>

<p>Now that you have a feel for creating TwiML documents, you need a way to serve
them from the web.</p>

<p><a href="http://mojolicio.us/">Mojolicious</a> is an easy-to-use web application
framework. Just a few lines and you have a sweet little web app to serve TwiML.
Feel free to read a little of the Mojolicious documentation. This author highly
recommends going through the
<a href="http://mojolicio.us/perldoc/Mojolicious/Lite">Mojolicious::Lite</a> documentation
first: almost everything you learn in Mojolicious::Lite also applies to the
larger Mojolicious application framework.</p>

<p>To write just enough Mojolicious to do what you've already done with the static
TwiML document, you need only two modules for this entire application. (Neither
has any dependencies--you're welcome.) Keep in mind that <code>Mojolicious::Lite</code>
enables 'warnings' and 'strict' by default: no sloppy programming allowed!</p>

<p>This application implements a Mojolicious handler for the <code>/menu</code>
route which is only called when the application receives an HTTP <code>GET</code> to the
<code>/menu</code> URI.</p>

<pre><code>#!/usr/bin/env perl

use Mojolicious::Lite;
use WWW::Twilio::TwiML;

get '/menu' =&gt; sub {
    my $self = shift;

    $self-&gt;render(format =&gt; 'xml',
                  text   =&gt; &lt;&lt;'_TWIML_');
&lt;?xml version="1.0" encoding="UTF-8" ?&gt;
&lt;Response&gt;
  &lt;Gather method="GET" action="/menu_handler" numDigits="1"&gt;
    &lt;Say&gt;Press 1 for Ryan&lt;/Say&gt;
    &lt;Say&gt;Press 2 for Liz&lt;/Say&gt;
    &lt;Say&gt;Press 3 for Jason&lt;/Say&gt;
    &lt;Say&gt;Press 4 for Erin&lt;/Say&gt;
    &lt;Say&gt;Press 5 for Rachel&lt;/Say&gt;
    &lt;Say&gt;Press 6 for Gilligan&lt;/Say&gt;
    &lt;Say&gt;Press 7 for Potsie&lt;/Say&gt;
  &lt;/Gather&gt;
&lt;/Response&gt;
_TWIML_
};

app-&gt;start;
</code></pre>

<p>That's all it takes for a Mojolicious application (source <a href="/pub/2011/12/12/menu_static">here</a>).
Mojolicious packs a full stack HTTP 1.1 web server, making tests easy. In one
shell, start your Mojolicious program as a daemon (use Ctrl-c to stop when
finished):</p>

<pre><code>$ perl menu_part daemon
[Mon Nov 14 21:41:34 2011] [info] Server listening (http://*:3000)
Server available at http://127.0.0.1:3000.
</code></pre>

<p>In another shell, pretend you're Twilio's application server and fetch the
TwiML:</p>

<pre><code>$ curl http://localhost:3000/menu
&lt;?xml version="1.0" encoding="UTF-8" ?&gt;
&lt;Response&gt;
  &lt;Gather method="GET" action="/menu_handler" numDigits="1"&gt;
    &lt;Say&gt;Press 1 for Ryan&lt;/Say&gt;
    &lt;Say&gt;Press 2 for Liz&lt;/Say&gt;
    &lt;Say&gt;Press 3 for Jason&lt;/Say&gt;
    &lt;Say&gt;Press 4 for Erin&lt;/Say&gt;
    &lt;Say&gt;Press 5 for Rachel&lt;/Say&gt;
    &lt;Say&gt;Press 6 for Gilligan&lt;/Say&gt;
    &lt;Say&gt;Press 7 for Potsie&lt;/Say&gt;
  &lt;/Gather&gt;
&lt;/Response&gt;
</code></pre>

<p>Is this progress? This is same TwiML as in <em>menu.xml</em>, but now it's
created with Mojolicious. At this point you can upload your app to a publicly
accessible server, and, assuming Mojolicious is also installed there, you can
start your application. Then go to the Twilio Dashboard and replace the
existing Voice URL with:</p>

<pre><code>http://your.server.org:3000/menu
</code></pre>

<h3>Important note about Mojolicious and HTTP GET</h3>

<p>Mojolicious's <code>get</code> method only responds to HTTP <code>GET</code> method
requests. Make sure that when you set the Voice URL in the Twilio Dashboard,
you also change the HTTP method to <code>GET</code>. Alternatively, you could use
Mojolicious's <code>post</code> method, which only responds to HTTP <code>POST</code>, or
the <code>any</code> method, which accepts both <code>GET</code> and <code>POST</code> (as well as
<code>PUT</code> and <code>DELETE</code>), but making Twilio use HTTP <code>GET</code> seems more appropriate.</p>

<h2><strong>Putting it all together</strong></h2>

<p>Now it's time to improve the program because it still serves static TwiML.  It
also needs a programmatic way tell Twilio what to do when the caller presses a
key.</p>

<p>Start over and make a hash for the phone menu. This could be put into a
separate file--and probably should be--but it wouldn't be a proper tutorial
without <em>something</em> left as an exercise.</p>

<pre><code>#!/usr/bin/env perl

use Mojolicious::Lite;
use WWW::Twilio::TwiML;

my %list = ( 1 =&gt; { name =&gt; 'Ryan',
                    number =&gt; '+19165557720' },
             2 =&gt; { name =&gt; 'Liz',
                    number =&gt; '+19165551211' },
             3 =&gt; { name =&gt; 'Jason',
                    number =&gt; '+19285550122' },
             4 =&gt; { name =&gt; 'Erin',
                    number =&gt; '+19285551729' },
             5 =&gt; { name =&gt; 'Rachel',
                    number =&gt; '+18015553992' },
             6 =&gt; { name =&gt; 'Gilligan',
                    recording =&gt; 'http://www.televisiontunes.com/'
                              .     'themesongs/Gilligans%20Island.mp3' },
             7 =&gt; { name =&gt; 'Potsie',
                    recording =&gt; 'http://www.televisiontunes.com/'
                              .     'themesongs/Happy%20Days%20-%20Season%202.mp3' },
           );

get '/menu' =&gt; sub {
    my $self = shift;
</code></pre>

<p>This should looks mostly familiar so far. Now create <code>$msg</code> which
holds all of the text you want Twilio to "Say" to the caller:</p>

<pre><code>    my $msg = join '. ',
      map { "Press $_ for $list{$_}-&gt;{name}" }
        sort keys %list;
</code></pre>

<p>It's time to build the TwiML document, and this could use some error handling
in case the caller doesn't press a key. Finally, print everything via
Mojolicious's <code>render()</code> method:</p>

<pre><code>    my $tw   = WWW::Twilio::TwiML-&gt;new();
    my $resp = $tw-&gt;Response;
    $resp-&gt;Gather({action    =&gt; $self-&gt;url_for('/menu_handler'),
                   method    =&gt; 'GET',
                   numDigits =&gt; 1})
         -&gt;Say({voice =&gt; 'woman'}, $msg);

    $resp-&gt;Say("You need to make a choice or hang up.");
    $resp-&gt;Redirect("/menu");

    $self-&gt;render(format =&gt; 'xml',
                  text   =&gt; $tw-&gt;to_string);
};
</code></pre>

<p>Remember to start Mojolicious's event loop; this code should always go at the
end of your application, as it never returns:</p>

<pre><code>app-&gt;start;
</code></pre>

<p>(Source <a href="/pub/2011/12/12/menu_part">here</a>). If declarative-style programming is new to you,
don't fret: under the hood, Mojolicious simply creates a map for itself that
says "when I receive an HTTP <code>GET</code> for '/menu', I should execute this
subroutine". The <code>app-&gt;start</code> routine begins a loop that waits
for said request, then handles it as you've defined (declared) it.</p>

<h2><strong>The menu handler route</strong></h2>

<p>Most of the hard work is done now. As specified in the <code>Gather</code>'s
<code>action</code> attribute above, when the caller presses a key, Twilio will
perform an HTTP <code>GET</code> on <code>/menu_handler</code>. Add one more Mojolicious
route:</p>

<pre><code>get '/menu_handler' =&gt; sub {
    my $self   = shift;
    my $choice = $self-&gt;param('Digits') || 0;

    my $tw     = WWW::Twilio::TwiML-&gt;new();
    my $resp   = $tw-&gt;Response;

    unless( exists $list{$choice} ) {
        $resp-&gt;Say({voice =&gt; 'woman'},
                   "Sorry, that's not a valid option.");

        $resp-&gt;Redirect({method =&gt; 'GET'}, "/menu");

        $self-&gt;render(format =&gt; 'xml',
                      text   =&gt; $tw-&gt;to_string);
        return;
    }
</code></pre>

<p>Twilio always passes a <code>Digits</code> parameter to URLs it fetches as a
result of a <code>Gather</code> action (see <a href="http://www.twilio.com/docs/api/twiml/gather">Twilio's Gather verb
documentation</a>);
<code>Digits</code> contains the digit or digits pressed by the caller. HTTP
<code>GET</code> (and <code>POST</code>) parameters are available to Mojolicious through the
<code>param()</code> method.</p>

<p>The code then checks to see if the option the caller has selected exists. If it
doesn't, it generates a TwiML response to tell Twilio to <code>Say</code> to
the caller "Sorry, that's not a valid option." then sends a redirect back to
the main menu.</p>

<p>It's polite to let the caller know what's going on, so add a status message:</p>

<pre><code>$resp-&gt;Say({voice =&gt; 'woman'},
           "I'll try connecting you now.");
</code></pre>

<p>Remember that all this code does is <em>build</em> the TwiML response object; only
when the complete, stringified TwiML object is sent to Twilio's application
server does the document have any effect on the application flow.</p>

<p>The next step is to look up the caller's choice in the <code>%list</code> hash.
If the caller's selection had a phone number associated with it, create a
<code>Dial</code>, <code>Play</code>, or <code>Say</code> TwiML object,
depending on whether <code>%list</code> specifies a number to call, a URL to an
audio file to fetch and play, or neither (respectively):</p>

<pre><code>    if( $list{$choice}-&gt;{number} ) {
        $resp-&gt;Dial($list{$choice}-&gt;{number});
    }

    elsif( $list{$choice}-&gt;{recording} ) {
        $resp-&gt;Play($list{$choice}-&gt;{recording});
    }

    else {
        $resp-&gt;Say({voice =&gt; 'woman'},
                   "Sorry, that option isn't working.");
        $resp-&gt;Redirect({method =&gt; 'GET'}, "/menu");
    }
</code></pre>

<p>Finally, invoke Mojolicious's <code>render()</code> method to create an XML
<em>Content-type</em> header and send the stringified TwiML object to
<code>stdout</code> (which Twilio's application server will read):</p>

<pre><code>    $self-&gt;render(format =&gt; 'xml',
                  text   =&gt; $tw-&gt;to_string);
};
</code></pre>

<p><a href="/pub/2011/12/12/menu">Here is the full source</a> for your enjoyment. If you've already set
Twilio's Voice URL in uour Sandbox, nothing further needs to be done on
Twilio's side. Just upload the new application to the web server and start it
(Mojolicious supports a variety of <a href="http://mojolicio.us/perldoc/Mojolicious/Guides/Cookbook#DEPLOYMENT">deployment
options</a>
including Morbo, CGI, FastCGI, or Plack).</p>

<p>You've made a simple phone menu here, but you've only learned a few of
<a href="http://www.twilio.com/docs/api/twiml/">Twilio's TwiML verbs</a>. With
<a href="http://search.cpan.org/perldoc?WWW::Twilio::API">WWW::Twilio::API</a>,
<a href="http://search.cpan.org/perldoc?WWW::Twilio::TwiML">WWW::Twilio::TwiML</a>, and
<a href="http://mojolicio.us">Mojolicious</a> you can also create conference rooms, make
voice recordings, send and receive SMS messages, reject calls from unwanted
numbers, and do other useful actions in just a few lines of code.</p>
]]>
        
    </content>
</entry>

<entry>
    <title>Automating Telephony with Perl and Twilio</title>
    <link rel="alternate" type="text/html" href="http://www.perl.com/pub/2011/09/automating-telephony-with-perl-and-twilio.html" />
    <id>tag:www.perl.com,2011:/pub//2.1972</id>

    <published>2011-09-21T13:00:01Z</published>
    <updated>2011-09-20T23:36:30Z</updated>

    <summary>Perl can make your phone ring. Scott Wiersdorf demonstrates how to use Twilio&apos;s API to make and receive phone calls and to automate SMS, all from Perl.</summary>
    <author>
        <name>Scott Wiersdorf</name>
        <uri>http://perlcode.org/</uri>
    </author>
    
    <category term="apis" label="APIs" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="telephony" label="telephony" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.perl.com/pub/">
        <![CDATA[<p>Perl can make your phone ring.</p>

<p><a href="http://www.twilio.com/">Twilio</a> allows developers to write applications that
can make and receive voice calls or SMS messages (though Twilio can do many
other interesting telephony things).  Twilio&#8217;s RESTful API, text-to-speech
synthesizer, speech transcription services, and Javascript client make it easy
to knock out a conference call application, an in-browser customer service
voice application, a weather-by-SMS application, reminder by
phone&mdash;anything, really&mdash;in minutes. This article shows how to make a
couple of small applications, one to help you pronounce words correctly and the
other to transcribe awkward condiment phone survey answers.</p>

<h2><strong>Twilio Setup</strong></h2>

<p>First, head over to <a href="http://www.twilio.com/">Twilio.com</a> and click the
&#8220;Try Twilio Free&#8221; link. While inbound calls cost US $0.01 per minute
and outbound calls cost US $0.02 per minute, Twilio has historically
given new users a generous account balance to start with for free
(currently US $30)&#8212;it&#8217;s plenty of credit to kick the tires and take it
for a spin.</p>

<p>Go ahead and register (I&#8217;ll wait here). When you&#8217;ve finished, you&#8217;ll
have an account SID (beginning with &#8220;AC&#8221;) and an auth token, available
from your Twilio Dashboard. These are your Twilio API username and
password; you&#8217;ll need them for any API application you write.</p>

<h2><strong>Twilio Basics</strong></h2>

<p>The Twilio website is full of well-organized documentation and sample
applications. I recommend starting with &#8220;How It Works&#8221; (one of the
main navigation links on the home page). Browse the documentation
under &#8220;Docs&#8221; as well.</p>

<p>H. H. Munroe said, &#8220;A little inaccuracy sometimes saves tons of
explanation.&#8221; Keeping that in mind, inbound calls (calls to a Twilio
number) work like this:</p>

<p><img src="http://www.perl.com/pub/2011/09/20/images/twilio-inbound.png"><br
/><em>Inbound calls to a Twilio number</em></p>

<p>1) the user calls &#8220;555-867-5309&#8221; on their phone</p>

<p>2) Twilio accepts the call, then makes an HTTP POST to
   http://example.com/jenny.xml</p>

<p>3) example.com responds with a &#8220;TwiML&#8221; document (TwiML is a simple XML
language that describes how Twilio will interact with callers):</p>

<pre><code>&lt;?xml version="1.0" encoding="UTF-8" ?&gt;
&lt;Response&gt;
  &lt;Say voice="woman"&gt;This is Jenny!&lt;/Say&gt;
&lt;/Response&gt;
</code></pre>

<p>4) Twilio&#8217;s TwiML parser and text-to-speech synthesizer read this
   document and then says to the user (in a voice from the uncanny
   valley), &#8220;This is Jenny!&#8221;</p>

<p>When you setup a sandbox number, you tell Twilio to map a URL to that
number. Twilio will GET/POST to that URL when receiving calls.</p>

<p>Outbound calls (calls from a Twilio number) work like this:</p>

<p><img src="http://www.perl.com/pub/2011/09/20/images/twilio-outbound.png"><br
/><em>Outbound calls from a Twilio number</em></p>

<p>1) An application makes an HTTP POST to Twilio&#8217;s &#8220;Calls&#8221; API with the
   parameters:</p>

<pre><code>From=+15558675309
To=+19991234567
Url=http://example.com/jenny.xml
</code></pre>

<p>2) Twilio places the call and waits for an answer</p>

<p>3) Once the user answers, Twilio retrieves the URL specified in the
   POST (which should return a TwiML document)</p>

<p>4) Twilio parses the TwiML document and passes it to the
   text-to-speech synthesizer</p>

<p>5) The synthesizer says to the user &#8220;This is Jenny!&#8221;</p>

<p>Twilio can also record voice input, transcribe it, send and receive
SMS messages, make conference calls, and a few other useful things,
all using the same familiar RESTful API and TwiML.</p>

<h2><strong>Twilio, meet Perl</strong></h2>

<p>CPAN makes writing Twilio applications easy, thanks to
<a href="http://search.cpan.org/perldoc?WWW::Twilio::API">WWW::Twilio::API</a>. My
(current) favorite way to install CPAN modules comes from the Mojolicious
project:</p>

<pre><code>curl -L cpanmin.us | perl - WWW::Twilio::API
</code></pre>

<p>cpanmin.us returns a Perl program which handles all of the build dependencies
for you. If you&#8217;re leery of running code from a website directly on the command
line, install <a href="http://search.cpan.org/perldoc?App::cpanminus">App::cpanminus</a>
and use its <code>cpanm</code> program instead.</p>

<p>If you&#8217;re like me and don&#8217;t want to mess up your clean development
environment, tell cpanmin.us or <code>cpanm</code> to install things into a
temporary location:</p>

<pre><code>$ mkdir ~/perl-test
$ export PERL5LIB=~/perl-test/lib/perl5
$ curl -L cpanmin.us | perl - --local-lib=~/perl-test WWW::Twilio::API
# or
$ cpanm --local-lib=~/perl-test WWW::Twilio::API
</code></pre>

<p>See <a href="http://www.cpan.org/modules/INSTALL.html">How to install CPAN
modules</a> for more
information and options.</p>

<h2><strong>Getting all the necessary Twilio information</strong></h2>

<p>After you install <a
href="http://search.cpan.org/perldoc?WWW::Twilio::API">WWW::Twilio::API</a>,
but before you make your first call, you need several pieces of information
from your Twilio Dashboard:</p>

<ul>
<li><p>AccountSid: this is a long string begining with &#8220;AC&#8221;</p></li>
<li><p>AuthToken: another long hex string, next to the AccountSid; you may
have to click a lock icon to reveal it</p></li>
<li><p>Sandbox number: found on the bottom half of the Dashboard page under
&#8220;Sandbox App&#8221;</p></li>
</ul>

<p>That&#8217;s all! Now you&#8217;re ready to go.</p>

<h2><strong>Your first phone call</strong></h2>

<p>Fire up your favorite editor:</p>

<pre><code>#!/usr/bin/env perl

use strict;
use warnings;
use WWW::Twilio::API;

my $twilio = WWW::Twilio::API-&gt;( AccountSid  =&gt; 'ACxxxxxxxxx',
                                 AuthToken   =&gt; 'xxxxxxxxxxx',
                                 API_VERSION =&gt; '2010-04-01' );

## A hollow voice says 'plugh'
my $response = $twilio-&gt;POST( 'Calls',
                              To   =&gt; '+15556667777', ## maybe your cell phone
                              From =&gt; '+12223334444', ## your Twilio sandbox
                              Url  =&gt; 'http://twimlets.com/message?'
                                    . 'Message%5B0%5D=plugh' );

print STDERR $response-&gt;{content};
</code></pre>

<p>That&#8217;s the entire application. Run it, and if all went well, you
should see a long XML string returned which resembles:</p>

<pre><code>&lt;?xml version="1.0"?&gt;
&lt;TwilioResponse&gt;
  &lt;Call&gt;
    &lt;To&gt;+15556667777&lt;/To&gt;
    &lt;From&gt;+12223334444&lt;/From&gt;
    &lt;Status&gt;queued&lt;/Status&gt;
    &lt;Direction&gt;outbound-api&lt;/Direction&gt;
  &lt;/Call&gt;
&lt;/TwilioResponse&gt;
</code></pre>

<p>&#8230; and then your phone should ring. I&#8217;ve always wondered how to
pronounce &#8220;plugh&#8221;&mdash;now I know.</p>

<h2><strong>What could possibly go wrong?</strong></h2>

<p>Early on in Twilio development, you&#8217;re likely to experience a few
little gotchas. For example, you might get this message:</p>

<pre><code>LWP will support https URLs if the LWP::Protocol::https module
is installed.
</code></pre>

<p>That&#8217;s LWP telling you to install
<a href="http://search.cpan.org/perldoc?LWP::Protocol::https">LWP::Protocol::https</a>. (It
will also install or update a few other modules, including
<a href="http://search.cpan.org/perldoc?Net::SSLeay">Net::SSLeay</a>).</p>

<p>If you see XML after running the script, your development environment
is probably fine. You might instead see:</p>

<pre><code>&lt;TwilioResponse&gt;
  &lt;RestException&gt;
    &lt;Status&gt;401&lt;/Status&gt;
    &lt;Message&gt;Authenticate&lt;/Message&gt;
    &lt;Code&gt;20003&lt;/Code&gt;
    &lt;MoreInfo&gt;http://www.twilio.com/docs/errors/20003&lt;/MoreInfo&gt;
  &lt;/RestException&gt;
&lt;/TwilioResponse&gt;
</code></pre>

<p>Notice the &#8220;<Status>401</Status>&#8221;? If you&#8217;re familiar with <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html">HTTP
status codes</a>,
you might remember that 401 means &#8220;Unauthorized&#8221;. You either didn&#8217;t
present any authorization information, or it was incorrect. In this
case, it usually means the AccountSid or AuthToken are incorrect. Log
into Twilio.com, go to the Dashboard and make sure your AccountSid and
AuthToken are correct.</p>

<h2><strong>What else can we do?</strong></h2>

<p>Everything depends on what you put in for the Url parameter. You can
browse some of the free applications at <a href="http://labs.twilio.com/twimlets/">Twilio
Labs</a>, though most of those are for
inbound calls.</p>

<p>Here&#8217;s a silly example of using the voicemail Twimlet to conduct a
brief phone survey and have the callee&#8217;s response transcribed and
emailed. Start by changing the Url line in the POST:</p>

<pre><code>my $email    = 'you@example.com';  ## your email
my $msg      = 'Please+tell+us+what+you+think+of+Tabasco+sauce';
my $response = $twilio-&gt;POST( 'Calls',
                              To   =&gt; '+15556667777',
                              From =&gt; '+12223334444',
                              Url  =&gt; "http://twimlets.com/voicemail?"
                                    . "Email=$email&amp;Message=$msg" );
</code></pre>

<p>Note that this Twimlet&#8217;s arguments are case-sensitive. &#8216;Email&#8217; and
&#8216;Message&#8217; are not the same as &#8216;email&#8217; and &#8216;message&#8217;. Make sure you use
the correct case.</p>

<p>Also, be sure to substitute your phone number for the To parameter and
your Twilio Sandbox phone number (also found on your Twilio Dashboard)
for the From parameter. Twilio phone numbers always use the
international calling prefix (e.g., United States numbers use &#8220;+1&#8221;
followed by the three digit area code followed by the seven digit
phone number).</p>

<p>When you run this, you&#8217;ll get a call from Twilio asking you to share
your insights into Tabasco sauce. Please be honest. Once you&#8217;ve given
your opinion, Twilio will then transcribe your message and email it to
the email address you specified.</p>

<h2><strong>I&#8217;m sending out an SMS</strong></h2>

<p>SMS messages are even easier: no TwiML needed. Instead of the Calls
API, use the <em>SMS/Messages</em> API:</p>

<pre><code>my $response = $twilio-&gt;POST( 'SMS/Messages',
                              To   =&gt; '+15556667777',
                              From =&gt; '+12223334444',
                              Body =&gt; 'Rescue me before '
                                   .  'I fall into despair' );
</code></pre>

<p>That&#8217;s all you have to do to send an SMS message using Twilio (though
the 160 character limit applies).</p>

<h2><strong>Conclusion</strong></h2>

<p>Twilio and Perl make a potent pair: so much is possible with so little code.
The next installment will cover writing larger applications with TwiML.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>What&apos;s Wrong with sort and How to Fix It</title>
    <link rel="alternate" type="text/html" href="http://www.perl.com/pub/2011/08/whats-wrong-with-sort-and-how-to-fix-it.html" />
    <id>tag:www.perl.com,2011:/pub//2.1970</id>

    <published>2011-08-31T13:00:01Z</published>
    <updated>2011-09-16T21:18:13Z</updated>

    <summary>In this excerpt from Programming Perl 4e, Tom Christiansen demonstrates that, in a Unicode world, sorting correctly can be trickier than you think.</summary>
    <author>
        <name>Tom Christiansen</name>
        <uri>http://training.perl.com/</uri>
    </author>
    
    <category term="sorting" label="sorting" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="unicode" label="Unicode" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.perl.com/pub/">
        <![CDATA[<p><em>By now, you may have read <a
        href="http://stackoverflow.com/questions/6162484/why-does-modern-perl-avoid-utf-8-by-default/6163129#6163129">Considerations
        on Using Unicode Properly in Modern Perl Applications</a>. Still think
    doing things correctly is easy? Tom Christiansen demonstrates that even
    sorting can be trickier than you think.</em></p>

<p><strong>NOTE</strong>: The following is an excerpt from the draft manuscript
of <em>Programming Perl</em>, 4&#7511;&#688; edition</p>

<p>Calling <code>sort</code> without a comparison function is quite often the
wrong thing to do, even on plain text. That's because if you use a bare sort,
you can get really strange results.  It's not just Perl either: almost all
programming languages work this way, even the shell command. You might be
surprised to  find that with this sort of nonsense sort, ‹B› comes before  ‹a›
not after it, ‹é› comes before ‹&#65348;›, and ‹&#64256;› comes after ‹zz›.
There's no end to such silliness, either; see the default sort tables at the
end of this article to see what I mean.</p>

<p>There are situations when a bare <code>sort</code> is appropriate, but fewer
than you think. One scenario is when every string you're sorting contains
nothing but the 26 lowercase (or uppercase, but not both) Latin letters from
‹a-z›, without any whitespace or punctuation.</p>

<p>Another occasion when a simple, unadorned <code>sort</code> is appropriate
is when you have no other goal but to iterate in an order that is merely
repeatable, even if that order should happen to be completely arbitrary. In
other words, yes, it's garbage, but it's the same garbage this time as it was
last time. That's because the default <code>sort</code> resorts to an
unmediated <code>cmp</code> operator, which has the "predictable garbage"
characteristics I just mentioned.</p>

<p>The last situation is much less frequent than the first two. It requires
that the things you're sorting be special&#8208;purpose, dedicated binary keys
whose bit sequences have with excruciating care been arranged to sort in some
prescribed fashion.  This is also the strategy for any reasonable use of the
<code>cmp</code> operator.</p>

<h2><strong>So what's wrong with <code>sort</code> anyway?</strong></h2>

<p>I know, I know.  I can hear everyone saying, "But it's called
<code>sort</code>, so how could that ever be wrong?"  Sure it's called
<code>sort</code>, but you still have to know how to use it to get useful
results out. <strong><em>Probably the most surprising thing about <code>sort</code>
        is that it does not by default do an alphabetic, an alphanumeric, or a
        numeric sort.</em></strong>  What it actually does is something else
altogether, and that something else is of surprisingly limited usefulness.</p>

<p>Imagine you have an array of records.  It does you virtually no good to
write:</p>

<pre><code>@sorted_recs = sort @recs;</code></pre>

<p>Because Perl's <code>cmp</code> operator does only a bit comparison not an
alphabetic one, it does nearly as little good to write your record sort this
way:</p>

<pre><code>@srecs = sort {
    $b-&gt;{AGE}      &lt;=&gt;  $b-&gt;{AGE}
                   ||
    $a-&gt;{SURNAME}  cmp  $b-&gt;{SURNAME}
} @recs;</code></pre>

<p>The problem is that that <code>cmp</code> for the record's
<code>SURNAME</code> field is <em>not</em> an alphabetic comparison. It's
merely a code point comparison.  That means it works like C's
<code>strcmp</code> function or Java's <code>String.compareTo</code> method.
Although commonly referred to as a "lexicographic" comparison, this is a gross
misnomer: it's about as far away from the way <em>real</em> lexicographers sort
dictionary entries as you can get without flipping a coin.</p>

<p>Fortunately, you don't have to come up with your own algorithm for
dictionary sorting, because Perl provides a standard class to do this for you:
<a href="http://search.cpan.org/perldoc?Unicode::Collate">Unicode::Collate</a>.
Don't let the name throw you, because while it was first invented for Unicode,
it works great on regular ASCII text, too, and does a better job at making
lexicographers happy than a plain old <code>sort</code> ever manages.</p>

<p>If you have code that purports to sort text that looks like this:</p>

<pre><code>@sorted_lines = sort @lines;</code></pre>

<p>Then all you have to get a dictionary sort is write instead:</p>

<pre><code>use Unicode::Collate;
@sorted_lines = Unicode::Collate::-&gt;new-&gt;sort(@lines);</code></pre>

<p>For structured records, like those with ages and surnames in them, you have
to be a bit fancier.  One way to fix it would be to use the class's own
<code>cmp</code> operator instead of the built&#8208;in one.</p>

<pre><code>use Unicode::Collate;
my $collator = Unicode::Collate::-&gt;new();
@srecs = sort {
    $b-&gt;{AGE}  &lt;=&gt;  $b-&gt;{AGE}
          ||
    $collator-&gt;cmp( $a-&gt;{SURNAME}, $b-&gt;{SURNAME} )
} @recs;</code></pre>

<p>However, that makes a fairly expensive method call for every possible
comparison. Because Perl's adaptive merge sort algorithm usually runs in
<em>O(n</em> · log <em>n)</em> time given <em>n</em> items, and because each
comparison requires two different computed keys, that can be a lot of duplicate
effort. Our sorting class therefore provide a convenient
<code>getSortKey</code> method that calculates a special binary key which you
can cache and later pass to the normal <code>cmp</code> operator on your own.
This trick lets you use <code>cmp</code> yet get a truly alphabetic sort out of
it for a change.</p>

<p>Here is a simple but sufficient example of how to do that:</p>

<pre><code>use Unicode::Collate;
my $collator = Unicode::Collate::-&gt;new();

# first calculate the magic sort key for each text field, and cache it
for my $rec (@recs) {
    $rec-&gt;{SURNAME_key} = $collator-&gt;getSortKey( $rec-&gt;{SURNAME} );
} 

# now sort the records as before, but for the surname field,
# use the cached sort key instead
@srecs = sort {
    $b-&gt;{AGE}          &lt;=&gt;  $b-&gt;{AGE}
                      ||
    $a-&gt;{SURNAME_key}  cmp  $b-&gt;{SURNAME_key}
} @recs;</code></pre>

<p>That's what I meant about very carefully preparing a mediated sort key that
contains the precomputed binary key.</p>

<h3><strong>English Card Catalogue Sorts</strong></h3>

<p>The simple code just demonstrated assumes you want to sort names the same
way you do regular text.  That isn't a good assumption, however.  Many
countries, languages, institutions, and sometimes even librarians have their
own notions about how a card catalogue or a phonebook ought to be sorted.</p>

<p>For example, in the English language, surnames with Scottish patronymics starting with ‹Mc› or ‹Mac›,  like <em>MacKinley</em> and <em>McKinley</em>, not only count as completely  identical synonyms for sorting purposes, they go before any other surname that begins with ‹M›, and so precede surnames like <em>Mables</em> or <em>Machado</em>.</p>

<p>Yes, really.</p>

<p>That means that the following names are sorted correctly -- for English:</p>

<pre><code>Lewis, C.S.
McKinley, Bill
MacKinley, Ron
Mables, Martha
Machado, José
Macon, Bacon</code></pre>

<p>Yes, it's true. Check out your local large English&#8208;language bookseller
or library -- presuming you can find one.  If you do, best make sure to blow the
dust off first.</p>

<h3><strong>Sorting Spanish Names</strong></h3>

<p>It's a good thing those names follow English rules for sorting names. If
this were Spanish, we would have to deal with double&#8208;barrelled surnames,
where the patronym sorts before the matronym, which in turn sorts before any
given names. That means that if Señor Machado's full name were, like the
poet's, <em>Antonio Cipriano José María y Francisco de Santa Ana Machado y
Ruiz</em>, then you would have to sort him with the other <em>Machados</em> but
then consider <em>Ruiz</em> before <em>Antonio</em> if there were any other
<em>Machados</em>.  Similarly, the poet <em>Federico del Sagrado Corazón de
Jesús García Lorca</em> sorts before the writer <em>Gabriel José de la
Concordia García Márquez</em>.</p>

<p>On the other hand, if your records are not full multifield hashes but only
simple text that don't happen to be surnames, your task is a lot simpler, since
now all you have to is get the <code>cmp</code> operator to behave sensibly.
That you can do easily enough this way:</p>

<pre><code>use Unicode::Collate;
@sorted_text = Unicode::Collate::-&gt;new-&gt;sort(@text);</code></pre>

<h3><strong>Sorting Text, Not Binary</strong></h3>

<p>Imagine you had this list of German&#8208;language authors:</p>

<pre><code>@germans = qw{
    Böll
    Born
    Böhme
    Bodmer
    Brandis
    Böttcher
    Borchert
    Bobrowski
};</code></pre>

<p>If you just sorted them with an unmediated <code>sort </code>operator, you
would get this utter nonsense:</p>

<pre><code>Bobrowski
Bodmer
Borchert
Born
Brandis
Brant
Böhme
Böll
Böttcher</code></pre>

<p>Or maybe this equally nonsensical answer:</p>

<pre><code>Bobrowski
Bodmer
Borchert
Born
Böll
Brandis
Brant
Böhme
Böttcher</code></pre>

<p>Or even this still completely nonsensical answer:</p>

<pre><code>Bobrowski
Bodmer
Borchert
Born
Böhme
Böll
Brandis
Brant
Böttcher</code></pre>

<p>The crucial point to all that is that <em>it's text not binary</em>, so not
only can you never judge what its bit patterns hold just by eyeballing it, more
importantly, it has special rules to make it sort alphabetically (some might
say sanely), an ordering no naïve code&#8208;point sort will never come even
close to getting right, especially on Unicode.</p>

<p>The correct ordering is:</p>

<pre><code>Bobrowski
Bodmer
Böhme
Böll
Borchert
Born
Böttcher
Brandis
Brant</code></pre>

<p>And that is precisely what</p>

<pre><code>use Unicode::Collate;
@sorted_germans = Unicode::Collate::-&gt;new-&gt;sort(@german_names);</code></pre>

<p>gives you: a correctly sorted list of those Germans' names.</p>

<h3><strong>Sorting German Names</strong></h3>

<p>Hold on, though.</p>

<p><strong>Correct in what language?</strong>  In English, yes, the order given
is now correct.  But considering that these authors wrote in the German
language, it is quite conceivable that  you should be following the rules for
ordering German names <strong> in German</strong>, not in English.  That
produces this ordering:</p>

<pre><code>Bobrowski
Bodmer
Böhme
Böll
Böttcher
Borchert
Born
Brandis
Brant</code></pre>

<p>How come <em>Böttcher</em> now came before <em>Borchert</em>?  Because
<em>Böttcher</em> is supposed to be the same as <em>Boettcher</em>. In a German
phonebook or other German list of German names, things like ‹ö› and ‹oe› are
considered synonyms, which is not at all how it works in English. To get the
German phonebook sort, you merely have to modify your constructor this way:</p>

<pre><code>use Unicode::Collate::Locale;
@sorted_germans = Unicode::Collate::Locale::
                      -&gt;new(locale =&gt; "de_phonebook")
                      -&gt;sort(@german_names);</code></pre>
<p>Isn't this fun?<p>

<p>Be glad you're not sorting names.  Sorting names is hard.</p>

<h3><strong>Default Sort Tables</strong></h3>

<p>Here are most of the Latin letters, ordered using the default
<code>sort</code>:</p>

<blockquote><pre>
&#65; &#66; &#67; &#68; &#69; &#70; &#71; &#72; &#73; &#74; &#75; &#76; &#77; &#78; &#79; &#80; &#81; &#82; &#83; &#84; &#85; &#86; &#87; &#88; &#89; &#90; &#97; &#98; &#99; &#100; &#101; &#102; &#103; &#104; &#105; &#106; 
&#107; &#108; &#109; &#110; &#111; &#112; &#113; &#114; &#115; &#116; &#117; &#118; &#119; &#120; &#121; &#122; &#170; &#186; &#192; &#193; &#194; &#195; &#196; &#197; &#198; &#199; &#200; &#201; &#202; &#203; &#204; &#205; &#206; &#207; &#208; &#209; 
&#210; &#211; &#212; &#213; &#214; &#216; &#217; &#218; &#219; &#220; &#221; &#222; &#223; &#224; &#225; &#226; &#227; &#228; &#229; &#230; &#231; &#232; &#233; &#234; &#235; &#236; &#237; &#238; &#239; &#240; &#241; &#242; &#243; &#244; &#245; &#246; 
&#248; &#249; &#250; &#251; &#252; &#253; &#254; &#255; &#256; &#257; &#258; &#259; &#260; &#261; &#262; &#263; &#264; &#265; &#266; &#267; &#268; &#269; &#270; &#271; &#272; &#273; &#274; &#275; &#276; &#277; &#278; &#279; &#280; &#281; &#282; &#283; 
&#284; &#285; &#286; &#287; &#288; &#289; &#290; &#291; &#292; &#293; &#294; &#295; &#296; &#297; &#298; &#299; &#300; &#301; &#302; &#303; &#304; &#305; &#306; &#307; &#308; &#309; &#310; &#311; &#312; &#313; &#314; &#315; &#316; &#317; &#318; &#319; 
&#320; &#321; &#322; &#323; &#324; &#325; &#326; &#327; &#328; &#330; &#331; &#332; &#333; &#334; &#335; &#336; &#337; &#338; &#339; &#340; &#341; &#342; &#343; &#344; &#345; &#346; &#347; &#348; &#349; &#350; &#351; &#352; &#353; &#354; &#355; &#356; 
&#357; &#358; &#359; &#360; &#361; &#362; &#363; &#364; &#365; &#366; &#367; &#368; &#369; &#370; &#371; &#372; &#373; &#374; &#375; &#376; &#377; &#378; &#379; &#380; &#381; &#382; &#383; &#384; &#385; &#386; &#387; &#391; &#392; &#393; &#394; &#395; 
&#396; &#397; &#398; &#399; &#400; &#401; &#402; &#403; &#404; &#405; &#406; &#407; &#408; &#409; &#410; &#411; &#412; &#413; &#414; &#420; &#421; &#422; &#427; &#428; &#429; &#430; &#431; &#432; &#433; &#434; &#435; &#436; &#437; &#438; &#439; &#440; 
&#441; &#442; &#446; &#447; &#452; &#453; &#454; &#455; &#456; &#457; &#458; &#459; &#460; &#461; &#462; &#463; &#464; &#465; &#466; &#467; &#468; &#469; &#470; &#471; &#472; &#473; &#474; &#475; &#476; &#477; &#478; &#479; &#480; &#481; &#482; &#483; 
&#484; &#485; &#486; &#487; &#488; &#489; &#490; &#491; &#492; &#493; &#494; &#495; &#496; &#497; &#498; &#499; &#500; &#501; &#503; &#504; &#505; &#506; &#507; &#508; &#509; &#510; &#511; &#512; &#513; &#514; &#515; &#516; &#517; &#518; &#519; &#520; 
&#521; &#522; &#523; &#524; &#525; &#526; &#527; &#528; &#529; &#530; &#531; &#532; &#533; &#534; &#535; &#536; &#537; &#538; &#539; &#540; &#541; &#542; &#543; &#544; &#545; &#548; &#549; &#550; &#551; &#552; &#553; &#554; &#555; &#556; &#557; &#558; 
&#559; &#560; &#561; &#562; &#563; &#564; &#565; &#566; &#567; &#570; &#571; &#572; &#573; &#574; &#592; &#593; &#594; &#595; &#597; &#598; &#599; &#600; &#601; &#602; &#603; &#604; &#605; &#606; &#607; &#608; &#609; &#610; &#611; &#612; &#613; &#614; 
&#615; &#616; &#617; &#618; &#619; &#620; &#621; &#622; &#623; &#624; &#625; &#626; &#627; &#628; &#630; &#633; &#634; &#635; &#636; &#637; &#638; &#639; &#640; &#641; &#642; &#643; &#644; &#645; &#646; &#647; &#648; &#649; &#650; &#651; &#652; &#653; 
&#654; &#655; &#656; &#657; &#658; &#659; &#665; &#666; &#667; &#668; &#669; &#670; &#671; &#672; &#675; &#676; &#677; &#678; &#679; &#680; &#681; &#682; &#683; &#737; &#738; &#739; &#7424; &#7425; &#7426; &#7427; &#7428; &#7429; &#7430; &#7431; &#7432; &#7433; 
&#7434; &#7435; &#7436; &#7437; &#7438; &#7439; &#7441; &#7443; &#7444; &#7448; &#7449; &#7450; &#7451; &#7452; &#7453; &#7454; &#7455; &#7456; &#7457; &#7458; &#7459; &#7468; &#7469; &#7470; &#7471; &#7472; &#7473; &#7474; &#7475; &#7476; &#7477; &#7478; &#7479; &#7480; &#7481; &#7482; 
&#7483; &#7484; &#7486; &#7487; &#7488; &#7489; &#7490; &#7491; &#7492; &#7493; &#7494; &#7495; &#7496; &#7497; &#7498; &#7499; &#7500; &#7501; &#7502; &#7503; &#7504; &#7505; &#7506; &#7510; &#7511; &#7512; &#7513; &#7514; &#7515; &#7522; &#7523; &#7524; &#7525; &#7531; &#7532; &#7533; 
&#7534; &#7535; &#7536; &#7537; &#7538; &#7539; &#7540; &#7541; &#7542; &#7680; &#7681; &#7682; &#7683; &#7684; &#7685; &#7686; &#7687; &#7688; &#7689; &#7690; &#7691; &#7692; &#7693; &#7694; &#7695; &#7696; &#7697; &#7698; &#7699; &#7700; &#7701; &#7702; &#7703; &#7704; &#7705; &#7706; 
&#7707; &#7708; &#7709; &#7710; &#7711; &#7712; &#7713; &#7714; &#7715; &#7716; &#7717; &#7718; &#7719; &#7720; &#7721; &#7722; &#7723; &#7724; &#7725; &#7726; &#7727; &#7728; &#7729; &#7730; &#7731; &#7732; &#7733; &#7734; &#7735; &#7736; &#7737; &#7738; &#7739; &#7740; &#7741; &#7742; 
&#7743; &#7744; &#7745; &#7746; &#7747; &#7748; &#7749; &#7750; &#7751; &#7752; &#7753; &#7754; &#7755; &#7756; &#7757; &#7758; &#7759; &#7760; &#7761; &#7762; &#7763; &#7764; &#7765; &#7766; &#7767; &#7768; &#7769; &#7770; &#7771; &#7772; &#7773; &#7774; &#7775; &#7776; &#7777; &#7778; 
&#7779; &#7780; &#7781; &#7782; &#7783; &#7784; &#7785; &#7786; &#7787; &#7788; &#7789; &#7790; &#7791; &#7792; &#7793; &#7794; &#7795; &#7796; &#7797; &#7798; &#7799; &#7800; &#7801; &#7802; &#7803; &#7804; &#7805; &#7806; &#7807; &#7808; &#7809; &#7810; &#7811; &#7812; &#7813; &#7814; 
&#7815; &#7816; &#7817; &#7818; &#7819; &#7820; &#7821; &#7822; &#7823; &#7824; &#7825; &#7826; &#7827; &#7828; &#7829; &#7830; &#7831; &#7832; &#7833; &#7834; &#7835; &#7838; &#7839; &#7840; &#7841; &#7842; &#7843; &#7844; &#7845; &#7846; &#7847; &#7848; &#7849; &#7850; &#7851; &#7852; 
&#7853; &#7854; &#7855; &#7856; &#7857; &#7858; &#7859; &#7860; &#7861; &#7862; &#7863; &#7864; &#7865; &#7866; &#7867; &#7868; &#7869; &#7870; &#7871; &#7872; &#7873; &#7874; &#7875; &#7876; &#7877; &#7878; &#7879; &#7880; &#7881; &#7882; &#7883; &#7884; &#7885; &#7886; &#7887; &#7888; 
&#7889; &#7890; &#7891; &#7892; &#7893; &#7894; &#7895; &#7896; &#7897; &#7898; &#7899; &#7900; &#7901; &#7902; &#7903; &#7904; &#7905; &#7906; &#7907; &#7908; &#7909; &#7910; &#7911; &#7912; &#7913; &#7914; &#7915; &#7916; &#7917; &#7918; &#7919; &#7920; &#7921; &#7922; &#7923; &#7924; 
&#7925; &#7926; &#7927; &#7928; &#7929; &#8490; &#8491; &#8498; &#8526; &#8544; &#8545; &#8546; &#8547; &#8548; &#8549; &#8550; &#8551; &#8552; &#8553; &#8554; &#8555; &#8556; &#8557; &#8558; &#8559; &#8560; &#8561; &#8562; &#8563; &#8564; 
&#8565; &#8566; &#8567; &#8568; &#8569; &#8570; &#8571; &#8572; &#8573; &#8574; &#8575; &#64256; &#64257; &#64258; &#64259; &#64260; &#64261; &#64262; &#65313; &#65314; &#65315; &#65316; &#65317; &#65318; &#65319; &#65320; &#65321;
&#65322; &#65323; &#65324; &#65325; &#65326; &#65327; &#65328; &#65329; &#65330; &#65331; &#65332; &#65333; &#65334; &#65335; &#65336; &#65337; &#65338; &#65345; &#65346; &#65347; &#65348; &#65349; &#65350; &#65351; &#65352; &#65353;
&#65354; &#65355; &#65356; &#65357; &#65358; &#65359; &#65360; &#65361; &#65362; &#65363; &#65364; &#65365; &#65366; &#65367; &#65368; &#65369; &#65370;</pre></blockquote>

<p>As you can see, those letters are scattered all over the place. Sure, it's
not completely random, but it's not useful either, because it is full of
arbitrary placement that makes no alphabetical sense. That's because it is not
an alphabetic sort at all. However, with the special kind of sort I've just
shown you above, the ones that call the <code>sort</code> method from the
<code>Unicode::Collate</code> class, you do get an alphabetic sort. Using that
method, the Latin letters I just showed you now come out in alphabetical order,
which is like this:</p>

<blockquote><pre>&#97; &#65345; &#65; &#65313; &#170; &#7491; &#7468; &#225; &#193; &#224; &#192; &#259; &#258; &#7855; &#7854; &#7857; &#7856; &#7861; &#7860; &#7859; &#7858; &#226; &#194; &#7845; &#7844; &#7847; &#7846; &#7851; &#7850; &#7849; &#7848; &#462; &#461; &#229; &#197; 
&#8491; &#507; &#506; &#228; &#196; &#479; &#478; &#227; &#195; &#551; &#550; &#481; &#480; &#261; &#260; &#257; &#256; &#7843; &#7842; &#513; &#512; &#515; &#514; &#7841; &#7840; &#7863; &#7862; &#7853; &#7852; &#7681; &#7680; &#230; &#198; &#7469; &#509; &#508; 
&#483; &#482; &#7834; &#7424; &#570; &#7425; &#7426; &#7494; &#592; &#7492; &#593; &#7493; &#594; &#98; &#65346; &#66; &#65314; &#7495; &#7470; &#7683; &#7682; &#7685; &#7684; &#7687; &#7686; &#665; &#384; &#7471; &#7427; &#7532; &#595; &#385; &#387; &#386; &#99; 
&#65347; &#8573; &#67; &#65315; &#8557; &#263; &#262; &#265; &#264; &#269; &#268; &#267; &#266; &#231; &#199; &#7689; &#7688; &#7428; &#572; &#571; &#392; &#391; &#597; &#100; &#65348; &#8574; &#68; &#65316; &#8558; &#7496; &#7472; &#271; &#270; &#7691; 
&#7690; &#7697; &#7696; &#7693; &#7692; &#7699; &#7698; &#7695; &#7694; &#273; &#272; &#240; &#208; &#499; &#675; &#498; &#497; &#454; &#453; &#452; &#677; &#676; &#7429; &#7430; &#7533; &#598; &#393; &#599; &#394; &#396; &#395; &#545; &#7839; &#101; &#65349; &#69; 
&#65317; &#7497; &#7473; &#233; &#201; &#232; &#200; &#277; &#276; &#234; &#202; &#7871; &#7870; &#7873; &#7872; &#7877; &#7876; &#7875; &#7874; &#283; &#282; &#235; &#203; &#7869; &#7868; &#279; &#278; &#553; &#552; &#7709; &#7708; &#281; &#280; &#275; &#274; &#7703; 
&#7702; &#7701; &#7700; &#7867; &#7866; &#517; &#516; &#519; &#518; &#7865; &#7864; &#7879; &#7878; &#7705; &#7704; &#7707; &#7706; &#7431; &#477; &#398; &#7474; &#601; &#399; &#7498; &#603; &#400; &#7499; &#600; &#602; &#604; &#7432; &#7500; &#605; &#606; &#666; &#612; 
&#102; &#65350; &#70; &#65318; &#7711; &#7710; &#64256; &#64259; &#64260; &#64257; &#64258; &#681; &#7534; &#402; &#401; &#8526; &#8498; &#103; &#65351; &#71; &#65319; &#7501; &#7475; &#501; &#500; &#287; &#286; &#285; &#284; &#487; &#486; &#289; &#288; &#291; 
&#290; &#7713; &#7712; &#609; &#610; &#485; &#484; &#608; &#403; &#667; &#611; &#404; &#104; &#65352; &#72; &#65320; &#7476; &#293; &#292; &#543; &#542; &#7719; &#7718; &#7715; &#7714; &#7721; &#7720; &#7717; &#7716; &#7723; &#7722; &#7830; &#295; &#294; &#668; 
&#405; &#614; &#615; &#105; &#65353; &#8560; &#73; &#65321; &#8544; &#7522; &#7477; &#237; &#205; &#236; &#204; &#301; &#300; &#238; &#206; &#464; &#463; &#239; &#207; &#7727; &#7726; &#297; &#296; &#304; &#303; &#302; &#299; &#298; &#7881; &#7880; &#521; 
&#520; &#523; &#522; &#7883; &#7882; &#7725; &#7724; &#8561; &#8545; &#8562; &#8546; &#307; &#306; &#8563; &#8547; &#8568; &#8552; &#305; &#618; &#7433; &#7502; &#616; &#407; &#617; &#406; &#106; &#65354; &#74; &#65322; &#7478; &#309; &#308; &#496; &#567; &#7434; 
&#669; &#607; &#644; &#107; &#65355; &#75; &#8490; &#65323; &#7503; &#7479; &#7729; &#7728; &#489; &#488; &#311; &#310; &#7731; &#7730; &#7733; &#7732; &#7435; &#409; &#408; &#670; &#108; &#65356; &#8572; &#76; &#65324; &#8556; &#737; &#7480; &#314; &#313; 
&#318; &#317; &#316; &#315; &#7735; &#7734; &#7737; &#7736; &#7741; &#7740; &#7739; &#7738; &#322; &#321; &#320; &#319; &#457; &#456; &#455; &#682; &#683; &#671; &#7436; &#410; &#573; &#619; &#620; &#621; &#564; &#622; &#411; &#654; &#109; &#65357; &#8575; &#77; 
&#65325; &#8559; &#7504; &#7481; &#7743; &#7742; &#7745; &#7744; &#7747; &#7746; &#7437; &#7535; &#625; &#110; &#65358; &#78; &#65326; &#7482; &#324; &#323; &#505; &#504; &#328; &#327; &#241; &#209; &#7749; &#7748; &#326; &#325; &#7751; &#7750; &#7755; &#7754; &#7753; 
&#7752; &#460; &#459; &#458; &#628; &#7483; &#7438; &#7536; &#626; &#413; &#414; &#544; &#627; &#565; &#331; &#330; &#7505; &#111; &#65359; &#79; &#65327; &#186; &#7506; &#7484; &#243; &#211; &#242; &#210; &#335; &#334; &#244; &#212; &#7889; &#7888; &#7891; 
&#7890; &#7895; &#7894; &#7893; &#7892; &#466; &#465; &#246; &#214; &#555; &#554; &#337; &#336; &#245; &#213; &#7757; &#7756; &#7759; &#7758; &#557; &#556; &#559; &#558; &#561; &#560; &#248; &#216; &#511; &#510; &#491; &#490; &#493; &#492; &#333; &#332; &#7763; 
&#7762; &#7761; &#7760; &#7887; &#7886; &#525; &#524; &#527; &#526; &#7899; &#7898; &#7901; &#7900; &#7905; &#7904; &#7903; &#7902; &#7907; &#7906; &#7885; &#7884; &#7897; &#7896; &#339; &#338; &#7439; &#7441; &#630; &#7444; &#7443; &#112; &#65360; &#80; &#65328; &#7510; 
&#7486; &#7765; &#7764; &#7767; &#7766; &#7448; &#7537; &#421; &#420; &#113; &#65361; &#81; &#65329; &#672; &#312; &#114; &#65362; &#82; &#65330; &#7523; &#7487; &#341; &#340; &#345; &#344; &#7769; &#7768; &#343; &#342; &#529; &#528; &#531; &#530; &#7771; 
&#7770; &#7773; &#7772; &#7775; &#7774; &#640; &#422; &#7449; &#7538; &#633; &#7450; &#634; &#635; &#636; &#637; &#638; &#7539; &#639; &#641; &#115; &#65363; &#83; &#65331; &#738; &#347; &#346; &#7781; &#7780; &#349; &#348; &#353; &#352; &#7783; &#7782; &#7777; 
&#7776; &#351; &#350; &#7779; &#7778; &#7785; &#7784; &#537; &#536; &#383; &#7835; &#223; &#7838; &#64262; &#64261; &#7540; &#642; &#643; &#645; &#646; &#116; &#65364; &#84; &#65332; &#7511; &#7488; &#357; &#356; &#7831; &#7787; &#7786; &#355; &#354; &#7789; &#7788; 
&#539; &#538; &#7793; &#7792; &#7791; &#7790; &#680; &#446; &#678; &#679; &#7451; &#359; &#358; &#574; &#7541; &#427; &#429; &#428; &#648; &#430; &#566; &#647; &#117; &#65365; &#85; &#65333; &#7512; &#7524; &#7489; &#250; &#218; &#249; &#217; &#365; &#364; 
&#251; &#219; &#468; &#467; &#367; &#366; &#252; &#220; &#472; &#471; &#476; &#475; &#474; &#473; &#470; &#469; &#369; &#368; &#361; &#360; &#7801; &#7800; &#371; &#370; &#363; &#362; &#7803; &#7802; &#7911; &#7910; &#533; &#532; &#535; &#534; &#432; &#431; 
&#7913; &#7912; &#7915; &#7914; &#7919; &#7918; &#7917; &#7916; &#7921; &#7920; &#7909; &#7908; &#7795; &#7794; &#7799; &#7798; &#7797; &#7796; &#7452; &#7453; &#7513; &#7454; &#7531; &#649; &#613; &#623; &#412; &#7514; &#7455; &#624; &#650; &#433; &#118; &#65366; &#8564; &#86; 
&#65334; &#8548; &#7515; &#7525; &#7805; &#7804; &#7807; &#7806; &#8565; &#8549; &#8566; &#8550; &#8567; &#8551; &#7456; &#651; &#434; &#652; &#119; &#65367; &#87; &#65335; &#7490; &#7811; &#7810; &#7809; &#7808; &#373; &#372; &#7832; &#7813; &#7812; &#7815; &#7814; &#7817; 
&#7816; &#7457; &#653; &#120; &#65368; &#8569; &#88; &#65336; &#8553; &#739; &#7821; &#7820; &#7819; &#7818; &#8570; &#8554; &#8571; &#8555; &#121; &#65369; &#89; &#65337; &#253; &#221; &#7923; &#7922; &#375; &#374; &#7833; &#255; &#376; &#7929; &#7928; &#7823; 
&#7822; &#563; &#562; &#7927; &#7926; &#7925; &#7924; &#655; &#436; &#435; &#122; &#65370; &#90; &#65338; &#378; &#377; &#7825; &#7824; &#382; &#381; &#380; &#379; &#7827; &#7826; &#7829; &#7828; &#397; &#7458; &#438; &#437; &#7542; &#549; &#548; &#656; &#657; 
&#658; &#439; &#495; &#494; &#7459; &#441; &#440; &#442; &#659; &#541; &#540; &#254; &#222; &#447; &#503;</pre></blockquote>

<p>Isn't that much nicer?</p>

<h3><strong>Romani Ite Domum</strong></h3>

<p>In case you're wondering what that last row of distinctly un&#8208;Roman Latin letters 
might possibly be, they're called respectively <a href="http://en.wikipedia.org/wiki/Ezh_(letter)"><em>ezh</em></a> &#658;, <a href="http://en.wikipedia.org/wiki/Yogh"><em>yogh</em></a> &#541;, <a href="http://en.wikipedia.org/wiki/Thorn_(letter)"><em>thorn</em></a> þ, and <a href="http://en.wikipedia.org/wiki/Wynn"><em>wynn</em></a> &#447;. They had to go somewhere, so they ended up getting stuck after ‹z›</p>

<p>Some are still used in certain non&#8208;English (but still Latin) alphabets
today, such as Icelandic, and even though you probably won't bump into them in
contemporary English texts, you might see some  if you're reading the original
texts of famous medieval English poems like  <em>Beowulf</em>, <em>Sir Gawain
and the Green Knight</em>, or <em>Brut</em>.</p>

<p>The last of those, <em>Brut</em>, was written by a fellow named
<em>La&#541;amon</em>, a name whose third letter is a yogh. Famous though he
was, I wouldn't suggest changing  your name to ‹La&#541;amon› in his honor, as
I doubt the phone company would be amused.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Using CPAN on Win32 ActivePerl</title>
    <link rel="alternate" type="text/html" href="http://www.perl.com/pub/2011/08/using-cpan-on-win32-activeperl.html" />
    <id>tag:www.perl.com,2011:/pub//2.1968</id>

    <published>2011-08-03T13:00:01Z</published>
    <updated>2011-08-03T17:26:03Z</updated>

    <summary>Christian Walde demonstrates that even ActivePerl users on Windows can use CPAN--out of the box.</summary>
    <author>
        <name>chromatic</name>
        <uri>http://www.modernperlbooks.com/</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://www.perl.com/pub/">
        <![CDATA[<p>or <em>easier than tying your shoelaces</em></p>

<p>Most of you know <a
href="http://www.activestate.com/activeperl">ActivePerl</a>, the commercial
Perl distribution provided to the community for free by <a
href="http://www.activestate.com/">ActiveState</a>. In the beginning,
ActivePerl did not bundle a C compiler. As Windows does not include a compiler,
much of the CPAN was inaccessible to Windows users&mdash;any dependency on an
XS module would fail. ActiveState instead provided a repository of binary PPM
packages so that users could avoid the need to install and configure a C
compiler.</p>

<p>So began a rumor, and so the rumor became lore, that "ActivePerl Does Not Do
CPAN."</p>

<p>As wrong as that preconception had been (and a clever hacker could use MSVC
or MinGW with ActivePerl), that rumor became even more wrong on 26 August 2009,
when ActiveState delivered Perl 5.10.1 with a bundled C compiler. Even though
Windows does not support <em>all</em> POSIX features, using CPAN with
ActivePerl on Windows is almost as nice as using CPAN on a Unix-like system:</p>

<ul>

<li>Download and install <a href="http://www.activestate.com/activeperl/downloads">ActivePerl</a> (5.12.4 and 5.14.1 are available at the time of this writing) with the default options</li>

<li>Open a command line window ( Start &gt; Run &gt; cmd )</li>
<li>Run <code>cpan</code></li>

</ul>

<p>That's it. That's only one extra step over running on Linux. For proof,
here's the output of my first run of the <code>cpan</code> command (edited for
brevity) and an installation of <a
href="http://search.cpan.org/perldoc?local::lib">local::lib</a> and <a
href="http://search.cpan.org/perldoc?App::cpanminus">cpanminus</a> (yes, they
work too):</p>

<pre><code>D:\&gt;cpan

It looks like you don't have a C compiler and make utility installed.  Trying
to install dmake and the MinGW gcc compiler using the Perl Package Manager.
This may take a a few minutes...

Downloading MinGW-5.1.4.1...done
Downloading dmake-4.11.20080107...done
Unpacking MinGW-5.1.4.1...done
Unpacking dmake-4.11.20080107...done
Generating HTML for MinGW-5.1.4.1...done
Generating HTML for dmake-4.11.20080107...done
Updating files in site area...done
1070 files installed

Please use the `dmake` program to run commands from a Makefile!


cpan shell -- CPAN exploration and modules installation (v1.9600)
Enter 'h' for help.

cpan&gt; install local::lib
Fetching with LWP:
...
Running install for module 'local::lib'
Running make for A/AP/APEIRON/local-lib-1.008004.tar.gz
Fetching with LWP:
http://ppm.activestate.com/CPAN/authors/id/A/AP/APEIRON/local-lib-1.008004.tar.gz
Fetching with LWP:
http://ppm.activestate.com/CPAN/authors/id/A/AP/APEIRON/CHECKSUMS
Checksum for C:\Perl14\cpan\sources\authors\id\A\AP\APEIRON\local-lib-1.008004.tar.gz ok
...

  CPAN.pm: Going to build A/AP/APEIRON/local-lib-1.008004.tar.gz


*** Module::AutoInstall version 1.03
*** Checking for Perl dependencies...
*** Since we're running under CPAN, I'll just let it take care
    of the dependency's installation later.
[Core Features]
- ExtUtils::MakeMaker ...loaded. (6.57_05 &gt;= 6.31)
- ExtUtils::Install   ...loaded. (1.56 &gt;= 1.43)
- Module::Build       ...loaded. (0.38 &gt;= 0.36)
- CPAN                ...loaded. (1.9600 &gt;= 1.82)
*** Module::AutoInstall configuration finished.
Checking if your kit is complete...
Looks good
Writing Makefile for local::lib
...
Running make test
All tests successful.
Files=7, Tests=29,  1 wallclock secs ( 0.06 usr +  0.08 sys =  0.14 CPU)
Result: PASS
  APEIRON/local-lib-1.008004.tar.gz
  C:\Perl14\site\bin\dmake.exe test -- OK
Running make install
...

cpan&gt; install App::cpanminus
Running install for module 'App::cpanminus'
Running make for M/MI/MIYAGAWA/App-cpanminus-1.4008.tar.gz
...
Running make test
All tests successful.
Files=1, Tests=1,  0 wallclock secs ( 0.03 usr +  0.03 sys =  0.06 CPU)
Result: PASS
  MIYAGAWA/App-cpanminus-1.4008.tar.gz
  C:\Perl14\site\bin\dmake.exe test -- OK
Running make install
...
cpan&gt; exit
Lockfile removed.

D:\&gt;cpanm
Usage: cpanm [options] Module [...]

Try `cpanm --help` or `man cpanm` for more options.

D:\&gt;</code></pre>

<p>Happy hacking!</p>]]>
        
    </content>
</entry>

<entry>
    <title>New Features of Perl 5.14: unicode_strings</title>
    <link rel="alternate" type="text/html" href="http://www.perl.com/pub/2011/06/new-features-of-perl-514-unicode-strings.html" />
    <id>tag:www.perl.com,2011:/pub//2.1954</id>

    <published>2011-06-08T18:12:39Z</published>
    <updated>2011-06-09T19:13:20Z</updated>

    <summary>Perl 5.14 provides a new feature called unicode_strings to improve Unicode string handling.</summary>
    <author>
        <name>chromatic</name>
        <uri>http://www.modernperlbooks.com/</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://www.perl.com/pub/">
        <![CDATA[<p>Perl 5.14 is now available. While this latest major release of Perl 5
brings with it many bugfixes, updates to the core libraries, and the usual
performance improvements, it also includes a few nice new features.</p>

<p>One such feature is the new <code>unicode_strings</code> feature, enabled with <code>use feature 'unicode_strings';</code> or <code>use feature ':5.14';</code>.  (Perl 5.12 first introduced this feature, though it remained incomplete until the development of 5.14. Fortunately, you can write <code>use feature ':5.12';</code> while running with 5.14 and still get all of the benefits of the improved form in Perl 5.14.)</p>

<p><code>unicode_strings</code> tells the Perl 5 compiler to assume Unicode
semantics for all string operations within the enclosing lexical scope. In
other words, Perl will treat all strings as if they contain Unicode characters
and not merely bytes. This fixes an issue when your code handles text outside
of the strict ASCII range.</p>

<p>For example, what should Perl assume if you read a character with a code
point between 128 and 255? It's obviously not ASCII text. Is it Latin-1? Is it
a raw byte? What should happen?</p>

<p>If you intend it as a Latin-1 character (&Ouml;, for example), then the
regular expression metacharacter <code>\w</code> should match it, because an O
even with a diaresis is still a letter. The Perl 5 documentation refers to this
as "character semantics".</p>

<p>If you intend it as the byte value 214, then <code>\w</code> should
<em>not</em> match it (though why are you using a regular expression against
it?). The Perl 5 documentation refers to this as "byte semantics".</p>

<p>Now assume you have several strings from several places and you don't know
the exact encodings of all of those sources and you want to concatenate two
strings or interpolate them into a third string. What happens?</p>

<p>With <code>unicode_strings</code> in effect, Perl 5 prefers to use character
semantics for all string operations. You can override this lexically with
<code>no feature 'unicode_strings';</code> or <code>use locale;</code>.</p>

<p>For more information, see <a
href="http://perldoc.perl.org/feature.html#the-%27unicode_strings%27-feature">perldoc feature</a> and especially
<a href="http://perldoc.perl.org/perlunicode.html#The-%22Unicode-Bug%22">The
Unicode Bug" in perldoc perlunicode</a>.</p> 
]]>
        

    </content>
</entry>

<entry>
    <title>New Features of Perl 5.14: IO::File on Demand</title>
    <link rel="alternate" type="text/html" href="http://www.perl.com/pub/2011/05/new-features-of-perl-514-iofile-on-demand.html" />
    <id>tag:www.perl.com,2011:/pub//2.1952</id>

    <published>2011-05-24T20:45:15Z</published>
    <updated>2011-05-24T20:46:56Z</updated>

    <summary>Perl 5.14 loads IO::File on demand for autovivified filehandles.</summary>
    <author>
        <name>chromatic</name>
        <uri>http://www.modernperlbooks.com/</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://www.perl.com/pub/">
        <![CDATA[<p>Perl 5.14 is now available. While this latest major release of Perl 5
brings with it many bugfixes, updates to the core libraries, and the usual
performance improvements, it also includes a few nice new features.</p>

<p>One such feature is loading <a
href="http://search.cpan.org/perldoc?IO::File">IO::File</a> on demand.</p>

<p>Autovivification of filehandles (colloquially known as "lexical
filehandles") has been in Perl 5 since the release of Perl 5.6.0:</p>

<pre><code>    open my $fh, &#39;&gt;&#39;, $filename
        or die &quot;Cannot write to &#39;$filename&#39;: $!\n&quot;;</code></pre>

<p>These filehandles behaved something like objects <em>if</em> you loaded
<code>IO::File</code> or <a
href="http://search.cpan.org/perldoc?IO::Handle">IO::Handle</a>, in that
you could call methods on them:</p>

<pre><code>    use IO::File;
    $fh-&gt;autoflush(1);</code></pre>

<p>Even though the Perl 5 core performed the appropriate gyrations to
produce these filehandles associated with the proper class, you had to
remember to <code>use</code> the appropriate module manually.</p>

<p>Perl 5.14 now <code>require</code>s <code>IO::File</code> if necessary
for you. This is a small feature, but it smooths out a confusing wrinkle in
an important feature of modern Perl 5.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>New Features of Perl 5.14: Non-destructive Substitution</title>
    <link rel="alternate" type="text/html" href="http://www.perl.com/pub/2011/05/new-features-of-perl-514-non-destructive-substitution.html" />
    <id>tag:www.perl.com,2011:/pub//2.1950</id>

    <published>2011-05-18T22:08:19Z</published>
    <updated>2011-05-18T22:12:26Z</updated>

    <summary>Perl 5.14 adds non-destructive substitution.</summary>
    <author>
        <name>chromatic</name>
        <uri>http://www.modernperlbooks.com/</uri>
    </author>
    
    <category term="language" label="language" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl5" label="perl 5" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl514" label="perl 5.14" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="syntax" label="syntax" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.perl.com/pub/">
        <![CDATA[<p><a href="http://news.perlfoundation.org/2011/05/perl-514.html">Perl 5.14 is now available</a>. While this latest major release of Perl 5 brings with it many bugfixes, updates to the core libraries, and the usual performance improvements, it also includes a few nice new features.</p>

<p>One such feature is non-destructive substitution:</p>

<pre><code>    use 5.014;

    my $greeting  = &#39;Hello, world!&#39;;

    # be more elite
    say $greeting =~ tr/aeiou/4310V/r;

    # then run away
    say $greeting =~ s/Hello/Goodbye/r;</code></pre>

<p>The new <code>/r</code> modifier to the substitution and transliteration
operators causes Perl to return the modified string, rather than modifying
the original string in place. This replaces the idiomatic but unwieldy:</p>

<pre><code>    my  $greeting  = &#39;Hello, world!&#39;;
    my ($leetgreet = $greeting) =~ tr/aeiou/4310V/;</code></pre>

<p>This feature is even more useful for avoiding two common problems with
substitutions in <code>map</code> expressions:</p>

<pre><code>    my @modified = map { s/foo/BAR/ } @original;</code></pre>

<p>Not only does the substitution modify the values of
<code>@original</code> in place, but the substitution returns a true value
if the substitution succeeded and a false value otherwise. While that code
<em>looks</em> correct, it's very subtly wrong. The corrected version of
this code in Perl 5.12 or earlier is:</p>

<pre><code>    my @modified = map { my $copy = $_; $copy =~ s/foo/BAR/; $copy } @original;</code></pre>

<p>5.14 requires the addition of a single character to produce the intended
behavior:</p>

<pre><code>    my @modified = map { s/foo/BAR/<strong>r</strong> } @original;</code></pre>

<p>See <code>perldoc perlop</code> for documentation of the <code>/r</code> modifier.</p>]]>
        
    </content>
</entry>

<entry>
    <title>New Features of Perl 5.14: package BLOCK</title>
    <link rel="alternate" type="text/html" href="http://www.perl.com/pub/2011/05/new-features-of-perl-514-package-block.html" />
    <id>tag:www.perl.com,2011:/pub//2.1948</id>

    <published>2011-05-16T18:31:25Z</published>
    <updated>2011-05-16T18:33:32Z</updated>

    <summary>Perl 5.14 adds a package BLOCK declaration.</summary>
    <author>
        <name>chromatic</name>
        <uri>http://www.modernperlbooks.com/</uri>
    </author>
    
    <category term="language" label="language" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl5" label="perl 5" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl514" label="perl 5.14" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="syntax" label="syntax" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.perl.com/pub/">
        <![CDATA[<p><a href="http://news.perlfoundation.org/2011/05/perl-514.html">Perl 5.14 is
now available</a>. While this latest major release of Perl 5 brings with it
many bugfixes, updates to the core libraries, and the usual performance
improvements, it also includes a few nice new features. This series of articles
provides a quick introduction to several of these features.</p>

<p>One such feature is the package BLOCK syntax:</p>

<pre><code>    package My::Class
    {
        ...
    }</code></pre>

<p>When you declare a package, you may now provide a block at the end of
the declaration. Within that block, the current namespace will be the
provided package name. Outside of that block, the previously effective
namespace will be in effect. The block provides normal lexical scoping, so
that any lexical variables declared within the block will be visible only
inside the block. As well, any lexical pragmas will respect the block's
scoping.</p>

<p>You do not need a trailing semicolon after the closing curly brace.</p>

<p>You may combine this with the package VERSION syntax introduced in Perl
5.12:</p>

<pre><code>    package My::Class v2011.05.16
    {
        ...
    }</code></pre>

<p>The VERSION must be an integer, a real number (with a single decimal),
or a dotted-decimal v-string as shown in the previous example. When
present, the VERSION declaration sets the package-scoped
<code>$VERSION</code> variable within the given namespace to the provided
value.</p>

<p><code>perldoc -f package</code> documents this syntax.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Writing on Walls with Facebook::Graph</title>
    <link rel="alternate" type="text/html" href="http://www.perl.com/pub/2011/04/writing-on-walls-with-facebookgraph.html" />
    <id>tag:www.perl.com,2011:/pub//2.1946</id>

    <published>2011-04-05T01:03:13Z</published>
    <updated>2011-04-05T01:08:05Z</updated>

    <summary>JT Smith shows how to write Facebook applications with offline permissions to post to user walls with Perl and Facebook::Graph.</summary>
    <author>
        <name>JT Smith</name>
        <uri>http://www.plainblack.com/</uri>
    </author>
    
    <category term="cpan" label="CPAN" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="dancer" label="Dancer" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="facebook" label="Facebook" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="facebookgraph" label="Facebook::Graph" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="webdevelopment" label="web development" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.perl.com/pub/">
        <![CDATA[<p>In my first article about <a
    href="http://search.cpan.org/perldoc?Facebook::Graph">Facebook::Graph</a>,
I showed you how to <a
    href="http://www.perl.com/pub/2011/03/facebook-authentication-with-perl-and-facebookgraph.html">use
    Facebook as an authentication mechanism for your site</a>.  This time let
me show you how to build on that authentication to post something to a user's
Facebook wall.</p>

<p>First things first. The application needs additional permissions from the
user. The previous app requested only basic rights to view the most basic of
information about the user. Any app that wants to post to auser's wall needs to
ask the user for permission to post to their wall. Replace the existing login
method with:</p>

<pre><code>get '/facebook/login' =&gt; sub {
    my $fb = Facebook::Graph-&gt;new( config-&gt;{facebook} );
    redirect $fb
        -&gt;authorize
        -&gt;extend_permissions( qw(publish_stream) )
        -&gt;uri_as_string;
};</code></pre>

<p>The only difference between this version and the original is the
<code>extend_permissions</code> line which asks for <code>publish_stream</code>
access. Facebook maintains <a
    href="http://developers.facebook.com/docs/authentication/permissions/">a
    table of Facebook application permissions</a> and their implications</a>.

<p>When a user grants this additional permission, the application can post
almost anything to the user's wall. For example, if you have a shop of some
kind, you could post something to a user's wall after a purchase:</p>

<pre><code>my $fb = Facebook::Graph-&gt;new( config-&gt;{facebook} );
$fb-&gt;add_post
  -&gt;set_message('I just bought Widget X from The Cool Shop for only $4.99.')
  -&gt;publish;</code></pre>

<p>Or more descriptive:</p>

<pre><code>$fb-&gt;add_post
  -&gt;set_message('I just bought Widget X from The Cool Shop for only $4.99.')
  -&gt;set_picture_uri('http://images.coolshop.com/widgetx.jpg'),
  -&gt;link_uri('http://www.coolshop.com/products/widget-x'),
  -&gt;link_caption('Widget X')
  -&gt;publish;</code></pre>

<p>If you publish links, do yourself a favor by making sure the page you are
linking uses <a href="http://ogp.me/">Open Graph Protocol</a> meta tags.
Facebook can refer to these tags, and will therefore link that metadata into
your post, which means if anybody posts your link
<em>http://www.coolshop.com/products/widget-x </em>into a Facebook post, it
will automatically pull in images, description, and other things.</p>

<p><strong>NOTE:</strong> Make sure whatever you post abides by <a
    href="http://developers.facebook.com/policy/">Facebook's Platform Polices</a>. If you don't, Facebook can and will ban your application.</p>

<p>This works well for posting something to Facebook when a logged-in user
performs an action in your application, but but what if you want to post
something <em>not</em> as the result of a direct user action? Maybe your site
isn't a shop. Maybe it's a reminders site that posts stuff like "Happy Birthday
Maggie!" or a random quote of the day. To post on behalf of the user even when
they aren't logged in to your site, you must request offline access. This
requires another update to the login page:</p>

<pre><code>get '/facebook/login' =&gt; sub {
    my $fb = Facebook::Graph-&gt;new( config-&gt;{facebook} );
    redirect $fb
        -&gt;authorize
        -&gt;extend_permissions( qw(offline_access publish_stream) )
        -&gt;uri_as_string;
};</code></pre>

<p>You can see the <code>offline_access</code> permission in addition to
<code>publish_stream</code> this time. Another necessary change is to store the
resulting access token in something more robust than a Dancer session this
time:</p>

<pre><code>get '/facebook/postback/' =&gt; sub {
    my $params = request-&gt;params;
    my $fb     = Facebook::Graph-&gt;new( config-&gt;{facebook} );

    $fb-&gt;request_access_token($params-&gt;{code});
    session access_token =&gt; $fb-&gt;access_token;

    my $user = $fb-&gt;fetch('me');

    database-&gt;quick_insert( 'facebook', {
        uid          =&gt; $user-&gt;{uid},=20
        name         =&gt; $user-&gt;{name},=20
        access_token =&gt; $fb-&gt;access_token,
       }
    );
    redirect '/';
};</code></pre>

<p>In addition to storing the <code>access_token</code> in a Dancer session,
the code also stores it in a database table for future reference (using <a
    href="http://search.cpan.org/perldoc?Dancer::Plugin::Database">Dancer::Plugin::Database</a>,
which is a wrapper around <a
    href="http://search.cpan.org/perldoc?DBI">DBI</a>). This sort of thing can
be good for other reasons too. For example, Facebook recommends caching data
that you fetch from it for faster response times. If you want to display the
user's name on every page, it's much faster to pull it out of the local
database based upon the access token you have in your Dancer session than it is
to request it from Facebook again.</p>

<p>As you can see, <code>Facebook::Graph</code> makes it quite easy to post to
Facebook on behalf of your users. Stay tuned for Part III, where I'll show you
how to publish calendar events and RSVP to them.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Facebook Authentication with Perl and Facebook::Graph</title>
    <link rel="alternate" type="text/html" href="http://www.perl.com/pub/2011/03/facebook-authentication-with-perl-and-facebookgraph.html" />
    <id>tag:www.perl.com,2011:/pub//2.1944</id>

    <published>2011-03-15T17:17:51Z</published>
    <updated>2011-04-05T01:08:18Z</updated>

    <summary>In the first of a series on writing Facebook applications with Perl, JT Smith demonstrates how to register an application and authenticate users with Facebook::Graph.</summary>
    <author>
        <name>JT Smith</name>
        <uri>http://www.plainblack.com/</uri>
    </author>
    
    <category term="cpan" label="CPAN" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="dancer" label="Dancer" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="facebook" label="Facebook" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="facebookgraph" label="Facebook::Graph" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="webdevelopment" label="web development" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.perl.com/pub/">
        <![CDATA[<p>Basic integration of software and web sites with Facebook, Twitter, and
other social networking systems has become a litmus test for business these
days. Depending on the software or site you might need to fetch some data, make
a post, create events, upload photos, or use one or more of the social
networking sites as a single sign-on system. This series will show you how to
do exactly those things on Facebook using <a
    href="http://search.cpan.org/perldoc?Facebook::Graph">Facebook::Graph</a>.</p>

<p>This first article starts small by using Facebook as an authentication
mechanism. There are certainly simpler things to do, but this is one of the
more popular things people want to be able to do.  Before you can do anything,
you need to have a Facebook account. Then <a
    href="http://apps.facebook.com/developer">register your new application</a>
(Figure 1).</p>

<p><img src="http://www.perl.com/pub/2011/03/15/register_app.png" alt="registering a Facebook application"
width="696" height="209" /><br /><em>Figure 1. Registering a Facebook
    application.</em></p>

<p>Then fill out the "Web Site" section of your new app (Figure 2).</p>

<p><img src="http://www.perl.com/pub/2011/03/15/register_website.png" width="740" height="224" alt="registering
your application's web site" /><br /><em>Figure 2. Registering your
    application's web site.</em></p>

<p>Registering an application with Facebook gives you a unique identifier for
your application as well as a secret key. This allows your app to communicate
with Facebook and use its API. Without it, you can't do much (besides screen
scraping and hoping).</p>

<p>Now you're ready to start creating your app. I've used the <a
    href="http://perldancer.org/">Dancer web app framework</a>, but feel free
to use your favorite.  Start with a basic Dancer module:</p>

<pre><code>package MyFacebook;

use strict;
use Dancer ':syntax';
use Facebook::Graph;

get '/' =&gt; sub {
  template 'home.tt'
};

true;</code></pre>

<p>That's sufficient to give the app a home page. The next step is to force
people to log in if they haven't already:</p>

<pre><code>before sub {
    if (request-&gt;path_info !~ m{^/facebook}) {
        if (session-&gt;{access_token} eq '') {
            request-&gt;path_info('/facebook/login')
        }
    }
};</code></pre>

<p>This little bit of Dancer magic says that if the path is not
<code>/facebook</code> and the user has no access_token attached to their
session, then redirect them to our login page. Speaking of our login page,
create that now:</p>

<pre><code>get '/facebook/login' =&gt; sub {
    my $fb = Facebook::Graph-&gt;new( config-&gt;{facebook} );
    redirect $fb-&gt;authorize-&gt;uri_as_string;
};</code></pre>

<p>This creates a page that will redirect the user to Facebook, and ask them if
it's ok for the app to use their basic Facebook information. That code passes
<code>Facebook::Graph</code> some configuration information, so remember to add
a section to Dancer's <em>config.yml</em> to keep track of that:</p>

<pre><code>facebook:
    postback: "http://www.madmongers.org/facebook/postback/"
    app_id: "XXXXXXXXXXXXXXXX"
    secret: "XXXXXXXXXXXXXXXXXXXXXXXXXXX"</code></pre>

<p>Remember, you get the app_id and the secret from Facebook's developer
application after you create the app. The postback tells Facebook where to post
back to after the user has granted the app authorization. Note that Facebook
requires a slash (/) on the end of the URL for the postback. With Facebook
ready to post to a URL, it's time to create it:</p>

<pre><code>get '/facebook/postback/' =&gt; sub {
    my $authorization_code = params-&gt;{code};
    my $fb                 = Facebook::Graph-&gt;new( config-&gt;{facebook} );

    $fb-&gt;request_access_token($authorization_code);
    session access_token =&gt; $fb-&gt;access_token;
    redirect '/';
};</code></pre>

<p>NOTE: I know it's called a postback, but for whatever reason Facebook does
the <code>POST</code> as a <code>GET</code>.</p>

<p>Facebook's postback passes an authorization code&mdash;a sort of temporary
password. Use that code to ask Facebook for an access token (like a session
id). An access token allows you to request information from Facebook <em>on
    behalf of the user</em>, so all of those steps are, essentially, your app
logging in to Facebook.  However, unless you store that access token to use
again in the future, the next request to Facebook will log you out.  Therefore,
the example shoves the access token into a Dancer session to store it for
future use before redirecting the user back to the front page of the site.</p>

<p>NOTE: The access token we have will only last for two hours. After that, you
have to request it again.</p>

<p>Now you can update the front page to include a little bit of information
from Facebook. Replace the existing front page with this one:</p>

<pre><code>get '/' =&gt; sub {
    my $fb = Facebook::Graph-&gt;new( config-&gt;{facebook} );

    $fb-&gt;access_token(session-&gt;{access_token});

    my $response = $fb-&gt;query-&gt;find('me')-&gt;request;
    my $user     = $response-&gt;as_hashref;
    template 'home.tt', { name =&gt; $user-&gt;{name} }
};</code></pre>

<p>This code fetches the access token back out of the session and uses it to
find out some information about the current user. It passes the name of that
user into the home template as a template parameter so that the home page can
display the user's name. (How do you know what to request and what responses
you get? See the <a
    href="http://developers.facebook.com/docs/reference/api/">Facebook Graph
    API documentation</a>.)</p>

<p>While there is a bit of a trick to using Facebook as an authentication
system, it's not terribly difficult.  Stay tuned for Part II where I'll show
you how to post something to a user's wall.</p>
]]>
        
    </content>
</entry>

<entry>
    <title>Perl QA Hackathon 2011: Call to Attention</title>
    <link rel="alternate" type="text/html" href="http://www.perl.com/pub/2011/02/perl-qa-hackathon-2011-call-to-attention.html" />
    <id>tag:www.perl.com,2011:/pub//2.1942</id>

    <published>2011-02-02T19:32:47Z</published>
    <updated>2011-02-02T19:41:31Z</updated>

    <summary>Lars Dɪᴇᴄᴋᴏᴡ has sent out a call for attention for the 2011 Perl QA Hackathon: The Perl QA hackathon 2011 is taking place from Saturday, April 16th to Monday, April 18th 2011 in Amsterdam, The Netherlands. Attendance is gratis. We...</summary>
    <author>
        <name>chromatic</name>
        <uri>http://www.modernperlbooks.com/</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://www.perl.com/pub/">
        <![CDATA[<p><a href="http://search.cpan.org/~daxim">Lars Dɪᴇᴄᴋᴏᴡ</a> has sent out a call for attention for the <a href="http://2011.qa-hackathon.org/qa2011/">2011 Perl QA Hackathon</a>:</p>

<blockquote><p>The Perl QA hackathon 2011 is taking place from Saturday, April 16th to 
Monday, April 18th 2011 in Amsterdam, The Netherlands. Attendance is 
gratis. We would like to know if you are interested in coming and 
participating. You can also propose other people who should be invited. As 
with the hackathons in the past years, we aim to fund the travel and 
accommodation costs for those who cannot get funding otherwise.</p>

<p>We would like to hear about your topics and ideas. Please find further 
information at the <a href="http://2011.qa-hackathon.org/qa2011/wiki">Perl QA Hackathon 2011 Wiki</a>.</p></blockquote>]]>
        
    </content>
</entry>

<entry>
    <title>Visualizing Music with SDL and Perl</title>
    <link rel="alternate" type="text/html" href="http://www.perl.com/pub/2011/01/visualizing-music-with-sdl-and-perl.html" />
    <id>tag:www.perl.com,2011:/pub//2.1940</id>

    <published>2011-01-24T14:00:01Z</published>
    <updated>2011-01-25T00:59:27Z</updated>

    <summary>In this edited excerpt from the SDL Perl manual, lead developer Kartik
Thakore walks through a non-game application of SDL and Perl, building a
music player with visualizations in just a few lines of code.</summary>
    <author>
        <name>Kartik Thakore</name>
        <uri>http://sdl.perl.org/</uri>
    </author>
    
    <category term="graphics" label="graphics" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="music" label="music" 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" />
    <category term="sdl" label="SDL" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.perl.com/pub/">
        <![CDATA[<h1><strong>Music Visualization with Perl and SDL</strong></h1>

<p>Many users know SDL as a powerful cross-platform library for graphics
programming and input, especially as the foundation of many open source
games. Perl users know it as the technology behind the beloved <a
href="http://www.frozen-bubble.org/">Frozen Bubble</a>.</p>

<p>Perl and SDL can do far more than destroy an infinite onslaught of
cartoon bubbles, however. The recently revitalized <a
href="http://sdlperl.ath.cx/projects/SDLPerl/">SDL Perl</a> project has
taken up the challenge of demonstrating that everyone's favorite system
administration language is capable of producing powerful multimedia
programs&mdash;including, but not limited to, games.</p>

<p>In this edited excerpt from the <a href="http://sdlperl.ath.cx/releases/SDL_Manual.html">SDL Perl manual</a>, lead developer Kartik
Thakore walks through a non-game application of SDL and Perl, building a
music player with visualizations in just a few lines of code.</p>

<h2><strong>Running this Demo</strong></h2>

<p>To run this example software, you need:</p>

<ul>

<li>Perl 5.10, with threading enabled</li>

<li>A curent installation of CPAN</li>

<pre><code>    $ <strong>cpan CPAN</strong></code></pre>

<li>The native libraries of libsdl, libsdl_mixer (with Ogg support),
libsdl_gfx, and their development packages</li>

<pre><code>    $ <strong>cpan Alien::SDL</strong></code></pre>

<li>SDL perl version 5.526 or newer</li>

<pre><code>    $ <strong>cpan SDL</strong></code></pre>

<li><a href="http://www.perl.com/pub/2011/01/24/music_visualizer.zip">this article's example files</a></li>

</ul>

<p>With all of that installed, extract the example file and run the
visualizer:</p>

<pre><code>    $ <strong>cd music_visualiser/</strong>
    $ <strong>perl visualiser.pl</strong></code></pre>

<h2><strong>Music Visualizer</strong></h2>

<p>The music visualizer example processes real-time sound data&mdash;data as it
plays&mdash;and displays the wave form on the screen. It will look something
like Figure 1.</p>

<p><img src="http://www.perl.com/pub/2011/01/24/spectro-1.png" alt="Simple Music Visualization" />
<br /><em>Figure 1. A simple music visualization.</em></p>

<h3><strong>The Code and Comments</strong></h3>

<p>The program begins with the usual boilerplate of an SDL Perl
application:</p>

<pre><code>    use strict;
    use warnings;

    use Cwd;
    use Carp;
    use File::Spec;

    use threads;
    use threads::shared;

    use SDL;
    use SDL::Event;
    use SDL::Events;

    use SDL::Audio;
    use SDL::Mixer;
    use SDL::Mixer::Music;
    use SDL::Mixer::Effects;

    use SDLx::App;</code></pre>

<p>It then creates an application with both audio and video support:</p>

<pre><code>    my $app = SDLx::App-&gt;new(
        init   =&gt; SDL_INIT_AUDIO | SDL_INIT_VIDEO,
        width  =&gt; 800,
        height =&gt; 600,
        depth  =&gt; 32,
        title  =&gt; &quot;Sound Event Demo&quot;,
        eoq    =&gt; 1,
        dt     =&gt; 0.2,
    );</code></pre>

<p>The application must initialize the audio system with a format matching
the expected audio input. <code>AUDIO_S16</code> provides a 16-bit signed
integer array for the stream data:</p>

<pre><code>    # Initialize the Audio
    unless ( SDL::Mixer::open_audio( 44100, AUDIO_S16, 2, 1024 ) == 0 ) {
        Carp::croak &quot;Cannot open audio: &quot; . SDL::get_error();
    }</code></pre>

<p>The music player needs the music files from the <em>data/music/</em>
directory:</p>

<pre><code>    # Load our music files
    my $data_dir = &#39;.&#39;;
    my @songs    = glob &#39;data/music/*.ogg&#39;;</code></pre>

<p>A music effect reads the music data into a stream array, shared between
threads:</p>

<pre><code>    my @stream_data :shared;

    #  Music Effect to pull Stream Data
    sub music_data {
        my ( $channel, $samples, $position, @stream ) = @_;

        {
            lock(@stream_data);
            push @stream_data, @stream;
        }

        return @stream;
    }</code></pre>

<p>... and that effect gets registered as a callback with
<code>SDL::Mixer::Effects</code>:</p>

<pre><code>    my $music_data_effect_id =
          SDL::Mixer::Effects::register( MIX_CHANNEL_POST, &quot;main::music_data&quot;,
            &quot;main::done_music_data&quot;, 0 );</code></pre>

<p>The program's single command-line option governs the number of lines to
display in the visualizer. The default is 50.</p>

<pre><code>    my $lines = $ARGV[0] || 50;</code></pre>

<p>The drawing callback for the <code>SDLx::App</code> runs while a song plays.
It reads the stream data and displays it on the screen as a wave form. The math
calculations produce a multi-colored bar graph representing slices of the music
data. The remaining visualization code should be straightforward:</p>

<pre><code>    #  Music Playing Callbacks
    my $current_song = 0;
    my $lines        = $ARGV[0] || 50;

    my $current_music_callback = sub {
        my ( $delta, $app ) = @_;

        $app-&gt;draw_rect( [ 0, 0, $app-&gt;w(), $app-&gt;h() ], 0x000000FF );
        $app-&gt;draw_gfx_text(
            [ 5, $app-&gt;h() - 10 ],
            [ 255, 0, 0, 255 ],
            &quot;Playing Song: &quot; . $songs[ $current_song - 1 ]
        );

        my @stream;
        {
            lock @stream_data;
            @stream      = @stream_data;
            @stream_data = ();
        }

        # To show the right amount of lines we choose a cut of the stream
        # this is purely for asthetic reasons.

        my $cut = @stream / $lines;

        # The width of each line is calculated to use.
        my $l_wdt = ( $app-&gt;w() / $lines ) / 2;

        for ( my $i = 0 ; $i &lt; $#stream ; $i += $cut ) {

            #  In stereo mode the stream is split between two alternating streams
            my $left  = $stream[$i];
            my $right = $stream[ $i + 1 ];

            #  For each bar we calculate a Y point and a X point
            my $point_y = ( ( ($left) ) * $app-&gt;h() / 4 / 32000 ) + ( $app-&gt;h / 2 );
            my $point_y_r =
              ( ( ($right) ) * $app-&gt;h() / 4 / 32000 ) + ( $app-&gt;h / 2 );
            my $point_x = ( $i / @stream ) * $app-&gt;w;

            # Using the parameters
            #   Surface, box coordinates and color as RGBA
            SDL::GFX::Primitives::box_RGBA(
                $app,
                $point_x - $l_wdt,
                $app-&gt;h() / 2,
                $point_x + $l_wdt,
                $point_y, 40, 0, 255, 128
            );
            SDL::GFX::Primitives::box_RGBA(
                $app,
                $point_x - $l_wdt,
                $app-&gt;h() / 2,
                $point_x + $l_wdt,
                $point_y_r, 255, 0, 40, 128
            );

        }

      $app-&gt;flip();
    };</code></pre>

<p>Whenever a song finishes, <code>SDL::Mixer::Music::playing_music</code>
returns <code>0</code>. The program detects this state change and calls
<code>music_finished_playing()</code>, where the program attaches the
<code>$play_next_song_callback</code> callback to switch to the next song
gracefully:</p>

<pre><code>    my $cms_move_callback_id;
    my $pns_move_callback_id;
    my $play_next_song_callback;

    sub music_finished_playing {
        SDL::Mixer::Music::halt_music();
        $pns_move_callback_id = $app-&gt;add_move_handler( $play_next_song_callback )
            if defined $play_next_song_callback;
    }

    $play_next_song_callback = sub {
        return $app-&gt;stop() if $current_song &gt;= @songs;

        my $song = SDL::Mixer::Music::load_MUS($songs[$current_song++]);

        SDL::Mixer::Music::hook_music_finished(&#39;main::music_finished_playing&#39;);
        SDL::Mixer::Music::play_music($song, 0 );

        $app-&gt;remove_move_handler( $pns_move_callback_id )
            if defined $pns_move_callback_id;
    };</code></pre>

<p>A move handler detects if music is playing:</p>

<pre><code>    $app-&gt;add_move_handler(
       sub {
           my $music_playing = SDL::Mixer::Music::playing_music();
           music_finished_playing() unless $music_playing;
       }
   );</code></pre>

<p>The first callback to trigger <code>$play_next_song_callback</code> gets the
first song:</p>

<pre><code>    $app-&gt;add_show_handler($current_music_callback);
    $pns_move_callback_id = $app-&gt;add_move_handler( $play_next_song_callback);</code></pre>

<p>... and a keyboard event handler for a keypress allows the user to move
through songs:</p>

<pre><code>    $app-&gt;add_event_handler(
        sub {
            my ($event, $app) = @_;

            if ($event-&gt;type == SDL_KEYDOWN &amp;&amp; $event-&gt;key_sym == SDLK_DOWN)
            {
                # Indicate that we are done playing the music_finished_playing
                music_finished_playing();
            }
        }
    );</code></pre>

<p>From there, the application is ready to run:</p>

<pre><code>    $app-&gt;run();</code></pre>

<p>... and the final code gracefully stops <code>SDL::Mixer</code>:</p>

<pre><code>    SDL::Mixer::Effects::unregister( MIX_CHANNEL_POST, $music_data_effect_id );
    SDL::Mixer::Music::hook_music_finished();
    SDL::Mixer::Music::halt_music();
    SDL::Mixer::close_audio();</code></pre>

<p>The result?  Several dozen lines of code glue together the SDL mixer and
display a real-time visualization of the music.</p>]]>
        
    </content>
</entry>

<entry>
    <title>The Philosophy of WebNano</title>
    <link rel="alternate" type="text/html" href="http://www.perl.com/pub/2010/11/the-philosophy-of-webnano.html" />
    <id>tag:www.perl.com,2010:/pub//2.1938</id>

    <published>2010-11-24T03:31:41Z</published>
    <updated>2010-11-25T00:50:07Z</updated>

    <summary>Why do so many web applications have the same components, yet so few actually share those components as libraries?  Perhaps the philosophy of building web frameworks is the culprit.  Zbigniew Lukasiak&apos;s WebNano is an attempt to solve that problem.</summary>
    <author>
        <name>Zbigniew Lukasiak</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://www.perl.com/pub/">
        <![CDATA[<h1>Why WebNano</h1>

<p>Many web applications have common components: a login page, a comment box,
an email confirmation mechanism, a generic CRUD page.  All of these are
well-defined components.  It's easy to believe that it should not be difficult
to abstract them away into libraries.  Yet every time you start a web
application you need to write that boring comment box again and again.</p>

<p>Why are there so few such libraries?  Why is writing them so hard?  There
are more and less important reasons, but there are many reasons.  Most projects
to make components eventually die the death of a thousand cuts.  Some of those problems can be solved and I believe that solving them would make a difference. <a
    href="http://search.cpan.org/perldoc?WebNano">WebNano</a> is my attempt at
doing that.<p>

<p>Probably the most popular Perl web framework is <a
    href="http://catalystframework.org/">Catalyst</a>.  It is also the web
framework I know the best&mdash;this is why I chose it as the point of
reference for my analysis.</p>

<h2><strong>Controllers in request scope</strong></h2>

<p>Five years ago I was staring at the first Catalyst examples and had foggy
intuition that there was something not quite optimal.  The essence of object
oriented programming is that the most accessed data should be available to all
methods in a class without explicitly passing it via parameters, but the
Catalyst examples always started with <code>my ( $self, $c, ... ) = @_</code>.
That's not very <a href="http://c2.com/cgi/wiki?DontRepeatYourself">DRY</a>.
The <code>$c</code> parameter gets passed everywhere as if it were a plain old
parameter.</p>

<p>At some point I <a
    href="http://perlalchemy.blogspot.com/2009/10/catalystcomponentinstancepercontext.html">counted
    how often methods from the manual use the controller object versus how
    often they use the context object which contains the request data</a>.  The
result was 117 and 38 respectively.  Many people commented that their code
often uses the controller object.  It's hard to judge this unless you can see
that code, but as my code resembled the example code from the manual, this
seems common.  This disproportion is only an illustration.  The question is not
about switching <code>$c</code> with <code>$self</code>. The question is why
the request data, which undeniably is in the center of the computation carried
out in controllers, is anything other than instance data.</p>

<p>My curiosity persisted until about a year ago, when I received a reply in
private communication from some members of the core team.  They want the
controller object to be immutable (see <a
    href="http://blog.woobling.org/2009/05/immutable-data-structures.html">Immutable
    Data Structures</a>).  That's impossible if the values of one or more of
its attributesmust necessarily change with each incoming request.  Immutable
objects are a good design choice and I accepted this answer but later I
wondered what would happen if the framework recreated the controller object
anew with each request?  Then it could hold the request data and still be
immutable for the lifetime of the request.</p>

<p>This would be a big change for Catalyst; Catalyst controllers are created at
the starup time, together with all the other application components (models and
views) and changing that does not seem feasible.  I decided to write a new web
framework.</p>

<p>I have tried many Perl web frameworks but I found only one more that uses
controllers in request scope.  This is a fundamental distinguishing feature of
WebNano.  It's not only about reducing the clutter of repeatable parameter
passing.  Instead, I believe that putting object into their natural scope will
fix a lot of the widely recognized <a
    href="http://jjnapiorkowski.vox.com/library/post/does-anyone-else-hate-the-stash.html">problems
    with the Catalyst stash and data passed through it</a>.  In procedural
programming it is not controversial to put your variable declarations into the
narrowest block that encompasses their uses.  The same should be true for
objects.  Using the same controller to serve multiple request <em>is</em> a bit
faster then recreating it each time, but that gain is modest.  <a
    href="http://www.cpantesters.org/cpan/report/7c61aa08-d810-11df-8503-f91d06264d1f">Object::Tiny
    on one of the tester machines could create 714286 object per second</a> and
even <a href="http://moose.perl.org/">Moose</a>, the slowest framework tested
there, can create more then a 10000 objects per second.  Eliminating a few of
such operations, in most circumstances, is not worth compromising on the
architecture.</p>

<p>I also tested these theoretical estimations with more down to earth <a
    href="http://httpd.apache.org/docs/2.0/programs/ab.html">ab</a> benchmarks
for a trivial application serving just one page.  WebNano was the fasted
framework tested, by a wide margin.  This is still an artificial test, but it
should be accurate enough to show that the cost introduced by this design
choice does not need to be big.</p>

<h2><strong>Decoupling</strong></h2>

<p>WebNano may have tested as the fastest framework because it does not do
much.  WebNano is really small. Its <em>lib/</em> directory currently contains
just 233 lines of code (as reported by <a
    href="http://www.dwheeler.com/sloccount/">sloccount</a>) and <a
    href="http://deps.cpantesters.org/?module=WebNano;perl=latest">minimal
    dependencies</a>.  CPAN libraries cover all corners of web application
programming, so WebNano can provide a basic structure and otherwise get out of
the way.  Assuming simplicity allowed me to remove a lot of code required for
advanced flexibility.</p>

<p>For example, Catalyst started the process of decoupling the web framework
from other parts of the application. With Catalyst you can use any persistence
layer for the model and any templating library for the view.  Yet with this
flexibility the <code>model()</code> and <code>view()</code> methods in
Catalyst are very simple.  There is no common behaviour among the various
libraries, so all these methods do is find a model or view by its name.  For
WebNano I decided that <code>-&gt;Something</code> is shorter and no less
informative then <code>-&gt;model('Something')</code>, so I removed the
<code>model()</code> and <code>view()</code> methods.</p>

<p>I also decided to leave out component initialization.  This is a generic
task used in all kinds of programs.  Any library which performs this task needs
to know nothing about the web part of the application, and CPAN offers many
such initialization libraries.  In my limited experiments <a
    href="http://search.cpan.org/dist/MooseX-SimpleConfig/">MooseX::SimpleConfig</a>
was very convenient. For more complex needs, <a
    href="http://search.cpan.org/dist/Bread-Board/">Bread::Board</a> seems like
a good choice.  This initialization layer needs to know how to create all the
objects used by the application, but you need no WebNano adapter to use
them.</p>

<h2><strong>Localized dispatching</strong></h2>

<p>Out of the box WebNano supports only one very simple dispatching model.
Dispatching controls which subroutine to call with which arguments and depends
directly on the behavior of the subroutines themselves.  This is why I don't
believe in external dispatchers where you configure all the dispatching for the
application in one place.  The dispatching might be in one place, but any
practical change you make requires updates in two places.  WebNano's default
dispatching is easy to extend and override on per-controller basis.</p>

<p>Writing a dispatcher is not hard; it's only complex and difficult when you
try to write a dispatching model to work for every possible application.  I
prefer to write a simple dispatcher covering only the most popular dispatching
scenarios and let the users of my framework write any specialized dispatching
code for specialized controllers. With WebNano this is possible because these
specialized dispatchers don't interfere with each other.</p>

<p>I also believe that this will make the controller classes more encapsulated
and facilitate building libraries of application controllers.</p>

<h2><strong>Granularity</strong></h2>

<p>I like the way Catalyst structures your web related code into controller
classes. This is a step forward from the <a
    href="http://search.cpan.org/~markstos/CGI-Application-4.31/lib/CGI/Application.pm">CGI::Application</a>
way of packing everything into one class.  I have no hard data to support my
impression, but the granularity of packing a few related pages into one
controller class feels just about right.  It gives room for expansion by adding
new classes and dividing existing ones, and it does not clutter the application
code with several nearly empty classes.  This is a very important feature.  I
copied this design wholeheartedly in WebNano.</p>

<h2><strong>Experiments with inheritance and overriding</strong></h2>

<p>One of the WebNano tests is an application which subclasses the main test
app.  It passes all the original tests and could be completely empty if I did
not want to test the overriding of the inherited parts.  I have seen many times
a need for such behaviour, from branding websites to SaaS to reusable intranet
tools.  Too many applications solve the problem of reuse by copying code.
Inheritance has its problems, but it enables ad-hoc reuse better than cut and
paste programming.</p>

<p>Be aware that you need to override much more than just methods.  My
experiment with WebNano overrides application parts: controllers, templates,
and configuration.  It also overrides individual controllers at the template
and method levels.</p>

<p>This type of inheritance could enable a natural mechanism to publish
applications to CPAN, because they could operate with no special installation.
Users could run them directly from <code>@INC</code> and only later override
the configuration or templates as needed.</p>

<h2><strong>Universality</strong></h2>

<p>In the most common case a web application serving a request needs to fetch
data, perform some computations on this data, and render a template with the
computed values.  Those tasks typically consume 99% of the overall time spent
serving a request. The other 1% of time spent in the application framework
processing matters little; reducing it will produce little noticeable speed
increase in the whole application.</p>

<p>Even so, there might be rare cases where the application needs to serve, for
example, small JSON data chunks from a memory cache. Even when this is a small
and simple part of the application, if it generates enough volume then the
speed of the framework suddenly becomes important. Would you code that part in
PHP?</p>

<p>I was very tempted to use Moose in WebNano.  Moose generates some
significant startup overhead, though for web applications running in persistent
environments this does not matter much because that overhead amortizes over
many requests. If you run your application as CGI, this startup time becomes
important.  Even if CGI is perceived as pass&eacute; now, it is still the
easiest way to deploy web applications and (especially with the most widespread
support from hosting companies).  Fortunately, using <a
    href="http://search.cpan.org/perldoc?MooseX::NonMoose">MooseX::NonMoose</a>
it is very easy to treat any hash based object classes as base classes for
Moose based code, so using WebNano does not mean that you need to stick to the
simplistic Object Oriented Framework it uses.</p>

<p>The plan is to make WebNano small but universal, then make extensions that
will be more powerful and more restricted. I think it is important that the
base platform can be used in all kinds of circumstances.</p>

<h2><strong>Conclusions</strong></h2>

<p>It is early to say if WebNano will live to the promise of facilitating the
development of web application components.  There is a first component at CPAN:
<a
    href="http://search.cpan.org/dist/WebNano-Controller-CRUD/">WebNano::Controller::CRUD</a>.
It still bears the label "experimental", but I used it in <a
    href="https://github.com/zby/Nblog">Nblog</a>.  When I compare it to my
first similar product <a
    href="http://search.cpan.org/~wreis/Catalyst-Example-InstantCRUD-0.037/lib/Catalyst/Example/Controller/InstantCRUD.pm">Catalyst::Example::Controller::InstantCRUD</a>,
there aren't many differences. As you might predict, the methods have one less
parameter (<code>$c</code>).  Inheritable templates are also nice for
deployment&mdash;you don't need to write your own templates to see it working,
and later you can easily override the defaults.  There is a bit more
dispatching code, but thanks to that, the code retrieves the result object in
only one place.  In Catalyst this is possible with chained dispatching.  In the

<a
    href="https://github.com/zby/WebNano/tree/master/examples/DvdDatabase/lib/DvdDatabase/Controller/">examples
    directory</a> there are four variations on this CRUD theme.  I remain
undecided about whis is optimal.</p>

<p>The surprising thing when converting Nblog from Catalyst to WebNano was how
little I missed the rich Catalyst features, even though WebNano has still so
little code.  I think it is a promising start.</p>

<p>Recently I discovered echoes of many of my design choices in the
publications by the Google testing guru <a
    href="http://misko.hevery.com/">Miško Hevery</a>.  My point of departure
for the considerations above were general rules such as decoupling and
encapsulation, where his concern is testability.  The resulting <a
    href="http://misko.hevery.com/2008/08/21/where-have-all-the-singletons-gone/">design
    without singletons</a> is remarkably similar.  There is a lot of good
articles at his blog, some were similar to what I already had considered (<a
    href="http://misko.hevery.com/2009/04/15/managing-object-lifetimes/">managing
    object lifetimes</a>) and others were completely new to me (<a
    href="http://misko.hevery.com/2009/04/08/how-to-do-everything-wrong-with-servlets/">how
    to do everything wrong with servlets</a>).  I recommend them all.</p>
]]>
        
    </content>
</entry>

<entry>
    <title>Perl in Plat_Forms 2011</title>
    <link rel="alternate" type="text/html" href="http://www.perl.com/pub/2010/10/perl-in-plat-forms-2011.html" />
    <id>tag:www.perl.com,2010:/pub//2.1936</id>

    <published>2010-10-29T21:25:51Z</published>
    <updated>2010-10-29T21:34:38Z</updated>

    <summary>Thanks to Lars Dɪᴇᴄᴋᴏᴡ for sending along this notice about the Plat_Forms 2011 web development contest. Unlike other comparisons of programming languages (such as the great unmaintainable speed-tweakers micromeasurement contest and This Is Odiously Bad Empiricism), Plat_Forms features real teams...</summary>
    <author>
        <name>chromatic</name>
        <uri>http://www.modernperlbooks.com/</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://www.perl.com/pub/">
        <![CDATA[<p>Thanks to <a href="http://search.cpan.org/~daxim/">Lars Dɪᴇᴄᴋᴏᴡ</a> for
sending along this notice about the <a
href="http://www.plat-forms.org/">Plat_Forms 2011 web development contest</a>.
Unlike other comparisons of programming languages (such as <a
href="http://shootout.alioth.debian.org/">the great unmaintainable
speed-tweakers micromeasurement contest</a> and This Is Odiously Bad
Empiricism), Plat_Forms features real teams of real programmers performing real
work.</p>

<p>Perl 5 can compete very well in this contest, with great web frameworks such as (but not limited to) Catalyst, Dancer, Mojolicious, and Jifty.  See the <a href="http://www.plat-forms.org/platforms-announcement#overview">Plat_Forms 2011 overview</a> and <a href="https://www.socialtext.net/perl5/index.cgi?events_2011_plat_forms">Plat_Forms 2011 on the Perl 5 Wiki</a> for more details.</p>
]]>
        
    </content>
</entry>

</feed>

