<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Perlsphere</title>
  <link rel="alternate" href="http://perlsphere.net/" type="text/html"/>
  <updated>2009-07-04T07:18:01Z</updated>
  <generator>Plagger/0.7.17</generator>
  <subtitle>The Perl firehose! The Web's biggest collection of Perl blogs.&lt;br /&gt;If you'd like your Perl blog or tech blog's Perl category to appear here, send mail to &amp;#112;&amp;#101;&amp;#114;&amp;#108;&amp;#115;&amp;#112;&amp;#104;&amp;#101;&amp;#114;&amp;#101;&amp;#64;&amp;#100;&amp;#111;&amp;#119;&amp;#110;&amp;#108;&amp;#111;&amp;#100;&amp;#101;&amp;#46;&amp;#111;&amp;#114;&amp;#103;.</subtitle>
  <id>tag:perlsphere.net,2006:smartfeed:all</id>
  <entry>
    <title>Ameliorate the Risk of Upgrading to a New Perl Release</title>
    <link rel="alternate" href="http://www.modernperlbooks.com/mt/2009/07/ameliorate-the-risk-of-upgrading-to-a-new-perl-release.html" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">Contrary to the strawman arguments set up and knocked down so easily by
people who believe that breaking the DarkPAN is a sin almost as bad as
apparent hypocrisy on the Internet, no one wants to change Perl 5
willy-nilly. Yet many people believe that a few carefully-planned
backwards-incompatible changes will allow Perl 5 to evolve into a much
more powerful, much cleaner, much more understandable, and even much
simpler language suitable not only for maintaining legacy projects but
also for creating amazing new projects.

I intended my deconstruction of fear surrounding Perl core language
changes to continue a long-standing debate. If you read Planet Perl Iron
Man or Planet Perl, you've read other people arguing over the
desirability of supporting the DarkPAN.

If your code is part of the DarkPAN (and it likely isn't, as you're
likely a part of the Perl community if you're reading this), you may
bristle at the suggestion that some people believe that retaining core
language backwards compatibility to support your code is one of the worst
ideas in Perl history. (If you haven't heard that suggestion, let me
repeat it: the idea that the Perl community should support hidden and
proprietary code of people who aren't part of the community, code that
the Perl community can't see let alone test, and code that may or may not
even exist is sufficiently ridiculous on its face that it mocks itself.)

Now then.

My previous post suggested that the real problem the Perl community is
trying to solve is one of risk management. If it doesn't make sense to
push all of the costs to manage the risk that an upgrade might change the
way your DarkPAN code behaves to the Perl community (and it doesn't make
sense), who bears that cost?

You do.

Don't panic, yet. It's simple to address that risk. I didn't say it's
easy. I said it's simple.


Your Responsibility as a DarkPAN Maintainer
-------------------------------------------

As a DarkPAN maintainer, you need to answer several questions about your
code.

  * Is this software worth maintaining?

  * Is this software under active maintenance?

  * Does this software need community support for the Perl core and any
    external dependencies?

  * Will this software work unchanged with a newer version of Perl?

  * If not, why not?

  * What changes are necessary to make this software work with a newer
    version of Perl?

Software outside of active maintenance can stay untouched. Don't worry
about it. (Of course, if you have to migrate to a new machine or a new
architecture or other dependencies, it's under active maintenance at
least for the sake of this argument.)

The other questions are more important. You need to be able to verify
that your code will perform as you expect if you change one or more
dependency.

Likely you already need to know this.

You need a comprehensive test suite which can run on any likely candidate
machine. You need a test environment where you can run your software's
test suite against an updated dependency -- a new CPAN distribution, for
example, or a new major release of Perl. You need unambiguous results and
comprehensible diagnostics.

In short, you need a sane development environment, just like any serious
project worth your time already has.

(You should also have a ten minute build, but if you can verify that your
software does what you expect in an hour or less and report the results
to the Perl community, you're well on your way.)

If you're really good, you can even test your DarkPAN code against
bleadperl or maintenance snapshots just to help p5p understand your
expectations (and to understand potential changes to the language which
may require you to revise your expectations, if not your code).

Anyone serious about software development should have a comprehensive and
useful test suite anyway. It's simple. It's not always easy; the Perl
community needs to make CPAN distribution installation and versioning
easier and cleaner. That debate is happening. The solution isn't obvious
yet, but a process of iteration and refinement will produce it.

Yet any DarkPAN code of such low importance that its maintainers can't
produce a test suite to verify that it works isn't worth p5p's time.
Forget that code. It's a dead end. Let's concentrate instead on refining
a language for serious software developers to write new code worth
maintaining.</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml"><p>Contrary to the strawman arguments set up and knocked down so easily by people who believe that breaking the DarkPAN is a sin almost as bad as apparent hypocrisy on the Internet, no one wants to change Perl 5 willy-nilly. Yet many people believe that a few carefully-planned backwards-incompatible changes will allow Perl 5 to evolve into a much more powerful, much cleaner, much more understandable, and even much simpler language suitable not only for maintaining legacy projects but also for creating amazing new projects.</p>
<p>I intended my deconstruction of <a href="http://www.modernperlbooks.com/mt/2009/07/fearpm.html">fear surrounding Perl core language changes</a> to continue a long-standing debate. If you read <a href="http://ironman.enlightenedperl.org/">Planet Perl Iron Man</a> or <a href="http://planet.perl.org/">Planet Perl</a>, you've read other people arguing over the desirability of supporting the DarkPAN.</p>
<p>If your code is part of the DarkPAN (and it likely <em>isn't</em>, as you're likely a part of the Perl community if you're reading this), you may bristle at the suggestion that some people believe that retaining core language backwards compatibility to support your code is one of the worst ideas in Perl history. (If you haven't heard that suggestion, let me repeat it: the idea that the Perl community should support hidden and proprietary code of people who aren't part of the community, code that the Perl community can't see let alone test, and code that may or may not even exist is sufficiently ridiculous on its face that it mocks itself.)</p>
<p>Now then.</p>
<p>My previous post suggested that the <em>real</em> problem the Perl community is trying to solve is one of risk management. If it doesn't make sense to push all of the costs to manage the risk that an upgrade might change the way your DarkPAN code behaves to the Perl community (and it doesn't make sense), who bears that cost?</p>
<p>You do.</p>
<p>Don't panic, yet. It's simple to address that risk. I didn't say it's easy. I said it's simple.</p>
<h2><strong>Your Responsibility as a DarkPAN Maintainer</strong></h2>
<p>As a DarkPAN maintainer, you need to answer several questions about your code.</p>
<ul>
<li>Is this software worth maintaining?</li>
<li>Is this software under active maintenance?</li>
<li>Does this software need community support for the Perl core and any external dependencies?</li>
<li>Will this software work unchanged with a newer version of Perl?</li>
<li>If not, why not?</li>
<li>What changes are necessary to make this software work with a newer version of Perl?</li>
</ul>
<p>Software outside of active maintenance can stay untouched. Don't worry about it. (Of course, if you have to migrate to a new machine or a new architecture or other dependencies, it's under active maintenance at least for the sake of this argument.)</p>
<p>The other questions are more important. You need to be able to verify that your code will perform as you expect if you change one or more dependency.</p>
<p>Likely you already need to know this.</p>
<p>You need a comprehensive test suite which can run on any likely candidate machine. You need a test environment where you can run your software's test suite against an updated dependency -- a new CPAN distribution, for example, or a new major release of Perl. You need unambiguous results and comprehensible diagnostics.</p>
<p>In short, you need a sane development environment, just like any serious project worth your time already has.</p>
<p>(You <em>should</em> also have a <a href="http://jamesshore.com/Blog/Living-in-the-Punch-Card-Era.html">ten minute build</a>, but if you can verify that your software does what you expect in an hour or less and report the results to the Perl community, you're well on your way.)</p>
<p>If you're really good, you can even test your DarkPAN code against bleadperl or maintenance snapshots just to help p5p understand your expectations (and to understand potential changes to the language which may require you to revise your expectations, if not your code).</p>
<p>Anyone serious about software development should have a comprehensive and useful test suite anyway. It's simple. It's not always easy; the Perl community needs to make CPAN distribution installation and versioning easier and cleaner. That debate is happening. The solution isn't obvious yet, but a process of iteration and refinement will produce it.</p>
<p>Yet any DarkPAN code of such low importance that its maintainers can't produce a test suite to verify that it works isn't worth p5p's time. Forget that code. It's a dead end. Let's concentrate instead on refining a language for serious software developers to write new code worth maintaining.</p></div>
    </content>
    <category term="darkpan maintenance modern perl perl perl programming software development"/>
    <published>2009-07-04T00:56:30Z</published>
    <updated>2009-07-04T00:56:30Z</updated>
    <author>
      <name>chromatic</name>
    </author>
    <id>tag:perlsphere.net,2006:tag:www.modernperlbooks.com,2009:/mt//1.67</id>
  </entry>
  <entry>
    <title>Bids for YAPC::EU::2010 - Pisa and Kiev!</title>
    <link rel="alternate" href="http://greenokapi.net/blog/2009/07/03/bids-for-yapceu2010-pisa-and-kiev/" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">Organizing a conference is hard, let's go shopping! For the first time
I'm officially helping, not just for the Italian Perl Workshop this year,
but possibly for YAPC::EU::2010 too. I've been working with the perl.it
guys on the proposal to host the European Perl Conference 2010 in Pisa.

We submitted the bid on Monday, and it's just been announced that the
teams competing are: Pisa (us) and Kiev in Ukraine. Wow! YEF have
actually published both our bids on that link, which is fantastic for
transparency.

It also means that we can read their bid... and it's a good one! Looks
like we've got some competition. Of course our Pisa bid is excellent too
- in any case, the next couple of weeks till we find out who won are
going to be a nailbiting time!</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml"><p>Organizing a conference is hard, let's go shopping! For the first time I'm officially helping, not just for the Italian Perl Workshop this year, but possibly for YAPC::EU::2010 too. I've been working with the <a href="http://perl.it/">perl.it</a> guys on the proposal to host the European Perl Conference 2010 in Pisa.</p>
<p>We submitted the bid on Monday, and it's just been <a href="http://www.yapceurope.org/news.html#20090703">announced</a> that the teams competing are: Pisa (us) and Kiev in Ukraine. Wow! YEF have actually published both our bids on that link, which is fantastic for transparency.</p>
<p>It also means that we can read their bid... and it's a good one! Looks like we've got some competition. Of course our Pisa bid is excellent too - in any case, the next couple of weeks till we find out who won are going to be a nailbiting time!</p></div>
    </content>
    <category term="perl .it .ua yapceu"/>
    <published>2009-07-03T19:56:33+01:00</published>
    <updated>2009-07-03T19:56:33+01:00</updated>
    <author>
      <name>osfameron</name>
    </author>
    <id>tag:perlsphere.net,2006:http://greenokapi.net/blog/?p=166</id>
  </entry>
  <entry>
    <title>DateTime::Duration::W3C?</title>
    <link rel="alternate" href="http://use.perl.org/~Ovid/journal/39221?from=rss" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">If this is on the CPAN, please let me know. I can't find it. If not, we
probably need it at work

The W3C duration standard, derived from the ISO 8601 duration standard,
allows one to specify durations in a format like PnYnMnDTnHnMnS (e.g.:
"P1Y2MT2H", a duration of one year, two months and two hours). I can't
find a proper parser for it and it turns out to have some tricky bits.
Basically, I want to do this:

  my $duration = DateTime::Duration::W3C-&gt;new_from_w3c("P1Y2MT2H");

Which would be more or less equivalent to:

  my $duration = DateTime::Duration-&gt;new(
  years  =&gt; 1,
  months =&gt; 2,
  hours  =&gt; 2,
  );

The only real difference would be (I think) adding string overloading to
allow one to print the duration and have it come out in the proper
format.

I can write this and try to handle the special cases I find documented (I'll
be damned if I'm going to pay 130 Swiss Francs for the damned ISO 8601
standard), but I'd love to know if it's already out there.</div>
    </summary>
    <content type="html">&lt;p&gt;If this is on the CPAN, please let me know. I can't find it. If not, we probably need it at work&lt;/p&gt;
&lt;p&gt;The &lt;a href="http://www.w3.org/TR/xmlschema-2/#duration"&gt;W3C duration standard&lt;/a&gt;, derived from the ISO 8601 duration standard, allows one to specify durations in a format like &lt;tt&gt;P&lt;em&gt;n&lt;/em&gt;Y&lt;em&gt;n&lt;/em&gt;M&lt;em&gt;n&lt;/em&gt;DT&lt;em&gt;n&lt;/em&gt;H&lt;em&gt;n&lt;/em&gt;M&lt;em&gt;n&lt;/em&gt;S&lt;/tt&gt; (e.g.: "P1Y2MT2H", a duration of one year, two months and two hours). I can't find a proper parser for it and it turns out to have some tricky bits. Basically, I want to do this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;
&lt;p&gt;&lt;tt&gt;my $duration = DateTime::Duration::W3C-&amp;gt;new_from_w3c("P1Y2MT2H");&lt;/tt&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;p&gt;Which would be more or less equivalent to:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;
&lt;p&gt;&lt;tt&gt;my $duration = DateTime::Duration-&amp;gt;new(&lt;br /&gt;
&amp;nbsp; &amp;nbsp; years&amp;nbsp; =&amp;gt; 1,&lt;br /&gt;
&amp;nbsp; &amp;nbsp; months =&amp;gt; 2,&lt;br /&gt;
&amp;nbsp; &amp;nbsp; hours&amp;nbsp; =&amp;gt; 2,&lt;br /&gt;
);&lt;/tt&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;p&gt;The only real difference would be (I think) adding string overloading to allow one to print the duration and have it come out in the proper format.&lt;/p&gt;
&lt;p&gt;I can write this and try to handle the special cases I find documented (&lt;a href="http://www.iso.org/iso/catalogue_detail?csnumber=40874"&gt;I'll be damned if I'm going to pay 130 Swiss Francs for the damned ISO 8601 standard&lt;/a&gt;), but I'd love to know if it's already out there.&lt;/p&gt;</content>
    <category term="journal"/>
    <published>2009-07-03T13:45:44Z</published>
    <updated>2009-07-03T13:45:44Z</updated>
    <author>
      <name>Ovid</name>
    </author>
    <id>tag:perlsphere.net,2006:http://use.perl.org/~Ovid/journal/39221?from=rss</id>
  </entry>
  <entry>
    <title>Padre::Plugin::WebGUI</title>
    <link rel="alternate" href="http://blog.patspam.com/2009/padrepluginwebgui" type="text/html"/>
    <summary type="text">For a little while now I've been working on a WebGUI plugin for Padre
(the Perl Application Development and Refactoring Environment). Progress
has been pretty slow, partly due to lack of time but also because often
the things I want to do are at the edge of what Padre currently supports
(or just that there's no existing examples of how to do something
easily).

I've released the code onto CPAN, and the current dev version is
available via github, but since it's all a bit hacky and alpha at the
moment I thought it worthwhile doing a little tour of what currently
works (on my dev box at least).


Installation
------------

Installation is the same as any other Padre plugin, either install via
cpan


cpan install Padre::Plugin::WebGUI

or from git:


git clone git://github.com/pdonelan/Padre-Plugin-WebGUI.git

perl Makefile.PL

make &amp;&amp; make test &amp;&amp; make install

Since this is a WebGUI plugin, you need to first install WebGUI, and also
WGDev.

Once you've done that, you will see the WebGUI plugin listed in the Padre
Plugin Manager:

Padre Plugin Manager

Click the enable button, and you'll see a WebGUI item appear in the
Plugin menu.


Controlling WRE Services
------------------------

The first thing you can do with the plugin is control your WRE services
(mysql, modperl, modproxy and spectre).

Click on: WebGUI &gt; WRE Services &gt; Modperl &gt; Restart and you'll see a
restart status message appear in the Padre output panel.

restart-modperl

Currently this is just a simple wrapper around the wreservice.pl script
that ships with WebGUI. A nice enhancement would be to turn the menu item
into a services dashboard with lights telling you which services are
currently running, and buttons to start/stop/restart.


Online Resources
----------------

Another item in the menu called Online Resources gives you access to a
bunch of handy WebGUI links that open in your browser – including one
that takes you straight to a web-based IRC client connected to #webgui.


WebGUI Log
----------

If you click the "Logview" checkbox on the WebGUI menu, a WebGUI Log
panel will open. This panel will start monitoring all of your WRE log
files (webgui.log, modperl.log, modproxy.log, etc..) and display changes
in real-time. WebGUI uses Log4perl as its logging engine, but it uses the
sitename as the Log4perl category, which means that you can't easily e.g.
turn on DEBUG output and filter out everything except the module you're
working on (unless you use my Log4perl::Filter::CallerMatch module). Once
we add in the ability to easily customise what files are being logged and
apply filters to what gets displayed, this will make the above scenario a
breeze.

The logview panel uses a long-running Padre task and File::Tail::select
to continuous monitor a bunch of files in realtime. The main thread
writes commands to a temp file to send commands to the monitoring thread
(the most important command being "exit" which tells the thread to break
out of its monitoring loop!). Later I plan on adding support for other
commands such as "add/remove this file from the list of files you're
watching", "add/remove filter", etc.. Since this seems like a generic
sort of feature I'm hoping to bundle Padre::Plugin::WebGUI::Logview and
Padre::Plugin::WebGUI::Task::Logview as a stand-alone module for other
Padre plugin developers to use (and improve).

logview


Asset Tree
----------

And finally, the coolect feature the WebGUI plugin has is the Asset Tree.

If you turn on the Asset Tree from the plugin menu, a new panel appears
with a "Connect" button on it. Currently this is hardwired to the default
WebGUI dev site at dev.localhost.localdomain but later I plan on adding a
Site Manager to allow you to define sites here.

Double-clicking on the Connect button connects to the site, and pulls
down the asset tree:

asset-tree

This is the same Asset Tree you see when you log in to your WebGUI site
and turn admin mode on. As you can see from the screenshot,
right-clicking on a node brings up a context menu, from which you can do
asset-specific actions. The plugin already gives you access to all of the
WGDev commands from the main plugin menu (with a dialog box asking you
what arguments you want to pass to the command), but it becomes a lot
more useful once you hook these WGDev commands to the Asset Tree context
menu. Then instead of having to remember what url or assetId your asset
has, you can just click through the tree to find the node you want,
right-click and off you go.

For example, WGDev has a package command that lets you package up node
and all of its children into a tarball that can be imported into other
sites, used in upgrade scripts, etc.. By integrating this command into
the context menu, you can have Padre prompt you you for the folder that
you want to save the WebGUI package in (via your native Save File dialog
box).

Similarly, WGDev has an edit command that lets you edit an asset (for
example a template file) via your favourite editor and then have the
changes pushed back into the database after you save and close the file.
By integrating this command into Padre, you could leave the file open,
and push the changes up every time you hit save(allowing for more
convenient continuous editing).</summary>
    <content type="html">&lt;p&gt;For a little while now I've been working on a &lt;a href="http://webgui.org"&gt;WebGUI&lt;/a&gt; plugin for &lt;a href="http://padre.perlide.org"&gt;Padre&lt;/a&gt; (the Perl Application Development and Refactoring Environment). Progress has been pretty slow, partly due to lack of time but also because often the things I want to do are at the edge of what Padre currently supports (or just that there's no existing examples of how to do something easily).&lt;/p&gt;
&lt;p&gt;I've released the code onto &lt;a href="http://search.cpan.org/search?query=Padre%3A%3APlugin%3A%3AWebGUI&amp;amp;mode=all"&gt;CPAN&lt;/a&gt;, and the current dev version is available via &lt;a href="http://github.com/pdonelan/Padre-Plugin-WebGU"&gt;github&lt;/a&gt;, but since it's all a bit hacky and alpha at the moment I thought it worthwhile doing a little tour of what currently works (on my dev box at least).&lt;/p&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;Installation is the same as any other Padre plugin, either install via cpan&lt;/p&gt;
&lt;pre class="brush: bash;"&gt;

cpan install Padre::Plugin::WebGUI
&lt;/pre&gt;
&lt;p&gt;or from git:&lt;/p&gt;
&lt;pre class="brush: bash;"&gt;

git clone git://github.com/pdonelan/Padre-Plugin-WebGUI.git

perl Makefile.PL

make &amp;amp;&amp;amp; make test &amp;amp;&amp;amp; make install
&lt;/pre&gt;
&lt;p&gt;Since this is a WebGUI plugin, you need to first install &lt;a href="http://webgui.org"&gt;WebGUI&lt;/a&gt;, and also &lt;a href="http://github.com/haarg/wgdev"&gt;WGDev&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Once you've done that, you will see the WebGUI plugin listed in the Padre Plugin Manager:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.patspam.com/wp-content/uploads/2009/07/Screenshot-Plugin-Manager.png"&gt;&lt;img src="http://blog.patspam.com/wp-content/uploads/2009/07/Screenshot-Plugin-Manager-300x225.png" alt="Padre Plugin Manager"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Click the enable button, and you'll see a WebGUI item appear in the Plugin menu.&lt;/p&gt;
&lt;h2&gt;Controlling WRE Services&lt;/h2&gt;
&lt;p&gt;The first thing you can do with the plugin is control your WRE services (mysql, modperl, modproxy and spectre).&lt;/p&gt;
&lt;p&gt;Click on: &lt;strong&gt;WebGUI &amp;gt; WRE Services &amp;gt; Modperl &amp;gt; Restart&lt;/strong&gt; and you'll see a restart status message appear in the Padre output panel.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.patspam.com/wp-content/uploads/2009/07/restart-modperl.png"&gt;&lt;img src="http://blog.patspam.com/wp-content/uploads/2009/07/restart-modperl-300x261.png" alt="restart-modperl"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Currently this is just a simple wrapper around the wreservice.pl script that ships with WebGUI. A nice enhancement would be to turn the menu item into a services dashboard with lights telling you which services are currently running, and buttons to start/stop/restart.&lt;/p&gt;
&lt;h2&gt;Online Resources&lt;/h2&gt;
&lt;p&gt;Another item in the menu called &lt;strong&gt;Online Resources&lt;/strong&gt; gives you access to a bunch of handy WebGUI links that open in your browser – including one that takes you straight to a web-based IRC client connected to #webgui.&lt;/p&gt;
&lt;h2&gt;WebGUI Log&lt;/h2&gt;
&lt;p&gt;If you click the "Logview" checkbox on the WebGUI menu, a &lt;strong&gt;WebGUI Log&lt;/strong&gt; panel will open. This panel will start monitoring all of your WRE log files (webgui.log, modperl.log, modproxy.log, etc..) and display changes in real-time. WebGUI uses Log4perl as its logging engine, but it &lt;a href="http://www.plainblack.com/webgui/dev/discuss/log4perl-webgui-custom-filter"&gt;uses the sitename as the Log4perl category&lt;/a&gt;, which means that you can't easily e.g. turn on DEBUG output and filter out everything except the module you're working on (unless you use my &lt;a href="http://github.com/pdonelan/log4perl-filter-callermatch"&gt;Log4perl::Filter::CallerMatch&lt;/a&gt; module). Once we add in the ability to easily customise what files are being logged and apply filters to what gets displayed, this will make the above scenario a breeze.&lt;/p&gt;
&lt;p&gt;The logview panel uses a long-running Padre task and &lt;a href="http://search.cpan.org/~mgrabnar/File-Tail-0.99.3/Tail.pm#select"&gt;File::Tail::select&lt;/a&gt; to continuous monitor a bunch of files in realtime. The main thread writes commands to a temp file to send commands to the monitoring thread (the most important command being "exit" which tells the thread to break out of its monitoring loop!). Later I plan on adding support for other commands such as "add/remove this file from the list of files you're watching", "add/remove filter", etc.. Since this seems like a generic sort of feature I'm hoping to bundle&amp;nbsp; Padre::Plugin::WebGUI::Logview and Padre::Plugin::WebGUI::Task::Logview as a stand-alone module for other Padre plugin developers to use (and improve).&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.patspam.com/wp-content/uploads/2009/07/logview.png"&gt;&lt;img src="http://blog.patspam.com/wp-content/uploads/2009/07/logview-300x230.png" alt="logview"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Asset Tree&lt;/h2&gt;
&lt;p&gt;And finally, the coolect feature the WebGUI plugin has is the Asset Tree.&lt;/p&gt;
&lt;p&gt;If you turn on the Asset Tree from the plugin menu, a new panel appears with a "Connect" button on it. Currently this is hardwired to the default WebGUI dev site at dev.localhost.localdomain but later I plan on adding a Site Manager to allow you to define sites here.&lt;/p&gt;
&lt;p&gt;Double-clicking on the Connect button connects to the site, and pulls down the asset tree:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.patspam.com/wp-content/uploads/2009/07/asset-tree.png"&gt;&lt;img src="http://blog.patspam.com/wp-content/uploads/2009/07/asset-tree-300x184.png" alt="asset-tree"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is the same Asset Tree you see when you log in to your WebGUI site and turn admin mode on. As you can see from the screenshot, right-clicking on a node brings up a context menu, from which you can do asset-specific actions. The plugin already gives you access to all of the WGDev commands from the main plugin menu (with a dialog box asking you what arguments you want to pass to the command), but it becomes a lot more useful once you hook these WGDev commands to the Asset Tree context menu. Then instead of having to remember what url or assetId your asset has, you can just click through the tree to find the node you want, right-click and off you go.&lt;/p&gt;
&lt;p&gt;For example, WGDev has a &lt;strong&gt;package&lt;/strong&gt; command that lets you package up node and all of its children into a tarball that can be imported into other sites, used in upgrade scripts, etc.. By integrating this command into the context menu, you can have Padre prompt you you for the folder that you want to save the WebGUI package in (via your native Save File dialog box).&lt;/p&gt;
&lt;p&gt;Similarly, WGDev has an &lt;strong&gt;edit&lt;/strong&gt; command that lets you edit an asset (for example a template file) via your favourite editor and then have the changes pushed back into the database after you save and close the file. By integrating this command into Padre, you could leave the file open, and push the changes up every time you hit save(allowing for more convenient continuous editing).&lt;/p&gt;</content>
    <category term="Perl WebGUI"/>
    <published>2009-07-03T08:42:06Z</published>
    <updated>2009-07-03T08:42:06Z</updated>
    <author>
      <name>Patrick</name>
    </author>
    <id>tag:perlsphere.net,2006:http://blog.patspam.com/?p=1155</id>
  </entry>
  <entry>
    <title>Coding Horror</title>
    <link rel="alternate" href="http://use.perl.org/~ChrisDolan/journal/39218?from=rss" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">Jeff Atwood is the best tech blogger in the world, in my opinion. And his
most recent post contains my nominee for the quote of the year:

  Open source software only comes in one edition: awesome.</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml"><p>Jeff Atwood is the best tech blogger in the world, in my opinion. And his <a href="http://www.codinghorror.com/blog/archives/001283.html">most recent post</a> contains my nominee for the quote of the year:</p>
<blockquote>
<div>
<p>Open source software only comes in one edition: <em>awesome</em>.</p>
</div>
</blockquote></div>
    </content>
    <category term="journal"/>
    <published>2009-07-03T02:24:36Z</published>
    <updated>2009-07-03T02:24:36Z</updated>
    <author>
      <name>ChrisDolan</name>
    </author>
    <id>tag:perlsphere.net,2006:http://use.perl.org/~ChrisDolan/journal/39218?from=rss</id>
  </entry>
  <entry>
    <title>perl helps save world pandemic</title>
    <link rel="alternate" href="http://jquelin.blogspot.com/2009/07/perl-helps-save-world-pandemic.html" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">ok, maybe the title was a bit too much dramatic - especially in those
days. :-)

i like playing board games, and my wife and i discovered recently
pandemic, from z-man games. it is a tremendous cooperative game, where
players allies to eradicate 4 diseases. but the infections spread out,
and if you aren't fast enough, you end up with a global pandemic - and
loose...

it is really addictive, so i decided to write a perl module
games::pandemic implementing a clone of this board game, with all its
rules. it was also a good occasion to learn moose, dist::zilla and other
modern perl stuff. at least, this goal is already fulfilled! :-)

i'm also using poe and tk (i know, i know). i just published the first
public release, version 0.4.0. it already implements all the player
actions, and here's a snapshot of a game:

of course it isn't finished, but i'm pretty happy of the result (even if
the gui might change in the future). i aim for a v1.0.0 playable alone,
and then allow networked game...

the code is available on github if you want to help - even "only"
translating strings is welcome!

so, expect to hear more about pandemic on this blog. and while waiting
for this perl version to be complete, i recommend you to buy a pandemic
board game: you won't regret it... [IMAGE]</div>
    </summary>
    <content type="text">ok, maybe the title was a bit too much dramatic - especially in those days. :-)&lt;br /&gt;
&lt;br /&gt;
i like playing board games, and my wife and i discovered recently &lt;a href="http://www.zmangames.com/boardgames/pandemic.htm"&gt;pandemic&lt;/a&gt;, from &lt;a href="http://www.zmangames.com/"&gt;z-man games&lt;/a&gt;. it is a tremendous cooperative game, where players allies to eradicate 4 diseases. but the infections spread out, and if you aren't fast enough, you end up with a global pandemic - and loose...&lt;br /&gt;
&lt;br /&gt;
it is really addictive, so i decided to write a perl module &lt;a href="http://search.cpan.org/dist/Games-Pandemic/"&gt;games::pandemic&lt;/a&gt; implementing a clone of this board game, with &lt;a href="http://www.aworldwithoutstring.com/A_World_Without_String/Home/Entries/2008/6/7_Pandemic.html"&gt;all its rules&lt;/a&gt;. it was also a good occasion to learn &lt;a href="http://search.cpan.org/dist/Moose/"&gt;moose&lt;/a&gt;, &lt;a href="http://search.cpan.org/dist/Dist-Zilla/"&gt;dist::zilla&lt;/a&gt; and other modern perl stuff. at least, this goal is &lt;a href="http://jquelin.blogspot.com/search/label/moose"&gt;already&lt;/a&gt; &lt;a href="http://jquelin.blogspot.com/search/label/dzill"&gt;fulfilled&lt;/a&gt;! :-)&lt;br /&gt;
&lt;br /&gt;
i'm also using &lt;a href="http://search.cpan.org/dist/POE/"&gt;poe&lt;/a&gt; and &lt;a href="http://search.cpan.org/dist/Tk/"&gt;tk&lt;/a&gt; (i know, i know). i just published the first public release, version 0.4.0. it already implements all the player actions, and here's a snapshot of a game:&lt;br /&gt;
&lt;a href="http://4.bp.blogspot.com/_qZIpP8ZamQY/SkztELIR4nI/AAAAAAAAAZQ/t2xufxmkjeo/s1600-h/blog.jpg"&gt;&lt;img src="http://4.bp.blogspot.com/_qZIpP8ZamQY/SkztELIR4nI/AAAAAAAAAZQ/t2xufxmkjeo/s320/blog.jpg" alt=""&gt;&lt;/a&gt;&lt;br /&gt;
of course it isn't finished, but i'm pretty happy of the result (even if the gui might change in the future). i aim for a v1.0.0 playable alone, and then allow networked game...&lt;br /&gt;
&lt;br /&gt;
the code is &lt;a href="http://github.com/jquelin/games-pandemic/"&gt;available on github&lt;/a&gt; if you want to help - even "only" translating strings is welcome!&lt;br /&gt;
&lt;br /&gt;
so, expect to hear more about pandemic on this blog. and while waiting for this perl version to be complete, i recommend you to buy a pandemic board game: you won't regret it...
&lt;div class="blogger-post-footer"&gt;&lt;img&gt;&lt;/div&gt;</content>
    <category term="moose games pandemic tk dzill perl poe"/>
    <published>2009-07-02T17:03:00Z</published>
    <updated>2009-07-02T17:03:00Z</updated>
    <author>
      <name>jquelin@gmail.com (Jérôme Quelin)</name>
    </author>
    <id>tag:perlsphere.net,2006:tag:blogger.com,1999:blog-6162910877268067002.post-6915346776850709202</id>
  </entry>
  <entry>
    <title>What is Catalyst, Really?</title>
    <link rel="alternate" href="http://blog.urth.org/2009/07/what-is-catalyst-really.html" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">A recent thread on the Mason users list reminded me of the problems I had
grokking Catalyst when I first looked at it. Raymond Wan wrote "I'm
skimming over the MVC part and as my system doesn't use an SQL database,
I'm wondering if Catalyst is overkill??"

Those of us who know Catalyst know that this question is based on some
wrong assumptions, but it's easy to see why Raymond has those
assumptions. Look at the Catalyst tutorial. In the very first chapter,
it's already talking about databases and DBIx::Class.

It's easy to look at this and assume that Catalyst is somehow tightly
bound to DBIx::Class or SQL databases.

The problem is that the tutorial docs really need to serve two different
audiences, though both audiences are Catalyst newbies.

On the one hand, you have people with relatively little web app
experience. Presumably, they know some Perl, and they do a web search for
"perl web application framework". Eventually, they'll get to Catalyst and
start reading about it. For those people, being given a set of standards
and a full walk through of Model and View (in addition to Controller) is
very valuable. It gives them all the tools they need to get started on
simple web apps without having to make too many choices.

The other audience is people who have some real web app development
experience with something more primitive than Catalyst. These could be
people coming from a Mason-based site without any real controllers, or
people who used something like Apache::Template with mod_perl, or maybe
they wrote their own controllers "by hand" using the mod_perl API.

Many of those folks will already have some experience with models. To
refer back to Raymond, presumably his system already has some sort of
model code, it just doesn't use a SQL DBMS. Those people will look at the
existing Catalyst tutorial and get confused. Isn't Catalyst flexible?
Then why does it look like RoR, with all my tool choices made for me?

It took me a while to realize that Catalyst, at its core, is smaller than
you might think, and you can use just the pieces you like.

The very core of Catalyst is its dispatching system. Given a URI, it
selects a piece of code to run. Its dispatcher is very powerful (Chained
methods are great!), and with plugins like Catalyst::Action::REST, it's
even better.

Along with the dispatching system, Catalyst also provides an abstraction
over the typical web app request/response cycle. The Request makes it
easy to look at incoming query arguments, POST data, file uploads, and
headers. The Response lets you set headers and return output to the
client, whether that be HTML or a downloadable file.

Catalyst also includes engines (think "environment adapters") for a
number of common web application environments, including vanilla CGI,
mod_perl, FastCGI, and more. These engines make sure that the
Request/Response API works exactly the same in any environment where
Catalyst can be deployed.

This is a huge win, since you can write your app without worrying about
the deployment environment. If you're writing an app for public
distribution, it gives the installing users a choice of how to deploy.

These core pieces are really the only parts of Catalyst you have to use
when you use Catalyst. If you don't want dispatch and a request/response
API, you don't want Catalyst.

Catalyst (really Catalyst-Devel) also includes a fantastic single-process
development server. This server can be started straight from an
application's checkout directory with one command. Even better, this dev
server can be told to monitor all relevant files and restart itself when
any of them change. Note that this is a proper restart, which avoids all
the myriad problems that afflict Apache::Reload and its ilk, which
attempt to reload modules in the same Perl interpreter.

Just these things - controllers, a request/response abstraction,
deployment agnosticism, and a great dev environment - are enough to make
Catalyst a great choice. Ignore everything else it does and you'll still
have improved your development process and improved your code.

Catalyst also does some other things ...

It has a component system which has allowed people to release a whole
host of useful plugins. If you look on CPAN, you'll find things like
sessions, powerful authentication, dumb authentication, I18N, and much
more. If a plugin does what you need, it'll save you a lot of development
time.

Note that the old "Catalyst::Plugin" system is in the process of being
deprecated, but the concept of pluggable components is still core to what
Catalyst is. All that's changed is the way pluggability works.

Catalyst lets you have multiple views. While many apps will just output
HTML via a templating system, this flexibility is great for RESTful apps
that may want to output XML, JSON, and still fall back to HTML for
browsers (see my REST-ForBrowsers for some help with that).

Catalyst also has configuration file handling built-in. Personally, I
avoid it, because it only works within the context of the whole "Catalyst
environment". That means it's awkward at best to load the configuration
outside of the web environment. I always make sure that application wide
setting are available for things like cron jobs. This falls into a
category of Catalyst features which are not best practices, but are
probably useful for people writing their first web app.

Catalyst gives you hooks for models. Again, this is something I never
use, but it's another "useful for web app n00bs" feature.

There's probably many other things I've left out. The point is that
Catalyst provides a very powerful set of core web app tools, and that
core is actually small.

Relative to a "my way or the highway" type framework (RoR and Jifty, I'm
looking at you), it's easy to port an existing application to Catalyst.
In fact, using Catalyst::Controller::WrapCGI, you can wrap an existing
CGI application with Catalyst, and then convert slowly over to "native"
controllers.

And most importantly, you can to Catalyst without touching your model at
all! Since many applications have the bulk of their code in the models
(at least, they do if you're doing it right), this is a huge win.

Next step is to turn some of this rambling into doc patches. I think a
section of the Catalyst tutorial aimed at folks coming from an "old
school" web app background would be great, and would really help people
like Raymond (and would've helped me a few years back).</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml"><p>A <a href="http://www.nabble.com/new-Mason-tutorial-to24256045.html">recent thread on the Mason users list</a> reminded me of the problems I had grokking Catalyst when I first looked at it. Raymond Wan wrote "I'm skimming over the MVC part and as my system doesn't use an SQL database, I'm wondering if Catalyst is overkill??"</p>
<p>Those of us who know Catalyst know that this question is based on some wrong assumptions, but it's easy to see why Raymond has those assumptions. Look at the <a href="http://search.cpan.org/~hkclark/Catalyst-Manual-5.8000/lib/Catalyst/Manual/Tutorial/01_Intro.pod">Catalyst tutorial</a>. In the very first chapter, it's already talking about databases and <a href="http://search.cpan.org/dist/DBIx-Class">DBIx::Class</a>.</p>
<p>It's easy to look at this and assume that Catalyst is somehow tightly bound to DBIx::Class or SQL databases.</p>
<p>The problem is that the tutorial docs really need to serve two different audiences, though both audiences are Catalyst newbies.</p>
<p>On the one hand, you have people with relatively little web app experience. Presumably, they know some Perl, and they do a web search for "perl web application framework". Eventually, they'll get to Catalyst and start reading about it. For those people, being given a set of standards and a full walk through of Model and View (in addition to Controller) is very valuable. It gives them all the tools they need to get started on simple web apps without having to make too many choices.</p>
<p>The other audience is people who have some real web app development experience with something more primitive than Catalyst. These could be people coming from a Mason-based site without any real controllers, or people who used something like Apache::Template with mod_perl, or maybe they wrote their own controllers "by hand" using the mod_perl API.</p>
<p>Many of those folks will already have some experience with models. To refer back to Raymond, presumably his system already has some sort of model code, it just doesn't use a SQL DBMS. Those people will look at the existing Catalyst tutorial and get confused. Isn't Catalyst flexible? Then why does it look like RoR, with all my tool choices made for me?</p>
<p>It took me a while to realize that Catalyst, at its core, is smaller than you might think, and you can use just the pieces you like.</p>
<p>The very core of Catalyst is its dispatching system. Given a URI, it selects a piece of code to run. Its dispatcher is very powerful (Chained methods are great!), and with plugins like <a href="http://search.cpan.org/dist/Catalyst-Action-REST">Catalyst::Action::REST</a>, it's even better.</p>
<p>Along with the dispatching system, Catalyst also provides an abstraction over the typical web app request/response cycle. The Request makes it easy to look at incoming query arguments, POST data, file uploads, and headers. The Response lets you set headers and return output to the client, whether that be HTML or a downloadable file.</p>
<p>Catalyst also includes engines (think "environment adapters") for a number of common web application environments, including vanilla CGI, mod_perl, FastCGI, and more. These engines make sure that the Request/Response API works exactly the same in any environment where Catalyst can be deployed.</p>
<p>This is a huge win, since you can write your app without worrying about the deployment environment. If you're writing an app for public distribution, it gives the installing users a choice of how to deploy.</p>
<p>These core pieces are really the only parts of Catalyst you have to use when you use Catalyst. If you don't want dispatch and a request/response API, you don't want Catalyst.</p>
<p>Catalyst (really <a href="http://search.cpan.org/dist/Catalyst-Devel">Catalyst-Devel</a>) also includes a fantastic single-process development server. This server can be started straight from an application's checkout directory with one command. Even better, this dev server can be told to monitor all relevant files and restart itself when any of them change. Note that this is a proper restart, which avoids all the myriad problems that afflict Apache::Reload and its ilk, which attempt to reload modules in the same Perl interpreter.</p>
<p>Just these things - controllers, a request/response abstraction, deployment agnosticism, and a great dev environment - are enough to make Catalyst a great choice. Ignore everything else it does and you'll still have improved your development process and improved your code.</p>
<p>Catalyst also does some other things ...</p>
<p>It has a component system which has allowed people to release a whole host of useful plugins. If you look on CPAN, you'll find things like <a href="http://search.cpan.org/dist/Catalyst-Plugin-Session">sessions</a>, <a href="http://search.cpan.org/dist/Catalyst-Plugin-Authentication">powerful authentication</a>, <a href="http://search.cpan.org/dist/Catalyst-Plugin-AuthenCookie">dumb authentication</a>, <a href="http://search.cpan.org/dist/Catalyst-Plugin-I18N">I18N</a>, and much more. If a plugin does what you need, it'll save you a lot of development time.</p>
<p>Note that the old "Catalyst::Plugin" system is in the process of being deprecated, but the concept of pluggable components is still core to what Catalyst is. All that's changed is the way pluggability works.</p>
<p>Catalyst lets you have multiple views. While many apps will just output HTML via a templating system, this flexibility is great for RESTful apps that may want to output XML, JSON, and still fall back to HTML for browsers (see my <a href="http://search.cpan.org/dist/Catalyst-Request-REST-ForBrowsers">REST-ForBrowsers</a> for some help with that).</p>
<p>Catalyst also has configuration file handling built-in. Personally, I avoid it, because it only works within the context of the whole "Catalyst environment". That means it's awkward at best to load the configuration outside of the web environment. I always make sure that application wide setting are available for things like cron jobs. This falls into a category of Catalyst features which are not best practices, but are probably useful for people writing their first web app.</p>
<p>Catalyst gives you hooks for models. Again, this is something I never use, but it's another "useful for web app n00bs" feature.</p>
<p>There's probably many other things I've left out. The point is that Catalyst provides a very powerful set of core web app tools, and that core is actually small.</p>
<p>Relative to a "my way or the highway" type framework (RoR and Jifty, I'm looking at you), it's easy to port an existing application to Catalyst. In fact, using <a href="http://search.cpan.org/dist/Catalyst-Controller-WrapCGI">Catalyst::Controller::WrapCGI</a>, you can wrap an existing CGI application with Catalyst, and then convert slowly over to "native" controllers.</p>
<p>And most importantly, you can to Catalyst without touching your model at all! Since many applications have the bulk of their code in the models (at least, they do if you're doing it right), this is a huge win.</p>
<p>Next step is to turn some of this rambling into doc patches. I think a section of the Catalyst tutorial aimed at folks coming from an "old school" web app background would be great, and would really help people like Raymond (and would've helped me a few years back).</p></div>
    </content>
    <category term="Programming"/>
    <published>2009-07-02T16:54:32Z</published>
    <updated>2009-07-02T16:54:32Z</updated>
    <author>
      <name>Dave Rolsky</name>
    </author>
    <id>tag:perlsphere.net,2006:tag:blog.urth.org,2009://2.96</id>
  </entry>
  <entry>
    <title>The Real Problem With Roles</title>
    <link rel="alternate" href="http://use.perl.org/~Ovid/journal/39208?from=rss" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">Inheritance, as most of us know, is rather problematic. Specifically,
it's been around since 1967 and for the past 42 years, people have been
arguing about how to do it right. Some OO languages don't have
inheritance (Self, Javascript). Some languages don't have multiple
inheritance (C#, Ruby). Some languages have multiple inheritance with
many safeguards (Eiffel) or none (Perl). Some languages just do strange
things with inheritance (BETA). Even very experienced OO developers
focusing on a single language will argue vociferously about whether or
not a design has been done correctly (do you really give a damn about
strict equivalence in overridden methods?)

The problem is ultimately that classes fulfill conflicting needs. As an
agent of responsibility, a class needs to do everything a class needs to
do. That sounds like a stupid tautology, but what it means is that as
systems grow, classes grow. Thus, classes tend to get larger.
Unfortunately, as agents of code reuse -- via inheritance or delegation
-- classes should be smaller. How many times have you seen (or written)
code which inherits from something because it needs one or two methods
but you're pulling in a lot of extra behavior which you don't need?

This responsibility/reuse tension which leads to classes wanting to be
both larger and smaller at the same time is much of the reason why
inheritance has proven so problematic. Interfaces in Java and C#, along
with mixins in Ruby and other languages were an attempt to decouple the
responsibility and reuse needs of classes, but they've all had their
problems. Roles seem to handle the decoupling of responsilibity and reuse
quite nicely, but some of you may have noticed some of the disagreements
that I and others have had about the proper use of roles. Why is that?

Ultimately, the disagreement boiled down to the fact that -- like
inheritance -- roles serve more than one master. Roles provide behavior
and roles provide an interface. Are we faced with another 40 years of
arguing because we've again tried to shoehorn too much into one thing? I
don't think this need be the case as, unlike classes, the different
things the roles provide aren't necessarily antagonistic, but it would be
nice if the different parties sat down and tried to come up with a
strategy (syntax?) for implementing roles which cleanly addresses these
disparate needs. Otherwise, there really will another 40 years of
arguing.</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml"><p>Inheritance, as most of us know, is rather problematic. Specifically, it's been around since 1967 and for the past 42 years, people have been arguing about how to do it right. Some OO languages don't have inheritance (Self, Javascript). Some languages don't have multiple inheritance (C#, Ruby). Some languages have multiple inheritance with many safeguards (Eiffel) or none (Perl). Some languages just do strange things with inheritance (BETA). Even very experienced OO developers focusing on a single language will argue vociferously about whether or not a design has been done correctly (do you <em>really</em> give a damn about strict equivalence in overridden methods?)</p>
<p>The problem is ultimately that classes fulfill conflicting needs. As an agent of responsibility, a class needs to do everything a class needs to do. That sounds like a stupid tautology, but what it means is that as systems grow, classes grow. Thus, classes tend to get larger. Unfortunately, as agents of code reuse -- via inheritance or delegation -- classes should be smaller. How many times have you seen (or written) code which inherits from something because it needs one or two methods but you're pulling in a lot of extra behavior which you don't need?</p>
<p>This responsibility/reuse tension which leads to classes wanting to be both larger and smaller at the same time is much of the reason why inheritance has proven so problematic. Interfaces in Java and C#, along with mixins in Ruby and other languages were an attempt to decouple the responsibility and reuse needs of classes, but they've all had their problems. Roles seem to handle the decoupling of responsilibity and reuse quite nicely, but some of you may have noticed some of the disagreements that I and others have had about the proper use of roles. Why is that?</p>
<p>Ultimately, the disagreement boiled down to the fact that -- like inheritance -- roles serve more than one master. Roles provide behavior and roles provide an interface. Are we faced with another 40 years of arguing because we've again tried to shoehorn too much into one thing? I don't think this need be the case as, unlike classes, the different things the roles provide aren't necessarily antagonistic, but it would be nice if the different parties sat down and tried to come up with a strategy (syntax?) for implementing roles which cleanly addresses these disparate needs. Otherwise, there really <em>will</em> another 40 years of arguing.</p></div>
    </content>
    <category term="journal"/>
    <published>2009-07-02T13:47:33Z</published>
    <updated>2009-07-02T13:47:33Z</updated>
    <author>
      <name>Ovid</name>
    </author>
    <id>tag:perlsphere.net,2006:http://use.perl.org/~Ovid/journal/39208?from=rss</id>
  </entry>
  <entry>
    <title>Why am I writing Padre?</title>
    <link rel="alternate" href="http://szabgab.com/blog/2009/07/1246515871.html" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">It is probably not that interesting for most of the people but I have my
excuses. What is more interesting - at least to me - is why others are
involved.

After all there were already more than 40 people who made some
contribution to Padre.

So I asked them to start writing down why are they involved. Some of them
have already added themselves to the developers page and we started a
separate page for translators though that one is new and has no been
filled yet.

So why do I write Padre?

There is a short explanation on that page but let me bore you with a
longer one here.

I have been teaching Perl 5 for almost 10 years now. Both beginner level
and advanced courses. In the beginner courses the majority of the people
use Windows with about 20-30 percent using Linux. Most of the Windows
users use Notepad++ or a similar editor. Some of them can configure their
editor to run the perl script right from the editor, others don't even
know how to enable syntax highlighting for Perl 5. Some of the people on
Windows don't know what the command line is but even those who know how
to open the command prompt are either afraid of it or just dislike it.

Mind you these are not stupid people or anything like that. Some of them
have many years of hardware design behind them. They are just used to
some kind of IDEs.

Others might use Linux/Unix but many not by choice. In many cases the
company they are working for gives them telnet access to an oldish Unix
machine and tell them to code in Perl. They hardly know vi, they don't
know how to configure syntax highlighting and they don't know how to
install any other editor.

I have been using vim for many years and I can testify that it is a
superb editor. Emacs is similary strong but I have not used it since
university. The problem with both of them is that they are totally
different from the editors most people are used to and their learning
curve is long and steep. It takes several months or even years to become
familiar with them. Most of the people don't want to invest that energy
and I certainly don't have the time for that in a 4 days long Perl 5
course.

So I usually tell them to use whatever they are familiar with. I think I
never had a student who picked Eclipse or Emacs. There were a few using
vi/vim but most of the people used Notepad++ or a similar Windows based
editor.

I don't think my students are too different from the average people
learning and using Perl. Most of them will never write a full blown web
application. Heck most of them won't have a need for object oriented
coding as they write only 100-200 line long scripts in Perl.

They never get really familiar with Perl and they will always have to
deal with strange code written by others. With all the other tasks they
are required to do in their primary language or tool they will keep
wondering what is $_ when they see it and will be surprised when they
don't.

They will wonder what is the relationship between $_ and $_[0].

So my first objective was to provide a simple Notepad++ like editor with
strong support for beginners or people with relatively little experience
with Perl.

For example I'd like to make sure that Padre users will be able to
highlight $_, press F1 and get an explanation. In case they highlight $_
from a $_[0] expression Padre should be clever enough to point this out
and give an explanation on @_ and @_[0].

I knew it is a big task though I did not think it is soo big. In any case
I knew I cannot handle this alone, especially as I am not such a good
programmer. So from the very beginning I tried to make it interesting,
accessible to experienced Perl 5 developers and in turn they made it fun
and hackable.

Unfortunatelly most of the experienced Perl developers are also hard-core
vim or emacs users and it is nearly impossible to move them away from
their editor. Luckily there were a few who got interested by the idea of
having a lot of control over their editor and that made the difference
between a failing one man project to a project with a lot of potential.

Then at one point came the idea to integrate Parrot and Rakudo and try to
provide a platform for Perl 6 development as well. With the awesome work
of Ahmad M. Zawawi Padre has a lot to offer to anyone who wants to write
Perl 6 code. With some more work we'll be able to integrate Parrot even
better and then Padre will be able to handle any language running on top
of Parrot.

While there are still lots of problems with Padre and installation can
still be difficult it already more or less has the same power as
Notepad++ on both Windows and Linux and probably on Mac too and it has
some extra features that even vim people started to steal.</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml"><p>It is probably not that interesting for most of the people but I have my excuses. What is more interesting - at least to me - is why others are involved.</p>
<p>After all there were already more than 40 people who made some contribution to Padre.</p>
<p>So I asked them to start writing down why are they involved. Some of them have already added themselves to the <a rel="nofollow" target="_blank" href="http://padre.perlide.org/developers.html">developers</a> page and we started a separate page for <a rel="nofollow" target="_blank" href="http://padre.perlide.org/translators.html">translators</a> though that one is new and has no been filled yet.</p>
<p>So why do I write Padre?</p>
<p>There is a short explanation on that page but let me bore you with a longer one here.</p>
<p>I have been teaching Perl 5 for almost 10 years now. Both beginner level and advanced courses. In the beginner courses the majority of the people use Windows with about 20-30 percent using Linux. Most of the Windows users use Notepad++ or a similar editor. Some of them can configure their editor to run the perl script right from the editor, others don't even know how to enable syntax highlighting for Perl 5. Some of the people on Windows don't know what the command line is but even those who know how to open the command prompt are either afraid of it or just dislike it.</p>
<p>Mind you these are not stupid people or anything like that. Some of them have many years of hardware design behind them. They are just used to some kind of IDEs.</p>
<p>Others might use Linux/Unix but many not by choice. In many cases the company they are working for gives them telnet access to an oldish Unix machine and tell them to code in Perl. They hardly know vi, they don't know how to configure syntax highlighting and they don't know how to install any other editor.</p>
<p>I have been using vim for many years and I can testify that it is a superb editor. Emacs is similary strong but I have not used it since university. The problem with both of them is that they are totally different from the editors most people are used to and their learning curve is long and steep. It takes several months or even years to become familiar with them. Most of the people don't want to invest that energy and I certainly don't have the time for that in a 4 days long Perl 5 course.</p>
<p>So I usually tell them to use whatever they are familiar with. I think I never had a student who picked Eclipse or Emacs. There were a few using vi/vim but most of the people used Notepad++ or a similar Windows based editor.</p>
<p>I don't think my students are too different from the average people learning and using Perl. Most of them will never write a full blown web application. Heck most of them won't have a need for object oriented coding as they write only 100-200 line long scripts in Perl.</p>
<p>They never get really familiar with Perl and they will always have to deal with strange code written by others. With all the other tasks they are required to do in their primary language or tool they will keep wondering what is $_ when they see it and will be surprised when they don't.</p>
<p>They will wonder what is the relationship between $_ and $_[0].</p>
<p>So my first objective was to <b>provide a simple Notepad++ like editor with strong support for beginners or people with relatively little experience with Perl</b>.</p>
<p>For example I'd like to make sure that Padre users will be able to highlight $_, press F1 and get an explanation. In case they highlight $_ from a $_[0] expression Padre should be clever enough to point this out and give an explanation on @_ and @_[0].</p>
<p>I knew it is a big task though I did not think it is soo big. In any case I knew I cannot handle this alone, especially as I am not such a good programmer. So from the very beginning I tried to make it <b>interesting, accessible to experienced Perl 5 developers</b> and in turn they made it <b>fun and hackable</b>.</p>
<p>Unfortunatelly most of the experienced Perl developers are also hard-core vim or emacs users and it is nearly impossible to move them away from their editor. Luckily there were a few who got interested by the idea of having a lot of control over their editor and that made the difference between a failing one man project to a project with a lot of potential.</p>
<p>Then at one point came the idea to integrate Parrot and Rakudo and try to provide <b>a platform for Perl 6 development</b> as well. With the awesome work of <a rel="nofollow" target="_blank" href="http://ahmadzawawi.blogspot.com/">Ahmad M. Zawawi</a> Padre has a lot to offer to anyone who wants to write Perl 6 code. With some more work we'll be able to integrate Parrot even better and then Padre will be able to handle any language running on top of Parrot.</p>
<p>While there are still lots of problems with Padre and installation can still be difficult it already more or less has the same power as Notepad++ on both Windows and Linux and probably on Mac too and it has some extra features that even <a rel="nofollow" target="_blank" href="http://code-and-hacks.blogspot.com/2009/06/stealing-from-padre-for-vim.html">vim people started to steal</a>.</p></div>
    </content>
    <published>2009-07-02T02:24:31-07:00</published>
    <updated>2009-07-02T02:24:31-07:00</updated>
    <author>
      <name>nobody</name>
    </author>
    <id>tag:perlsphere.net,2006:ylxaLesS3hGLuL_IPm7D0g_45b4b6805d18507b66173666634273d8</id>
  </entry>
  <entry>
    <title>The impending death of BZip2</title>
    <link rel="alternate" href="http://use.perl.org/~Alias/journal/39206?from=rss" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">  adam@svn:~/svn.ali.as/db$ ls -l
  total 30884
  -rw-r--r-- 1 adam adam 9558294 Jul  2 03:45 cpandb.gz
  -rw-r--r-- 1 adam adam 8538979 Jul  2 03:45 cpandb.bz2
  -rw-r--r-- 1 adam adam 5960155 Jul  2 03:45 cpandb.lz
  -rw-r--r-- 1 adam adam 3014480 Jun 30 06:46 cpanmeta.gz
  -rw-r--r-- 1 adam adam 2658756 Jun 30 06:46 cpanmeta.bz2
  -rw-r--r-- 1 adam adam 1825600 Jun 30 06:46 cpanmeta.lz</div>
    </summary>
    <content type="html">&lt;blockquote&gt;
&lt;div&gt;
&lt;p&gt;&lt;tt&gt;adam@svn:~/svn.ali.as/db$ ls -l&lt;br /&gt;
total 30884&lt;br /&gt;
-rw-r--r-- 1 adam adam 9558294 Jul&amp;nbsp; 2 03:45 cpandb.gz&lt;br /&gt;
-rw-r--r-- 1 adam adam 8538979 Jul&amp;nbsp; 2 03:45 cpandb.bz2&lt;br /&gt;
-rw-r--r-- 1 adam adam 5960155 Jul&amp;nbsp; 2 03:45 cpandb.lz&lt;br /&gt;
-rw-r--r-- 1 adam adam 3014480 Jun 30 06:46 cpanmeta.gz&lt;br /&gt;
-rw-r--r-- 1 adam adam 2658756 Jun 30 06:46 cpanmeta.bz2&lt;br /&gt;
-rw-r--r-- 1 adam adam 1825600 Jun 30 06:46 cpanmeta.lz&lt;/tt&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;</content>
    <category term="journal"/>
    <published>2009-07-02T06:18:57Z</published>
    <updated>2009-07-02T06:18:57Z</updated>
    <author>
      <name>Alias</name>
    </author>
    <id>tag:perlsphere.net,2006:http://use.perl.org/~Alias/journal/39206?from=rss</id>
  </entry>
  <entry>
    <title>Degradable Gists (update)</title>
    <link rel="alternate" href="http://feedproxy.google.com/~r/yuvalkogman/~3/Nb82MBMPhsI/degradable-gists-update.html" type="text/html"/>
    <summary type="text">The good people at GitHub have implemented a JSONP api for Gists, so I
have updated my graceful degarding script accordingly (see previous post).

Now the code no longer needs to hijack document.write and has better load
time characteristics as well. If you use traditional &lt;script&gt; tags then
each gist will block the loading of the page at that point, causing
jittery page renderings, and preventing the rest of the content from
appearing. This script styles the &lt;pre&gt; tags when the DOM becomes ready,
and only fetches the syntax highlighted HTML after the onload event, when
all other page elements have finished loading.

The second new bit is the Perl scripts I've added to streamline working
with these degradable Gists.

The first script is very simple, given a Gist ID it prints out a &lt;pre&gt;
tag suitable for inclusion into your HTML document. For instance
make_pre_tag.pl 115368 outputs:

&lt;pre id="fake-gist-115368" class="fake-gist"&gt;use Moose;
has fun =&amp;gt; ( isa =&amp;gt; &amp;quot;Constant&amp;quot; );&lt;/pre&gt;

The second script, update_gists.pl is much more interesting. It uses
XML::LibXML to find all the pre tags with the class fake-gist in a
document. If these tags have no ID then App::Nopaste is used to create
new Gists. Otherwise AnyEvent::HTTP is used to concurrently fetch the
updated versions from http://gist.github.com/.

I start by editing a plain XHTML document in my editor, adding code in
the &lt;pre&gt; tags, and then I post the code blocks to github all at once. I
use CDATA sections to escape the source code in the XHTML document.

&lt;pre lang="perl" class="fake-gist"&gt;&lt;![CDATA[
$object-&gt;method(
    foo =&gt; $bar, 
);
]]&gt;&lt;/pre&gt;

The script re-escapes that using HTML entities so that it is valid HTML
(which doesn't support CDATA). This way the &lt;pre&gt; tags render fine under
quirks mode, allowing jQuery to append HTML strings to the document.

[IMAGE][IMAGE]</summary>
    <content type="html">&lt;p&gt;The &lt;a href="http://defunkt.github.com/"&gt;good people&lt;/a&gt; at &lt;a href="https://github.com/"&gt;GitHub&lt;/a&gt; have implemented a &lt;a href="http://en.wikipedia.org/wiki/JSON#JSONP"&gt;JSONP&lt;/a&gt; api for &lt;a href="http://gist.github.com/"&gt;Gists&lt;/a&gt;, so I have updated my &lt;a href="http://github.com/nothingmuch/jquery-gist-upgrade"&gt;graceful degarding script&lt;/a&gt; accordingly (see &lt;a href="http://blog.woobling.org/2009/05/graceful-degrading-of-gists.html"&gt;previous post&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Now the code no longer needs to hijack &lt;tt&gt;document.write&lt;/tt&gt; and has better load time characteristics as well. If you use traditional &lt;tt&gt;&amp;lt;script&amp;gt;&lt;/tt&gt; tags then each gist will block the loading of the page at that point, causing jittery page renderings, and preventing the rest of the content from appearing. This script styles the &lt;tt&gt;&amp;lt;pre&amp;gt;&lt;/tt&gt; tags when the DOM becomes ready, and only fetches the syntax highlighted HTML after the &lt;tt&gt;onload&lt;/tt&gt; event, when all other page elements have finished loading.&lt;/p&gt;
&lt;p&gt;The second new bit is the Perl scripts I've added to streamline working with these degradable Gists.&lt;/p&gt;
&lt;p&gt;The first script is very simple, given a Gist ID it prints out a &lt;tt&gt;&amp;lt;pre&amp;gt;&lt;/tt&gt; tag suitable for inclusion into your HTML document. For instance &lt;tt&gt;make_pre_tag.pl 115368&lt;/tt&gt; outputs:&lt;/p&gt;
&lt;pre class="fake-gist" id="fake-gist-139200"&gt;
&amp;lt;pre id="fake-gist-115368" class="fake-gist"&amp;gt;use Moose;
has fun =&amp;amp;gt; ( isa =&amp;amp;gt; &amp;amp;quot;Constant&amp;amp;quot; );&amp;lt;/pre&amp;gt;
&lt;/pre&gt;
&lt;p&gt;The second script, &lt;tt&gt;update_gists.pl&lt;/tt&gt; is much more interesting. It uses &lt;a href="http://search.cpan.org/perldoc?XML%3A%3ALibXML"&gt;&lt;tt&gt;XML::LibXML&lt;/tt&gt;&lt;/a&gt; to find all the &lt;tt&gt;pre&lt;/tt&gt; tags with the class &lt;tt&gt;fake-gist&lt;/tt&gt; in a document. If these tags have no ID then &lt;a href="http://search.cpan.org/perldoc?App%3A%3ANopaste"&gt;&lt;tt&gt;App::Nopaste&lt;/tt&gt;&lt;/a&gt; is used to create new Gists. Otherwise &lt;a href="http://search.cpan.org/perldoc?AnyEvent%3A%3AHTTP"&gt;&lt;tt&gt;AnyEvent::HTTP&lt;/tt&gt;&lt;/a&gt; is used to concurrently fetch the updated versions from &lt;a href="http://gist.github.com/"&gt;http://gist.github.com/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I start by editing a plain XHTML document in my editor, adding code in the &lt;tt&gt;&amp;lt;pre&amp;gt;&lt;/tt&gt; tags, and then I post the code blocks to github all at once. I use &lt;tt&gt;CDATA&lt;/tt&gt; sections to escape the source code in the XHTML document.&lt;/p&gt;
&lt;pre class="fake-gist" id="fake-gist-139202"&gt;
&amp;lt;pre lang="perl" class="fake-gist"&amp;gt;&amp;lt;![CDATA[
$object-&amp;gt;method(
    foo =&amp;gt; $bar, 
);
]]&amp;gt;&amp;lt;/pre&amp;gt;
&lt;/pre&gt;
&lt;p&gt;The script re-escapes that using HTML entities so that it is valid HTML (which doesn't support &lt;tt&gt;CDATA&lt;/tt&gt;). This way the &lt;tt&gt;&amp;lt;pre&amp;gt;&lt;/tt&gt; tags render fine under quirks mode, allowing jQuery to append HTML strings to the document.&lt;/p&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img&gt;&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/yuvalkogman/~4/Nb82MBMPhsI"&gt;</content>
    <category term="jquery github xml perl gist"/>
    <published>2009-07-02T02:08:00Z</published>
    <updated>2009-07-02T02:08:00Z</updated>
    <author>
      <name>nothingmuch</name>
    </author>
    <id>tag:perlsphere.net,2006:tag:blogger.com,1999:blog-876358347971598886.post-1685520250994980699</id>
  </entry>
  <entry>
    <title>Fear.pm</title>
    <link rel="alternate" href="http://www.modernperlbooks.com/mt/2009/07/fearpm.html" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">If you read Planet Perl Iron Man (and you should) or listen to the
discussions of the corehackers project, you may have seen more discussion
about Perl 5's DarkPAN problem.

One of the big tensions in the Perl 5 world is between progress and
stability. (I use both terms with the same sense of distaste I hear the
terms "pro-choice" and "pro-life". Then again, I sympathize with
linguistic prescriptivism, if only to clarify motives and intent.)

"Perl 5 must change," some people cry. "There's no good reason Perl
shouldn't enable strictures and warnings by default for all new
programs!"

"Perl 5 cannot change," retort others. "There's too much existing code to
change Perl's behavior!"

I find the latter argument ridiculous such that withering mockery is the
only good response. That's rarely useful, however.

When people say "Perl 5 cannot change its default behavior!", I believe
they have in mind several other points. Some of them are good points. Yet
until the Perl community as a whole can address those points directly,
we'll remain at an impasse. (The word "impasse" overstates things; to a
man, the active Perl 5 pumpkings appear to hew strongly to the "Change is
painful and bad and wrong" philosophy, even going as far to say that
frequent releases are undesirable hassles because stat calls are not
cheap.)


Translation to English of Various Meanings of "Stability Über Alles"
--------------------------------------------------------------------

With that in mind, here are several possible meanings of "You can't
change default behavior!

  * Distributors may upgrade Perl 5 in their installations and may have
    to upgrade packages which depend on Perl 5 to work with the new
    version. This is true. This is what distributors do. This is what
    distributors do with all of their dependencies. This is why
    distributors exist. This is also only a problem if no optional
    mechanism of disabling new features exists -- and such a feature
    needs to exist.

  * Changing Perl 5's default behavior may render existing tutorials and
    examples obsolete. Good. Many existing examples of Perl 5 code are
    horrible. A steadfast refusal to run unmaintainable code may even
    encourage the creation of better tutorials and the publication of
    better examples.

  * 

    Existing code -- left untouched for a decade -- may suddenly break.

    I don't understand this point.

    I ran into Perl 4 code the other day. Somehow the last sixteen years
    of Perl 5 releases have not yet managed to erase all perl4 binaries
    -- as well as the Perl 4 source code -- from the world's hard drives
    and tape drives and USB drives. Why should anyone believe that Perl
    5.10.0 will not be available when Perl 5.10.1 comes out? Ditto Perl
    5.12.0.

    Sometimes this argument has nuance to it. We must use a version of
    Perl supported by a vendor to whom we offer supplications of fresh
    fruits, wines, native crafts, and large checks. In other words,
    you're paying for the privilege of not upgrading. Good for you. Go
    bug the organization you're paying. That's why you're paying them.

    Sometimes this argument indicates that the arguer has no business
    working with computers in a professional setting. We don't know what
    software we're running and we won't know what will break if we
    upgrade and we don't know how to fix it if it does. If that's you,
    write your stakeholders a letter suggesting that they try to avoid
    upgrading, ever. Then find another line of work, perhaps something
    involving no technology more complex than one rock stacked atop
    another.

    If you can't test your software against newer dependencies, identify
    any potential problems, and work with upstream to resolve those
    issues before you perform an upgrade -- or if you're unwilling to do
    so -- then you are dangerously incompetent. That kind of incompetence
    is not the Perl community's responsibility.

    Don't short your stock, either -- that smacks of insider trading.

  * 

    Frequent, experimental, zig-zag changes to Perl 5 syntax and
    semantics will be confusing! Yeah. That's why no one's suggested
    doing them. Suggesting that Perl 5 could use real function signatures
    or strictures-on-by-default is very different from throwing every
    potential combination of hash-and-array-sort function into one big
    global namespace.

    The desire to add missing features and the desire for more frequent
    releases by no means implies a lack of foresight or holistic design,
    nor a lack of comprehensive testing, nor thoughtful refinement of an
    idea and implementation to the point where it's obviously right.

  * 

    Changes mean bugs, and we can't have bugs! There are already bugs.
    There are already regressions -- including a performance regression
    that would have affected only a few people if a stable 5.10.1 had
    come out in early 2008.

    The only way to avoid bugs altogether is to avoid writing software.
    The best you can do is make them unlikely, catch them early, and fix
    them quickly (remembering that unreleased software may as well not
    exist to your users).

  * It's irresponsible to break someone else's code, especially if you
    can't see it. It's insane to support invisible code that may not even
    exist.

  * There are so many competing implementations of this idea on the CPAN,
    it's obvious there's no one right way to do things! There are so many
    competing implementations of this idea on the CPAN because there's no
    obvious good, default, built-in way to do things.

  * My code has to run on several different major versions of Perl; I
    can't take advantage of these new features. You have a change
    management problem. Not me.

  * I can't show you a test case, but this change breaks my code! There's
    an invisible sign on the road by my house that gives me the right to
    charge a $5 toll. Pay up.

  * This is the way it's always been. How's that working out?


A More Serious Take on Stability
--------------------------------

Change doesn't have to be painful. Change doesn't have to be chaotic.
It's possible to meet many of the real underlying goals with technical
means.

The problem isn't technical, however. It's social. It's fear.

This is the fear of risk -- the risk that unknown problems lurk in
seemingly minor changes. This is also the fear of the risk that the cost
of mitigating this risk is too high. This is especially the fear of the
risk that changing Perl 5 will appear so expensive that people will stop
using it.

With all of that mockery out of the way, perhaps the Perl community can
have a sober assesment of risk, bereft of fears and stupid technical
blatherings that serve only to obscure the real question:

  Whose needs do the features and policies and strategies and goals and
  visions of Perl 5 development serve?

Change for the sake of change itself is useless. Stability for the sake
of stability is equally useless. No one wants complete stability or
complete chaos. (Even if you think you want complete stability, you
don't; when you find a bug or a typo or a confusing section of
documentation, you've found a place where perfect stability gets in your
way.)

(You'd almost think the Perl 5 community didn't have a few experienced
project managers, methodologists, risk managers, and software developers,
if not several thousand people who know how to create, maintain, sustain,
and release free software projects.)

There must be a middle ground. There must be a way to identify real
needs, prioritize useful changes, and deliver those changes to
stakeholders in an efficient and effective fashion. I reject the false
dilemmas which state that we have to make a choice between relentless,
plodding conservatism and Psychotic Hyperactive Purposless-esque
change...

... especially when the alternative is to suggest that every file
containing modern Perl code start with a wall of boilerplate:

use 5.010;

use strict;
use warnings;

use utf8;
use Carp;
use Want;
use CLASS;
use SUPER;
use autodie;
use autobox;
use signatures;

use mro 'c3';

use IO::Handle;
use File::stat;
use autobox::Core;
use UNIVERSAL::ref;

I hate to channel John Stuart Mill, but if Perl 5 stays like that for
long, it won't be a language suitable for novices to write new programs.
It'll be merely a great language to maintain code written in the late
'90s not yet replaced with something with slightly saner defaults.

That would be a pity.</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml"><p>If you read <a href="http://ironman.enlightenedperl.org/">Planet Perl Iron Man</a> (and you should) or listen to the discussions of the <a href="http://sungo.us/archives/2009/06/27/index.html">corehackers</a> project, you may have seen more discussion about <a href="http://www.modernperlbooks.com/mt/2009/02/the-darkpan-dependency-management-and-support-problem.html">Perl 5's DarkPAN problem</a>.</p>
<p>One of the big tensions in the Perl 5 world is between progress and stability. (I use both terms with the same sense of distaste I hear the terms "pro-choice" and "pro-life". Then again, I sympathize with <a href="http://itre.cis.upenn.edu/~myl/languagelog/archives/001732.html">linguistic prescriptivism</a>, if only to clarify motives and intent.)</p>
<p>"Perl 5 must change," some people cry. "There's no good reason Perl shouldn't enable strictures and warnings by default for all new programs!"</p>
<p>"Perl 5 cannot change," retort others. "There's too much existing code to change Perl's behavior!"</p>
<p>I find the latter argument ridiculous such that withering mockery is the only good response. That's rarely useful, however.</p>
<p>When people say "Perl 5 cannot change its default behavior!", I believe they have in mind several other points. Some of them are good points. Yet until the Perl community as a whole can <em>address</em> those points directly, we'll remain at an impasse. (The word "impasse" overstates things; to a man, the active Perl 5 pumpkings appear to hew strongly to the "Change is painful and bad and wrong" philosophy, even going as far to say that <a href="http://groups.google.com/group/perl.perl5.porters/msg/e234c986c6d04661">frequent releases are undesirable hassles because <code>stat</code> calls are not cheap</a>.)</p>
<h2><strong>Translation to English of Various Meanings of "Stability Über Alles"</strong></h2>
<p>With that in mind, here are several possible meanings of "You can't change default behavior!</p>
<ul>
<li><em>Distributors may upgrade Perl 5 in their installations and may have to upgrade packages which depend on Perl 5 to work with the new version.</em> This is true. This is what distributors do. This is what distributors do with all of their dependencies. This is why distributors exist. This is also only a problem if no <em>optional</em> mechanism of disabling new features exists -- and such a feature needs to exist.</li>
<li><em>Changing Perl 5's default behavior may render existing tutorials and examples obsolete</em>. Good. <a href="http://www.modernperlbooks.com/mt/2009/02/the-opposite-of-modern.html">Many existing examples of Perl 5 code are horrible</a>. A steadfast refusal to run unmaintainable code may even encourage the creation of better tutorials and the publication of better examples.</li>
<li>
<p><em>Existing code -- left untouched for a decade -- may suddenly break.</em></p>
<p>I don't understand this point.</p>
<p>I ran into Perl 4 code the other day. Somehow the last sixteen years of Perl 5 releases have not yet managed to erase all <code>perl4</code> binaries -- as well as the Perl 4 source code -- from the world's hard drives and tape drives and USB drives. Why should anyone believe that Perl 5.10.0 will not be available when Perl 5.10.1 comes out? Ditto Perl 5.12.0.</p>
<p>Sometimes this argument has nuance to it. <em>We must use a version of Perl supported by a vendor to whom we offer supplications of fresh fruits, wines, native crafts, and large checks.</em> In other words, you're paying for the privilege of not upgrading. Good for you. Go bug the organization you're paying. That's why you're paying them.</p>
<p>Sometimes this argument indicates that the arguer has no business working with computers in a professional setting. <em>We don't know what software we're running and we won't know what will break if we upgrade and we don't know how to fix it if it does.</em> If that's you, write your stakeholders a letter suggesting that they try to avoid upgrading, <em>ever</em>. Then find another line of work, perhaps something involving no technology more complex than one rock stacked atop another.</p>
<p>If you can't test your software against newer dependencies, identify any potential problems, and work with upstream to resolve those issues before you perform an upgrade -- or if you're unwilling to do so -- then you are dangerously incompetent. That kind of incompetence is not the Perl community's responsibility.</p>
<p>Don't short your stock, either -- that smacks of insider trading.</p>
</li>
<li>
<p><em>Frequent, experimental, zig-zag changes to Perl 5 syntax and semantics will be confusing!</em> Yeah. That's why no one's suggested doing them. Suggesting that Perl 5 could use real function signatures or strictures-on-by-default is very different from throwing every potential combination of hash-and-array-sort function into one big global namespace.</p>
<p>The desire to add missing features and the desire for more frequent releases by no means implies a lack of foresight or holistic design, nor a lack of comprehensive testing, nor thoughtful refinement of an idea and implementation to the point where it's obviously right.</p>
</li>
<li>
<p><em>Changes mean bugs, and we can't have bugs!</em> There are <em>already</em> bugs. There are <em>already</em> regressions -- including <a href="http://www.modernperlbooks.com/mt/2009/06/who-gets-to-criticize-your-free-software-project.html">a performance regression that would have affected only a few people if a stable 5.10.1 had come out in early 2008</a>.</p>
<p>The only way to avoid bugs altogether is to avoid writing software. The best you can do is make them unlikely, catch them early, and fix them quickly (remembering that unreleased software may as well not exist to your users).</p>
</li>
<li><em>It's irresponsible to break someone else's code, especially if you can't see it.</em> It's <em>insane</em> to support invisible code that may not even exist.</li>
<li><em>There are so many competing implementations of this idea on the CPAN, it's obvious there's no one right way to do things!</em> There are so many competing implementations of this idea on the CPAN <em>because</em> there's no obvious good, default, built-in way to do things.</li>
<li><em>My code has to run on several different major versions of Perl; I can't take advantage of these new features.</em> <em>You</em> have a change management problem. Not me.</li>
<li><em>I can't show you a test case, but this change breaks my code!</em> There's an invisible sign on the road by my house that gives me the right to charge a $5 toll. Pay up.</li>
<li><em>This is the way it's always been.</em> How's that working out?</li>
</ul>
<h2><strong>A More Serious Take on Stability</strong></h2>
<p>Change doesn't have to be painful. Change doesn't have to be chaotic. It's possible to meet many of the <em>real</em> underlying goals with technical means.</p>
<p>The problem isn't technical, however. It's social. It's fear.</p>
<p>This is the fear of risk -- the risk that unknown problems lurk in seemingly minor changes. This is also the fear of the risk that the cost of mitigating this risk is too high. This is especially the fear of the risk that changing Perl 5 will appear so expensive that people will stop using it.</p>
<p>With all of that mockery out of the way, perhaps the Perl community can have a sober assesment of risk, bereft of fears and stupid technical blatherings that serve only to obscure the real question:</p>
<blockquote>Whose needs do the features and policies and strategies and goals and visions of Perl 5 development serve?</blockquote>
<p>Change for the sake of change itself is useless. Stability for the sake of stability is equally useless. No one wants complete stability or complete chaos. (Even if you think you want complete stability, you don't; when you find a bug or a typo or a confusing section of documentation, you've found a place where perfect stability gets in your way.)</p>
<p>(You'd almost think the Perl 5 community didn't have a few experienced project managers, methodologists, risk managers, and software developers, if not several thousand people who know how to create, maintain, sustain, and release free software projects.)</p>
<p>There must be a middle ground. There must be a way to identify real needs, prioritize useful changes, and deliver those changes to stakeholders in an efficient and effective fashion. I reject the false dilemmas which state that we have to make a choice between relentless, plodding conservatism and Psychotic Hyperactive Purposless-esque change...</p>
<p>... especially when the alternative is to suggest that every file containing modern Perl code start with a wall of boilerplate:</p>
<pre>
<code>use 5.010;

use strict;
use warnings;

use utf8;
use Carp;
use Want;
use CLASS;
use SUPER;
use autodie;
use autobox;
use signatures;

use mro 'c3';

use IO::Handle;
use File::stat;
use autobox::Core;
use UNIVERSAL::ref;</code>
</pre>
<p>I hate to channel John Stuart Mill, but if Perl 5 stays like that for long, it won't be a language suitable for novices to write new programs. It'll be merely a great language to maintain code written in the late '90s not yet replaced with something with slightly saner defaults.</p>
<p>That would be a pity.</p></div>
    </content>
    <category term="advocacy modern perl perl perl 5i perl programming"/>
    <published>2009-07-01T23:31:55Z</published>
    <updated>2009-07-01T23:31:55Z</updated>
    <author>
      <name>chromatic</name>
    </author>
    <id>tag:perlsphere.net,2006:tag:www.modernperlbooks.com,2009:/mt//1.66</id>
  </entry>
  <entry>
    <title>Updating minicpan alphas more frequently</title>
    <link rel="alternate" href="http://www.dagolden.com/index.php/271/updating-minicpan-alphas-more-frequently/" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">At the Perl QA hackathon, Andreas Koenig, the maintainer of PAUSE,
demonstrated a way to decrease the lag between new distribution uploads
to PAUSE and syndication to CPAN mirrors. (See
File::Rsync::Mirror::Recent on CPAN for details). Running minicpan
against a one of the new, fast updating mirrors results a very fresh
minicpan, but, until now, only for regular releases, not for alpha
development releases.

Last year, I wrote CPAN::Mini::Devel to include development releases in a
minicpan, but it depends on an obscure, large, infrequently updated
index.1 Now, with smaller, fast-updating index files available for rsync,
I released CPAN::Mini::Devel::Recent to take advantage of them for
minicpan as well.

This is all still experimental, but if you do Perl programming and want
bleeding-edge development releases within minutes of their upload to
PAUSE, then find a fast mirror, try out CPAN::Mini::Devel::Recent and let
me know how it works for you. After installation, you can configure it to
be used automatically by adding “class: CPAN::Mini::Devel::Recent” to
your .minicpanrc file.

  1. indices/find-ls.gz</div>
    </summary>
    <content type="html">&lt;p&gt;At the Perl QA hackathon, Andreas Koenig, the maintainer of &lt;a href="http://pause.perl.org/"&gt;PAUSE&lt;/a&gt;, demonstrated a way to decrease the lag between new distribution uploads to PAUSE and syndication to &lt;a href="http://mirrors.cpan.org/"&gt;CPAN mirrors&lt;/a&gt;.&amp;nbsp; (See &lt;a href="http://search.cpan.org/perldoc?File::Rsync::Mirror::Recent"&gt;File::Rsync::Mirror::Recent&lt;/a&gt; on CPAN for details).&amp;nbsp;&amp;nbsp; Running &lt;a href="http://search.cpan.org/perldoc?minicpan"&gt;minicpan&lt;/a&gt; against a one of the new, fast updating mirrors results a very fresh minicpan, but, until now, only for regular releases, not for alpha development releases.&lt;/p&gt;
&lt;p&gt;Last year, I wrote &lt;a href="http://search.cpan.org/perldoc?CPAN::Mini::Devel"&gt;CPAN::Mini::Devel&lt;/a&gt; to include development releases in a minicpan, but it depends on an obscure, large, infrequently updated index.&lt;sup&gt;1&lt;/sup&gt; Now, with smaller, fast-updating index files available for rsync, I released &lt;a href="http://search.cpan.org/perldoc?CPAN::Mini::Devel::Recent"&gt;CPAN::Mini::Devel::Recent&lt;/a&gt; to take advantage of them for minicpan as well.&lt;/p&gt;
&lt;p&gt;This is all still experimental, but if you do Perl programming and want bleeding-edge development releases within minutes of their upload to PAUSE, then find a fast mirror, try out CPAN::Mini::Devel::Recent and let me know how it works for you.&amp;nbsp; After installation, you can configure it to be used automatically by adding “class: CPAN::Mini::Devel::Recent” to your .minicpanrc file.&lt;/p&gt;
&lt;ol class="footnotes"&gt;
&lt;li id="footnote_0_271" class="footnote"&gt;indices/find-ls.gz&lt;/li&gt;
&lt;/ol&gt;</content>
    <category term="cpan perl"/>
    <published>2009-07-01T22:03:34Z</published>
    <updated>2009-07-01T22:03:34Z</updated>
    <author>
      <name>david</name>
    </author>
    <id>tag:perlsphere.net,2006:http://www.dagolden.com/?p=271</id>
  </entry>
  <entry>
    <title>grok 0.09 is out</title>
    <link rel="alternate" href="http://blog.nix.is/grok-009-is-out" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">The code is starting to take a more stable form. I’ve prepended an
underscore to all private/internal subroutines and documented the rest.
Perl authors wishing to use grok’s functionality will now have an easier
time doing so.

I’ve also added various author tests to the distribution to help keep the
code in shape (or at least remind me when it’s not), notably Test::Pod,
Test::Pod::Coverage, and Test::Perl::Critic.

Since my last blog post, grok has gained a few features. It can print the
name of the target file (like perldoc -l), print an index of known
documentation files, output xhtml, and detect whether the target file has
Pod 5 or Pod 6 in it. It’s also got some Win32 fixes and more informative
error messages.

Pretty soon I will start bringing in some more docs to bundle with it.
Tutorials and such. I will also most likely implement function
documentation lookup (like perldoc -f) in grok.</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml"><p>The code is starting to take a more stable form. I’ve prepended an underscore to all private/internal subroutines and documented the rest. Perl authors wishing to use <code>grok</code>’s functionality will now have an easier time doing so.<br/>
<span id="more-206"/><br/>
I’ve also added various author tests to the distribution to help keep the code in shape (or at least remind me when it’s not), notably <code>Test::Pod</code>, <code>Test::Pod::Coverage</code>, and <code>Test::Perl::Critic</code>.</p>
<p>Since my last blog post, <code>grok</code> has gained a few features. It can print the name of the target file (like <code>perldoc -l</code>), print an index of known documentation files, output xhtml, and detect whether the target file has Pod 5 or Pod 6 in it. It’s also got some Win32 fixes and more informative error messages.</p>
<p>Pretty soon I will start bringing in some more docs to bundle with it. Tutorials and such. I will also most likely implement function documentation lookup (like <code>perldoc -f</code>) in grok.</p></div>
    </content>
    <category term="english gsoc perl perl6"/>
    <published>0</published>
    <updated>0</updated>
    <author>
      <name>Hinrik Örn Sigurðsson</name>
    </author>
    <id>tag:perlsphere.net,2006:http://blog.nix.is/?p=206</id>
  </entry>
  <entry>
    <title>PL_runops</title>
    <link rel="alternate" href="http://feedproxy.google.com/~r/yuvalkogman/~3/YP1QW4Yu4bE/plrunops.html" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">I'm going to try to do a series of posts about learning Perl internals. I
am still a beginner, I have trouble remembering the many macros, or
keeping everything in my head all at once, so hopefully I will be able to
make some sense of this stuff in a way that is accessible to other
beginners.

While I'm definitely diving right in to the deep end, I think PL_runops
is a good place to start as any, there's not a lot you need to learn to
see how it works. I don't think Perl has a shallow end.

PL_runops is a variable in the interpreter containing a function pointer,
which in most cases will be Perl_runops_standard.

Perl_runops_standard is the function that executes opcodes in a loop.
Here's how it's defined:

int
Perl_runops_standard(pTHX)
{
    dVAR;
    while ((PL_op = CALL_FPTR(PL_op-&gt;op_ppaddr)(aTHX))) {
        PERL_ASYNC_CHECK();
    }

    TAINT_NOT;
    return 0;
}

Perl makes extensive use of macros, which can sometimes be confusing, but
in this instance it's not too daunting. This loop will essentially keep
calling PL_op-&gt;op_ppaddr, assigning the result to PL_op. As long as a
valid value is returned it will keep executing code.

Just to get it out of the way, PERL_ASYNC_CHEK is a macro that checks to
see if any signals were delivered to the process, and invokes the
handlers in %SIG if necessary.

So what's PL_op? It's essentially Perl's instruction pointer, it refers
to the opcode currently being executed. When Perl compiles source code it
produces an optree. This is probably one of the more complicated
structure in Perl internals, but right now we're only concerned with one
small part, the op_ppaddr field of a single node in the tree. The
op_ppaddr field contains a pointer to the function that implements the
op.

PP stands for push/pop, which means that it's a function that operates in
the context of the Perl stack, pushing and popping items as necessary to
do its work, and returns the next opcode to execute.

pp.h defines a PP macro, which sets up a signature for a function that
returns an op pointer. Let's have a look at two simple PP functions.
First is pp_const:

PP(pp_const)
{
    dVAR;
    dSP;
    XPUSHs(cSVOP_sv);
    RETURN;
}

This is an implementation of the const op, which pushes the value of a
literal constant to the stack. The cSVOP_sv macro is used to get the
actual SV (scalar value structure) of the constant's value from the
optree. SVOP is an OP structure that contains an SV value. The c stands
for "current".

Let's rewrite the body of the macro using some temporary values:

/* the current opcode is op_const, so the op structure is an SVOP
 * Instead of using the long chain of macros we'll put it in a variable */
SVOP *svop = (SVOP *)PL_op; 

/* and then we can simply use the op_sv field, which
 * contains a pointer to a scalar value structure */
SV *sv = svop-&gt;op_sv;

This SV is then pushed onto the stack using the XPUSHs macro. The X in
XPUSHs means that the stack will be extended if necessary, and the s
denotes SV. To read the documentation of these macros, refer to perlapi.

The next thing that executes is the RETURN macro. This macro is defined
in pp.h, along with a few others:

#define RETURN          return (PUTBACK, NORMAL)

#define PUTBACK         PL_stack_sp = sp

/* normal means no special control flow */
#define NORMAL          PL_op-&gt;op_next

/* we'll use this one later: */
#define RETURNOP(o)     return (PUTBACK, o)

Recall that there are no lists in C. The comma operator in C executes its
left side, then its right, and returns that value (unfortunately we have
that in Perl, too). The RETURN macro therefore desugars to something
like:

PL_stack_sp = sp;
return(PL_op-&gt;op_next);

The XPUSHs macro manipulated the local copy of the pointer to the stack,
sp as it was adding our SV. This change is not immediately written to the
actual stack pointer, PL_stack_sp . The PUTBACK macro sets the "real"
stack to the version we've manipulated in the body of our opcode.

Then the opcode simply returns PL_op-&gt;op_next. The op_next field in the
op contains a pointer to the next op that should be executed. In this
case if the code being executed was:

my $x = 42;

then the const op compiled to handle the 42 literal would have pushed an
SV containing the integer 42 onto the stack, and the op_next in this case
is the assignment operator, which will actually use the value.

So, to recap, when PL_op contains a pointer to this const op,
PL_op-&gt;op_ppaddr will contain a pointer to pp_const. PL_runops will call
that function, which in turn will push ((SVOP *)PL_op)-&gt;op_sv onto the
stack, update PL_stack_sp, and return PL_op-&gt;op_next.

At this point runops_standard will assign that value to PL_op, and then
invoke the op_ppaddr of the next opcode (the assignment op).

So far so good?

To spice things up a bit, here's the implementation of logical or (||):

PP(pp_or)
{
    dVAR; dSP;
    if (SvTRUE(TOPs))
        RETURN;
    else {
        if (PL_op-&gt;op_type == OP_OR)
            --SP;
        RETURNOP(cLOGOP-&gt;op_other);
    }
}

The or op is of a different type than the const op. Instead of SVOP it's
a LOGOP, and it doesn't have an op_sv but instead it has an op_other
which contains a pointer to a different branch in the optree.

When pp_or is executed it will look at the value at the top of the stack
using the TOPs macro, and check if it evaluates to a true value using the
SvTRUE macro.

If that's the case it short circuits to op_next using the RETURN macro,
but if it's false it needs to evaluate its right argument.

--SP is used to throw away the argument (so that $a || $b doesn't end up
returning both $a and $b).

Then the RETURNOP macro is used to call PUTBACK, and to return PL_op's
op_other. RETURN is essentialy the same as RETURNOP(NORMAL). op_other
contains a pointer to the op implementing the right branch of the ||,
whereas op_next is the op that will use the value of the || expression.

This is one of the most basic parts of the Perl 5 virtual machine. It's a
stack based machine that roughly follows the threaded code model for its
intermediate code structures.

The data types mostly revolve around the SV data structure, and moving
pointers to SVs from op to op using the stack.

For me the hardest part to learn in Perl is definitely the rich set of
macros, which are almost a language in their own right.

If you search for runops on the CPAN you will find a number of
interesting modules that assign to PL_runops at compile time, overriding
the way opcodes are dispatched.

For more information on Perl internals, the best place to start is
perlguts, and the wonderful perlguts illustrated.

[IMAGE][IMAGE]</div>
    </summary>
    <content type="html">&lt;p&gt;I'm going to try to do a series of posts about learning Perl internals. I am still a beginner, I have trouble remembering the many macros, or keeping everything in my head all at once, so hopefully I will be able to make some sense of this stuff in a way that is accessible to other beginners.&lt;/p&gt;
&lt;p&gt;While I'm definitely diving right in to the deep end, I think &lt;tt&gt;PL_runops&lt;/tt&gt; is a good place to start as any, there's not a lot you need to learn to see how it works. I don't think Perl has a shallow end.&lt;/p&gt;
&lt;p&gt;&lt;tt&gt;PL_runops&lt;/tt&gt; is a variable in the interpreter containing a function pointer, which in most cases will be &lt;tt&gt;Perl_runops_standard&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;&lt;tt&gt;Perl_runops_standard&lt;/tt&gt; is the function that executes opcodes in a loop. Here's how it's defined:&lt;/p&gt;
&lt;pre class="fake-gist" id="fake-gist-139031"&gt;
int
Perl_runops_standard(pTHX)
{
    dVAR;
    while ((PL_op = CALL_FPTR(PL_op-&amp;gt;op_ppaddr)(aTHX))) {
        PERL_ASYNC_CHECK();
    }

    TAINT_NOT;
    return 0;
}
&lt;/pre&gt;
&lt;p&gt;Perl makes extensive use of macros, which can sometimes be confusing, but in this instance it's not too daunting. This loop will essentially keep calling &lt;tt&gt;PL_op-&amp;gt;op_ppaddr&lt;/tt&gt;, assigning the result to &lt;tt&gt;PL_op&lt;/tt&gt;. As long as a valid value is returned it will keep executing code.&lt;/p&gt;
&lt;p&gt;Just to get it out of the way, &lt;tt&gt;PERL_ASYNC_CHEK&lt;/tt&gt; is a macro that checks to see if any signals were delivered to the process, and invokes the handlers in &lt;tt&gt;%SIG&lt;/tt&gt; if necessary.&lt;/p&gt;
&lt;p&gt;So what's &lt;tt&gt;PL_op&lt;/tt&gt;? It's essentially Perl's instruction pointer, it refers to the opcode currently being executed. When Perl compiles source code it produces an optree. This is probably one of the more complicated structure in Perl internals, but right now we're only concerned with one small part, the &lt;tt&gt;op_ppaddr&lt;/tt&gt; field of a single node in the tree. The &lt;tt&gt;op_ppaddr&lt;/tt&gt; field contains a pointer to the function that implements the op.&lt;/p&gt;
&lt;p&gt;&lt;tt&gt;PP&lt;/tt&gt; stands for push/pop, which means that it's a function that operates in the context of the Perl stack, pushing and popping items as necessary to do its work, and returns the next opcode to execute.&lt;/p&gt;
&lt;p&gt;&lt;tt&gt;pp.h&lt;/tt&gt; defines a &lt;tt&gt;PP&lt;/tt&gt; macro, which sets up a signature for a function that returns an op pointer. Let's have a look at two simple &lt;tt&gt;PP&lt;/tt&gt; functions. First is &lt;tt&gt;pp_const&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="fake-gist" id="fake-gist-139032"&gt;
PP(pp_const)
{
    dVAR;
    dSP;
    XPUSHs(cSVOP_sv);
    RETURN;
}
&lt;/pre&gt;
&lt;p&gt;This is an implementation of the &lt;tt&gt;const&lt;/tt&gt; op, which pushes the value of a literal constant to the stack. The &lt;tt&gt;cSVOP_sv&lt;/tt&gt; macro is used to get the actual &lt;tt&gt;SV&lt;/tt&gt; (scalar value structure) of the constant's value from the optree. &lt;tt&gt;SVOP&lt;/tt&gt; is an &lt;tt&gt;OP&lt;/tt&gt; structure that contains an &lt;tt&gt;SV&lt;/tt&gt; value. The &lt;tt&gt;c&lt;/tt&gt; stands for "current".&lt;/p&gt;
&lt;p&gt;Let's rewrite the body of the macro using some temporary values:&lt;/p&gt;
&lt;pre class="fake-gist" id="fake-gist-139033"&gt;
/* the current opcode is op_const, so the op structure is an SVOP
 * Instead of using the long chain of macros we'll put it in a variable */
SVOP *svop = (SVOP *)PL_op; 

/* and then we can simply use the op_sv field, which
 * contains a pointer to a scalar value structure */
SV *sv = svop-&amp;gt;op_sv;
&lt;/pre&gt;
&lt;p&gt;This SV is then pushed onto the stack using the &lt;tt&gt;XPUSHs&lt;/tt&gt; macro. The &lt;tt&gt;X&lt;/tt&gt; in &lt;tt&gt;XPUSHs&lt;/tt&gt; means that the stack will be extended if necessary, and the &lt;tt&gt;s&lt;/tt&gt; denotes &lt;tt&gt;SV&lt;/tt&gt;. To read the documentation of these macros, refer to &lt;a href="http://perldoc.perl.org/perlapi.html"&gt;perlapi&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The next thing that executes is the &lt;tt&gt;RETURN&lt;/tt&gt; macro. This macro is defined in &lt;tt&gt;pp.h&lt;/tt&gt;, along with a few others:&lt;/p&gt;
&lt;pre class="fake-gist" id="fake-gist-139034"&gt;
#define RETURN          return (PUTBACK, NORMAL)

#define PUTBACK         PL_stack_sp = sp

/* normal means no special control flow */
#define NORMAL          PL_op-&amp;gt;op_next

/* we'll use this one later: */
#define RETURNOP(o)     return (PUTBACK, o)
&lt;/pre&gt;
&lt;p&gt;Recall that there are no lists in C. The comma operator in C executes its left side, then its right, and returns that value (unfortunately &lt;a href="http://blog.sartak.org/2009/06/reflections-on-yapcna-2009.html#context"&gt;we have that in Perl&lt;/a&gt;, too). The &lt;tt&gt;RETURN&lt;/tt&gt; macro therefore desugars to something like:&lt;/p&gt;
&lt;pre class="fake-gist" id="fake-gist-139035"&gt;
PL_stack_sp = sp;
return(PL_op-&amp;gt;op_next);
&lt;/pre&gt;
&lt;p&gt;The &lt;tt&gt;XPUSHs&lt;/tt&gt; macro manipulated the local copy of the pointer to the stack, &lt;tt&gt;sp&lt;/tt&gt; as it was adding our SV. This change is not immediately written to the actual stack pointer, &lt;tt&gt;PL_stack_sp&lt;/tt&gt; . The &lt;tt&gt;PUTBACK&lt;/tt&gt; macro sets the "real" stack to the version we've manipulated in the body of our opcode.&lt;/p&gt;
&lt;p&gt;Then the opcode simply returns &lt;tt&gt;PL_op-&amp;gt;op_next&lt;/tt&gt;. The &lt;tt&gt;op_next&lt;/tt&gt; field in the op contains a pointer to the next op that should be executed. In this case if the code being executed was:&lt;/p&gt;
&lt;pre class="fake-gist" id="fake-gist-139036"&gt;
my $x = 42;
&lt;/pre&gt;
&lt;p&gt;then the const op compiled to handle the &lt;tt&gt;42&lt;/tt&gt; literal would have pushed an &lt;tt&gt;SV&lt;/tt&gt; containing the integer 42 onto the stack, and the &lt;tt&gt;op_next&lt;/tt&gt; in this case is the assignment operator, which will actually use the value.&lt;/p&gt;
&lt;p&gt;So, to recap, when &lt;tt&gt;PL_op&lt;/tt&gt; contains a pointer to this const op, &lt;tt&gt;PL_op-&amp;gt;op_ppaddr&lt;/tt&gt; will contain a pointer to &lt;tt&gt;pp_const&lt;/tt&gt;. &lt;tt&gt;PL_runops&lt;/tt&gt; will call that function, which in turn will push &lt;tt&gt;((SVOP *)PL_op)-&amp;gt;op_sv&lt;/tt&gt; onto the stack, update &lt;tt&gt;PL_stack_sp&lt;/tt&gt;, and return &lt;tt&gt;PL_op-&amp;gt;op_next&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;At this point &lt;tt&gt;runops_standard&lt;/tt&gt; will assign that value to &lt;tt&gt;PL_op&lt;/tt&gt;, and then invoke the &lt;tt&gt;op_ppaddr&lt;/tt&gt; of the next opcode (the assignment op).&lt;/p&gt;
&lt;p&gt;So far so good?&lt;/p&gt;
&lt;p&gt;To spice things up a bit, here's the implementation of logical or (&lt;tt&gt;||&lt;/tt&gt;):&lt;/p&gt;
&lt;pre class="fake-gist" id="fake-gist-139037"&gt;
PP(pp_or)
{
    dVAR; dSP;
    if (SvTRUE(TOPs))
        RETURN;
    else {
        if (PL_op-&amp;gt;op_type == OP_OR)
            --SP;
        RETURNOP(cLOGOP-&amp;gt;op_other);
    }
}
&lt;/pre&gt;
&lt;p&gt;The &lt;tt&gt;or&lt;/tt&gt; op is of a different type than the &lt;tt&gt;const&lt;/tt&gt; op. Instead of &lt;tt&gt;SVOP&lt;/tt&gt; it's a &lt;tt&gt;LOGOP&lt;/tt&gt;, and it doesn't have an &lt;tt&gt;op_sv&lt;/tt&gt; but instead it has an &lt;tt&gt;op_other&lt;/tt&gt; which contains a pointer to a different branch in the optree.&lt;/p&gt;
&lt;p&gt;When &lt;tt&gt;pp_or&lt;/tt&gt; is executed it will look at the value at the top of the stack using the &lt;tt&gt;TOPs&lt;/tt&gt; macro, and check if it evaluates to a true value using the &lt;tt&gt;SvTRUE&lt;/tt&gt; macro.&lt;/p&gt;
&lt;p&gt;If that's the case it short circuits to &lt;tt&gt;op_next&lt;/tt&gt; using the &lt;tt&gt;RETURN&lt;/tt&gt; macro, but if it's false it needs to evaluate its right argument.&lt;/p&gt;
&lt;p&gt;&lt;tt&gt;--SP&lt;/tt&gt; is used to throw away the argument (so that &lt;tt&gt;$a || $b&lt;/tt&gt; doesn't end up returning both &lt;tt&gt;$a&lt;/tt&gt; and &lt;tt&gt;$b&lt;/tt&gt;).&lt;/p&gt;
&lt;p&gt;Then the &lt;tt&gt;RETURNOP&lt;/tt&gt; macro is used to call &lt;tt&gt;PUTBACK&lt;/tt&gt;, and to return &lt;tt&gt;PL_op&lt;/tt&gt;'s &lt;tt&gt;op_other&lt;/tt&gt;. &lt;tt&gt;RETURN&lt;/tt&gt; is essentialy the same as &lt;tt&gt;RETURNOP(NORMAL)&lt;/tt&gt;. &lt;tt&gt;op_other&lt;/tt&gt; contains a pointer to the op implementing the right branch of the &lt;tt&gt;||&lt;/tt&gt;, whereas &lt;tt&gt;op_next&lt;/tt&gt; is the op that will use the value of the &lt;tt&gt;||&lt;/tt&gt; expression.&lt;/p&gt;
&lt;p&gt;This is one of the most basic parts of the Perl 5 virtual machine. It's a stack based machine that roughly follows the &lt;a href="http://en.wikipedia.org/wiki/Threaded_code"&gt;threaded code&lt;/a&gt; model for its intermediate code structures.&lt;/p&gt;
&lt;p&gt;The data types mostly revolve around the &lt;tt&gt;SV&lt;/tt&gt; data structure, and moving pointers to &lt;tt&gt;SV&lt;/tt&gt;s from op to op using the stack.&lt;/p&gt;
&lt;p&gt;For me the hardest part to learn in Perl is definitely the rich set of macros, which are almost a language in their own right.&lt;/p&gt;
&lt;p&gt;If you &lt;a href="http://search.cpan.org/search?m=all&amp;amp;q=runops"&gt;search for runops&lt;/a&gt; on the CPAN you will find a number of interesting modules that assign to &lt;tt&gt;PL_runops&lt;/tt&gt; at compile time, overriding the way opcodes are dispatched.&lt;/p&gt;
&lt;p&gt;For more information on Perl internals, the best place to start is &lt;a href="http://perldoc.perl.org/perlguts.html"&gt;perlguts&lt;/a&gt;, and the wonderful &lt;a href="http://www.cpan.org/authors/id/GAAS/illguts-0.09.pdf"&gt;perlguts illustrated&lt;/a&gt;.&lt;/p&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img&gt;&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/yuvalkogman/~4/YP1QW4Yu4bE"&gt;</content>
    <category term="internals c perl"/>
    <published>2009-07-01T19:17:00Z</published>
    <updated>2009-07-01T19:17:00Z</updated>
    <author>
      <name>nothingmuch</name>
    </author>
    <id>tag:perlsphere.net,2006:tag:blogger.com,1999:blog-876358347971598886.post-2319009520838986755</id>
  </entry>
  <entry>
    <title>CPANDB 0.02 - Now we're starting to get somewhere</title>
    <link rel="alternate" href="http://use.perl.org/~Alias/journal/39203?from=rss" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">On the back my my improved and high-coverage CPAN::Mini::Visit and
Archive::* fixes, I've finally managed to build a complete-coverage
version of CPANDB.

CPANDB is a merged and cleaned up schema that combines the CPAN index,
the "CPAN Uploads" database (for PAUSE upload dates), and both class and
distribution level dependency information held in META.yml files
(replacing the CPANTS dependency graph).

To take a look at it, you can grab a copy of the SQLite database directly
from the following URL.

http://svn.ali.as/db/cpandb.gz.

The data sources used to generate it are not perfectly time-synced yet,
so I expect to see a few minor flaws for another release or two. But
compared to everything else available (from pretty much everybody) this
should be a significant improvement.

As well as clearing up the last tiny data quality issues, I'm also yet to
merge in the rt.cpan.org database (which is almost ready) and the CPAN
Ratings database (which is a text file I really don't want to have to
parse).

But don't let this stop you trying it out now (I've appended the schema
to the bottom of this post so you can get a clearer idea of what's in
there).

As usual, feedback is welcome.

CREATE TABLE author (
author TEXT NOT NULL PRIMARY KEY,
name TEXT NOT NULL
);

CREATE TABLE distribution (
distribution TEXT NOT NULL PRIMARY KEY,
version TEXT NULL,
author TEXT NOT NULL,
release TEXT NOT NULL,
uploaded TEXT NOT NULL,
FOREIGN KEY ( author ) REFERENCES author ( author )
);

CREATE TABLE module (
module TEXT NOT NULL PRIMARY KEY,
version TEXT NULL,
distribution TEXT NOT NULL,
FOREIGN KEY ( distribution ) REFERENCES distribution ( distribution )
);

CREATE TABLE requires (
distribution TEXT NOT NULL,
module TEXT NOT NULL,
version TEXT NULL,
phase TEXT NOT NULL,
PRIMARY KEY ( distribution, module, phase ),
FOREIGN KEY ( distribution ) REFERENCES distribution ( distribution ),
FOREIGN KEY ( module ) REFERENCES module ( module )
);

CREATE TABLE dependency (
distribution TEXT NOT NULL,
dependency TEXT NOT NULL,
phase TEXT NOT NULL,
PRIMARY KEY ( distribution, dependency, phase ),
FOREIGN KEY ( distribution ) REFERENCES distribition ( distribution ),
FOREIGN KEY ( dependency ) REFERENCES distribution ( distribution )
);</div>
    </summary>
    <content type="html">&lt;p&gt;On the back my my improved and high-coverage CPAN::Mini::Visit and Archive::* fixes, I've finally managed to build a complete-coverage version of &lt;a href="http://search.cpan.org/perldoc?CPANDB"&gt;CPANDB&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;CPANDB is a merged and cleaned up schema that combines the CPAN index, the "CPAN Uploads" database (for PAUSE upload dates), and both class and distribution level dependency information held in META.yml files (replacing the CPANTS dependency graph).&lt;/p&gt;
&lt;p&gt;To take a look at it, you can grab a copy of the SQLite database directly from the following URL.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://svn.ali.as/db/cpandb.gz"&gt;http://svn.ali.as/db/cpandb.gz&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The data sources used to generate it are not perfectly time-synced yet, so I expect to see a few minor flaws for another release or two. But compared to everything else available (from pretty much everybody) this should be a significant improvement.&lt;/p&gt;
&lt;p&gt;As well as clearing up the last tiny data quality issues, I'm also yet to merge in the rt.cpan.org database (which is almost ready) and the CPAN Ratings database (which is a text file I really don't want to have to parse).&lt;/p&gt;
&lt;p&gt;But don't let this stop you trying it out now (I've appended the schema to the bottom of this post so you can get a clearer idea of what's in there).&lt;/p&gt;
&lt;p&gt;As usual, feedback is welcome.&lt;/p&gt;
&lt;p&gt;CREATE TABLE author (&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; author TEXT NOT NULL PRIMARY KEY,&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; name TEXT NOT NULL&lt;br /&gt;
);&lt;/p&gt;
&lt;p&gt;CREATE TABLE distribution (&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; distribution TEXT NOT NULL PRIMARY KEY,&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; version TEXT NULL,&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; author TEXT NOT NULL,&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; release TEXT NOT NULL,&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; uploaded TEXT NOT NULL,&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; FOREIGN KEY ( author ) REFERENCES author ( author )&lt;br /&gt;
);&lt;/p&gt;
&lt;p&gt;CREATE TABLE module (&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; module TEXT NOT NULL PRIMARY KEY,&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; version TEXT NULL,&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; distribution TEXT NOT NULL,&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; FOREIGN KEY ( distribution ) REFERENCES distribution ( distribution )&lt;br /&gt;
);&lt;/p&gt;
&lt;p&gt;CREATE TABLE requires (&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; distribution TEXT NOT NULL,&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; module TEXT NOT NULL,&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; version TEXT NULL,&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; phase TEXT NOT NULL,&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; PRIMARY KEY ( distribution, module, phase ),&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; FOREIGN KEY ( distribution ) REFERENCES distribution ( distribution ),&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; FOREIGN KEY ( module ) REFERENCES module ( module )&lt;br /&gt;
);&lt;/p&gt;
&lt;p&gt;CREATE TABLE dependency (&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; distribution TEXT NOT NULL,&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; dependency TEXT NOT NULL,&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; phase TEXT NOT NULL,&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; PRIMARY KEY ( distribution, dependency, phase ),&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; FOREIGN KEY ( distribution ) REFERENCES distribition ( distribution ),&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; FOREIGN KEY ( dependency ) REFERENCES distribution ( distribution )&lt;br /&gt;
);&lt;/p&gt;</content>
    <category term="journal"/>
    <published>2009-07-01T17:17:06Z</published>
    <updated>2009-07-01T17:17:06Z</updated>
    <author>
      <name>Alias</name>
    </author>
    <id>tag:perlsphere.net,2006:http://use.perl.org/~Alias/journal/39203?from=rss</id>
  </entry>
  <entry>
    <title>Tech Tip: Finding CPAN Distributions that only have a Build.PL</title>
    <link rel="alternate" href="http://community.livejournal.com/shlomif_tech/28615.html" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">A few times in the past, I wanted to find perl 5 CPAN distributions that
only had a Module-Build-based Build.PL file and not a fallback
Makefile.PL file. Yesterday, after some trial and error, I was able to
formulate Yahoo Search query, to do just that.

Here it is - the shortened URL with a hyperlink to the full one:

http://xrl.us/bezbkx - Yahoo Search to find Build.PL only distributions

It works by looking for specific phrases in the /dist pages, looking for
"Build.PL" and specifically excluding "Makefile.PL". I hereby place this
URL and whatever associated techniques under CC0 / Public Domain. Enjoy!</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml"><p>A few times in the past, I wanted to find perl 5 CPAN distributions that only had a <a href="http://search.cpan.org/dist/Module-Build/">Module-Build</a>-based Build.PL file and not a fallback Makefile.PL file. Yesterday, after some trial and error, I was able to formulate <a href="http://search.yahoo.com/">Yahoo Search</a> query, to do just that.</p>
<p>Here it is - the shortened URL with a hyperlink to the full one:</p>
<p><a href="http://search.yahoo.com/search;_ylt=A0geusbSektKDlEAwnJXNyoA?p=%22Build.PL%22+%22This+Release%22+%22CPAN+Testers%22+-%22Makefile.PL%22+-%22create_makefile_pl%22&amp;y=Search&amp;fr=sfp&amp;vm=p&amp;vs=search.cpan.org&amp;vf=all&amp;fr2=sb-top&amp;sao=0">http://xrl.us/bezbkx - Yahoo Search to find Build.PL only distributions</a></p>
<p>It works by looking for specific phrases in the /dist pages, looking for "Build.PL" and specifically excluding "Makefile.PL". I hereby place this URL and whatever associated techniques under <a href="http://creativecommons.org/license/zero">CC0 / Public Domain</a>. Enjoy!</p></div>
    </content>
    <category term="search tip tech building tech tip extutils-makemaker build.pl perl build module-build yahoo cpan"/>
    <published>2009-07-01T15:27:35Z</published>
    <updated>2009-07-01T15:27:35Z</updated>
    <author>
      <name>shlomif@iglu.org.il (Shlomi Fish)</name>
    </author>
    <id>tag:perlsphere.net,2006:http://community.livejournal.com/shlomif_tech/28615.html</id>
  </entry>
  <entry>
    <title>Test Reporting system: Smolder wish-list</title>
    <link rel="alternate" href="http://szabgab.com/blog/2009/07/1246433080.html" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">I'd like to have a system that can hold all the artifacts of a test
execution and that also knows a lot about TAP. Smolder is a good start as
it knows about TAP but there are tons of other things I'd like to have in
it.

Some of them are hard to add, others are harder.

Anyway, earlier I wrote about Reporting Test Results. Now let me write
about my wish-list:

1) I'd like Smolder to collect all the artifacts of a test run. Look at
the data Buildbot collects or what is collected by the PostgreSQL test
farm! Each run has several stages and the actual test run is only one of
them. In a Test Reporting system I'd like to have access to all the
output and error files of all the stages.

2) The tests might create some additional log files, I'd like to be able
to include those too.

3) One major issue we have is test counting. TAP encourages you to have a
plan - the number of test units you are going to execute in a test run -
so that it can check the number of actually executed test to that number.
Keeping the plan up to date is annoying, people don't like it so many use
no plan. Some TAP producers don't even let you plan ahead (e.g. the ones
I saw in PHP) but I think generally those that are more xUnit like won't
have a test plan.

In larger settings this plan does not even help as it does not provide
any tools to avoid reducing the test plan accidentally along with a
shortcut in the test script: A developer can comment out several tests
temporarily and adjust the plan for the time while he is trying to fix a
bug forgetting to revert these changes after he is done.

Smolder could help a bit here: On the first result report the
administrator of the project should look at the reports and mark them as
having the correct number of tests. Then if Smolder notices a test report
with a different number of test for the same test file it should raise an
alert. The project administrator can examine the change and decided if
that is the new correct number of tests setting the new expected number
to this or if it was changed by mistake.

4) History of unit tests. If we would like to be able to provide a
history based on the actual test units (calls to an ok() function) then
we need to have some unique identifier for each test as we cannot assume
that the test number or the test name will remain the same. After all
people sometimes insert new tests or remove old test at the beginning of
the test scripts and the names can change.

Smolder could also help here too. It could track the test numbers and
test names. If it sees a change it can alert the project administrator
who can then use some GUI to connect the old test units to the new ones.

Both involves some manual work but I think large organizations will be
ready to invest that work in order to get the benefit of greater control
and better reports.

What would you like to have in your test reporting system?</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml"><p>I'd like to have a system that can hold all the artifacts of a test execution and that also knows a lot about TAP. <a rel="nofollow" target="_blank" href="http://cpan.uwinnipeg.ca/dist/Smolder">Smolder</a> is a good start as it knows about TAP but there are tons of other things I'd like to have in it.</p>
<p>Some of them are hard to add, others are harder.</p>
<p>Anyway, earlier I wrote about <a rel="nofollow">Reporting Test Results</a>. Now let me write about my wish-list:</p>
<p>1) I'd like Smolder to <b>collect all the artifacts</b> of a test run. Look at the data <a rel="nofollow" target="_blank" href="http://buildbot.buildbot.net/waterfall">Buildbot</a> collects or what is collected by the <a rel="nofollow" target="_blank" href="http://www.pgbuildfarm.org/cgi-bin/show_status.pl">PostgreSQL test farm</a>! Each run has several stages and the actual test run is only one of them. In a Test Reporting system I'd like to have access to all the output and error files of all the stages.</p>
<p>2) The tests might create some <b>additional log files</b>, I'd like to be able to include those too.</p>
<p>3) One major issue we have is <b>test counting</b>. <a rel="nofollow" target="_blank" href="http://testanything.org/">TAP</a> encourages you to have a plan - the number of test units you are going to execute in a test run - so that it can check the number of actually executed test to that number. Keeping the plan up to date is annoying, people don't like it so many use <i>no plan</i>. Some TAP producers don't even let you plan ahead (e.g. the ones I saw in PHP) but I think generally those that are more xUnit like won't have a test plan.</p>
<p>In larger settings this plan does not even help as it does not provide any tools to avoid reducing the test plan accidentally along with a shortcut in the test script: A developer can comment out several tests temporarily and adjust the plan for the time while he is trying to fix a bug forgetting to revert these changes after he is done.</p>
<p>Smolder could help a bit here: On the first result report the administrator of the project should look at the reports and mark them as having the correct number of tests. Then if Smolder notices a test report with a different number of test for the same test file it should raise an alert. The project administrator can examine the change and decided if that is the new correct number of tests setting the new expected number to this or if it was changed by mistake.</p>
<p>4) <b>History of unit tests</b>. If we would like to be able to provide a history based on the actual test units (calls to an ok() function) then we need to have some unique identifier for each test as we cannot assume that the test number or the test name will remain the same. After all people sometimes insert new tests or remove old test at the beginning of the test scripts and the names can change.</p>
<p>Smolder could also help here too. It could track the test numbers and test names. If it sees a change it can alert the project administrator who can then use some GUI to connect the old test units to the new ones.</p>
<p>Both involves some manual work but I think large organizations will be ready to invest that work in order to get the benefit of greater control and better reports.</p>
<p>What would you like to have in your test reporting system?</p></div>
    </content>
    <published>2009-07-01T03:24:40-07:00</published>
    <updated>2009-07-01T03:24:40-07:00</updated>
    <author>
      <name>nobody</name>
    </author>
    <id>tag:perlsphere.net,2006:ylxaLesS3hGLuL_IPm7D0g_d8203c9e2d9fee44ec9a978aea201e3f</id>
  </entry>
  <entry>
    <title>Autodie 2.00 released</title>
    <link rel="alternate" href="http://pjf.id.au/blog/?position=577" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">Autodie 2.00 released
This weekend the long awaited autodie 2.00 for Perl was released to the
CPAN, which was almost immediately replaced by 2.02, which fixes some
oopsed tests and which adds a couple more features to give us a really
sweet experience. This blog entry assumes you're using 2.02.

Observant viewers will notice that the major version number has changed.
I've taken the great leap from 1.999 to 2.00. Clearly, something is
different, and you might be wondering what.

Well, autodie 2.0 now supports a hinting interface for user-defined
subroutines. Put simply, if you have a user-defined subroutine that does
something funny to signify failure, you can now tell autodie about that.
Once it knows, it can Do The Right Thing when checking your subroutine.
You can even put the hints into the same file as those subs, and if
someone is using autodie 2.00, it will find the hints and use them.

This may not sound very exciting, but it is. It means that a lot of
really ugly error-checking code, both on the CPAN and the DarkPAN, can go
away. Lexically. Still not convinced this will change your life? Let's
look a little more closely; trust me, you'll like it.

Let's pretend you're working on a piece of legacy code. For some reason,
the people who wrote this code decided the best way to signal errors is
by returning the list (undef, "Error message"). I don't know why, but
I've seen this anti-pattern emerge independently in three 100k+ line
projects I've been involved in.

sub some_sub {
    if ( not batteries_full() ) {
        return ( undef, "insufficient energy" );
    }

    if ( not coin_inserted() ) {
        return ( undef, "insufficient credit" );
    }

    my @results = some_calculation();

    return @results;
}

If you want to check to see if some_sub() returns an error, you need to
capture its return values, look at the first one to see if it's
undefined, and if it's not, use the second one as your error. At least,
that's what you're supposed to do.

What actually happens is most developers decide that's way too hard, and
don't bother checking for errors. Then one day, the batteries on your
doomsday-asteroid-destroying-satellite go flat, nobody notices, and
through an ironic twist of fate you're left as the last known human
survivor, and there are zombie hordes and walking killer plants outside.

So, how can autodie help us? Well, before version 2.00, it couldn't. But
now, with autodie::hints, it can! We can give autodie hints about how the
return values are checked. They look like this:

use autodie::hints;

autodie::hints-&gt;set_hints_for(
    'Some::Package::some_sub' =&gt; {
        scalar =&gt; sub { 1 },
        list   =&gt; sub { @_ == 2 and not defined $_[0] },
    },
);

Our hints here are simple subroutines. If they return true, our
subroutine has failed. If they return false, it's executed successfully.
Notice that our scalar hint always returns true. That's because we
consider any call of our subroutine in scalar context to be a mistake.
It's returning a list of values, and you should be checking that list.

Once we've set our hints, we can then use autodie to automatically check
if we're successful:

use Some::Module qw(some_sub);

sub target_asteroid {

    use autodie qw( ! some_sub );

    # autodie has lexical scope, so only calls to some_sub inside
    # the target_asteroid subroutine are affected.

    my @results = some_sub();     # Succeeds or dies
}

sub target_ufo {
    my @results = some_sub();

    # autodie is out of lexical scope, so we have to manually
    # process @results here.
}


If you're wondering what that exclamation mark means, it means "insist on
hints", and is a new piece of syntax with autodie 2.00. If for any reason
autodie can't find the hints for some_sub, our code won't compile. That's
a very good thing, and avoids us having a false sense of security if we
use autodie on an unhinted sub.

However the error messages from autodie aren't really that useful.
They're going to be things like "Can't some_sub() at space_defense.pl
line 53". There's a noticable lack of explanation as to why some_sub()
failed.

Luckily, since the way early versions of autodie, we've been able to
register message handlers. And with the new features in autodie 2.02, we
can produce very rich messages. Let's see how!

use autodie::exception;

autodie::exception-&gt;register(
    'Some::Module::some_sub' =&gt; sub {
        my ($error) = @_;

        if ($error-&gt;context eq "scalar") {
             return "some_sub() can't be called in a scalar context";
        }

        # $error-&gt;return gives a list of everything our failed sub
        # returned.  We know this particular sub puts the error
        # message the second argument (index 1).

        my $error_msg = $error-&gt;return-&gt;[1];

        return "some_sub() failed: $error_msg";
    }
);

Now, whenever some_sub() fails, it'll print a genuinely useful message,
like "some_sub() failed: Insufficient energy at space_defense.pl line 53".
Yes, autodie automatically adds the file and line number for you. Nice!

But wait, there's more! We don't want to see this sort of code floating
around in your programs. You may be dealing with other people's modules
that you can't modify, so we can't hide all this configuration in there.
So, we can write our own pragma that contains all this info. Here's the
full code for a theoretical my::autodie pragma, and is the exact same
code used by the t/blog_hints.t file in autodie's test suite.

package my::autodie;
use strict;
use warnings;

use base qw(autodie);
use autodie::exception;
use autodie::hints;

autodie::hints-&gt;set_hints_for(
    'Some::Module::some_sub' =&gt; {
        scalar =&gt; sub { 1 },
        list   =&gt; sub { @_ == 2 and not defined $_[0] }
    },
);

autodie::exception-&gt;register(
    'Some::Module::some_sub' =&gt; sub {
        my ($E) = @_;

        if ($E-&gt;context eq "scalar") {
            return "some_sub() can't be called in scalar context";
        }

        my $error = $E-&gt;return-&gt;[1];

        return "some_sub() failed: $error";
    }
);

1;

It works exactly the same as regular autodie, except it also knows how to
handle some_sub(), and display good looking error messages. Here's how
we'd use it:

use Some::Module qw(some_sub);
use my::autodie qw( ! some_sub );

my @results = some_sub();  # Succeeds or dies with a useful error!

There's a lot more you can do with autodie, and if you want to learn
more, I'd suggest coming to my talk at OSCON or YAPC::EU, where I'll be
covering all this and more, with a distinctive Star Trek twist. ;)

Posted: 1st July 2009.

Tags: autodie hints perl

Bookmark:

Digg this Digg this</div>
    </summary>
    <content type="html">&lt;p&gt;&lt;b&gt;Autodie 2.00 released&lt;/b&gt;&lt;br /&gt;
This weekend the long awaited &lt;a href="http://search.cpan.org/perldoc?autodie"&gt;autodie 2.00&lt;/a&gt; for Perl was released to the CPAN, which was almost immediately replaced by 2.02, which fixes some oopsed tests and which adds a couple more features to give us a really sweet experience. This blog entry assumes you're using 2.02.&lt;/p&gt;
&lt;p&gt;Observant viewers will notice that the major version number has changed. I've taken the great leap from 1.999 to 2.00. Clearly, something is different, and you might be wondering what.&lt;/p&gt;
&lt;p&gt;Well, autodie 2.0 now supports a &lt;a href="http://search.cpan.org/perldoc?autodie::hints"&gt;hinting interface&lt;/a&gt; for user-defined subroutines. Put simply, if you have a user-defined subroutine that does something funny to signify failure, you can now tell autodie about that. Once it knows, it can Do The Right Thing when checking your subroutine. You can even put the hints into the same file as those subs, and if someone is using autodie 2.00, it will find the hints and use them.&lt;/p&gt;
&lt;p&gt;This may not sound very exciting, but it is. It means that a lot of really ugly error-checking code, both on the CPAN and the DarkPAN, can go away. Lexically. Still not convinced this will change your life? Let's look a little more closely; trust me, you'll like it.&lt;/p&gt;
&lt;p&gt;Let's pretend you're working on a piece of legacy code. For some reason, the people who wrote this code decided the best way to signal errors is by returning the list &lt;tt&gt;(undef, "Error message")&lt;/tt&gt;. I don't know why, but I've seen this anti-pattern emerge independently in &lt;i&gt;three&lt;/i&gt; 100k+ line projects I've been involved in.&lt;/p&gt;
&lt;pre&gt;
sub some_sub {
    if ( not batteries_full() ) {
        return ( undef, "insufficient energy" );
    }

    if ( not coin_inserted() ) {
        return ( undef, "insufficient credit" );
    }

    my @results = some_calculation();

    return @results;
}
&lt;/pre&gt;
&lt;p&gt;If you want to check to see if &lt;tt&gt;some_sub()&lt;/tt&gt; returns an error, you need to capture its return values, look at the first one to see if it's undefined, and if it's not, use the second one as your error. At least, that's what you're &lt;i&gt;supposed&lt;/i&gt; to do.&lt;/p&gt;
&lt;p&gt;What actually happens is most developers decide that's way too hard, and don't bother checking for errors. Then one day, the batteries on your doomsday-asteroid-destroying-satellite go flat, nobody notices, and through an ironic twist of fate you're left as the last known human survivor, and there are zombie hordes and walking killer plants outside.&lt;/p&gt;
&lt;p&gt;So, how can &lt;a href="http://search.cpan.org/perldoc?autodie"&gt;autodie&lt;/a&gt; help us? Well, before version 2.00, it couldn't. But now, with &lt;a href="http://search.cpan.org/perldoc?autodie::hints"&gt;autodie::hints&lt;/a&gt;, it can! We can give autodie hints about how the return values are checked. They look like this:&lt;/p&gt;
&lt;pre&gt;
use autodie::hints;

autodie::hints-&amp;gt;set_hints_for(
    'Some::Package::some_sub' =&amp;gt; {
        scalar =&amp;gt; sub { 1 },
        list   =&amp;gt; sub { @_ == 2 and not defined $_[0] },
    },
);
&lt;/pre&gt;
&lt;p&gt;Our hints here are simple subroutines. If they return true, our subroutine has failed. If they return false, it's executed successfully. Notice that our scalar hint always returns true. That's because we consider any call of our subroutine in scalar context to be a mistake. It's returning a list of values, and you should be checking that list.&lt;/p&gt;
&lt;p&gt;Once we've set our hints, we can then use autodie to automatically check if we're successful:&lt;/p&gt;
&lt;pre&gt;
use Some::Module qw(some_sub);

sub target_asteroid {

    use autodie qw( ! some_sub );

    # autodie has lexical scope, so only calls to some_sub inside
    # the target_asteroid subroutine are affected.

    my @results = some_sub();     # Succeeds or dies
}

sub target_ufo {
    my @results = some_sub();

    # autodie is out of lexical scope, so we have to manually
    # process @results here.
}

&lt;/pre&gt;
&lt;p&gt;If you're wondering what that exclamation mark means, it means "insist on hints", and is a new piece of syntax with autodie 2.00. If for any reason autodie can't find the hints for &lt;tt&gt;some_sub&lt;/tt&gt;, our code won't compile. That's a very good thing, and avoids us having a false sense of security if we use autodie on an unhinted sub.&lt;/p&gt;
&lt;p&gt;However the error messages from autodie aren't really that useful. They're going to be things like &lt;tt&gt;"Can't some_sub() at space_defense.pl line 53"&lt;/tt&gt;. There's a noticable lack of explanation as to why &lt;tt&gt;some_sub()&lt;/tt&gt; failed.&lt;/p&gt;
&lt;p&gt;Luckily, since the way early versions of autodie, we've been able to register message handlers. And with the new features in autodie 2.02, we can produce very rich messages. Let's see how!&lt;/p&gt;
&lt;pre&gt;
use autodie::exception;

autodie::exception-&amp;gt;register(
    'Some::Module::some_sub' =&amp;gt; sub {
        my ($error) = @_;

        if ($error-&amp;gt;context eq "scalar") {
             return "some_sub() can't be called in a scalar context";
        }

        # $error-&amp;gt;return gives a list of everything our failed sub
        # returned.  We know this particular sub puts the error
        # message the second argument (index 1).

        my $error_msg = $error-&amp;gt;return-&amp;gt;[1];

        return "some_sub() failed: $error_msg";
    }
);
&lt;/pre&gt;
&lt;p&gt;Now, whenever &lt;tt&gt;some_sub()&lt;/tt&gt; fails, it'll print a genuinely useful message, like &lt;tt&gt;"some_sub() failed: Insufficient energy at space_defense.pl line 53"&lt;/tt&gt;. Yes, autodie automatically adds the file and line number for you. Nice!&lt;/p&gt;
&lt;p&gt;But wait, there's more! We don't want to see this sort of code floating around in your programs. You may be dealing with other people's modules that you can't modify, so we can't hide all this configuration in there. So, we can &lt;i&gt;write our own pragma&lt;/i&gt; that contains all this info. Here's the full code for a theoretical &lt;tt&gt;my::autodie&lt;/tt&gt; pragma, and is the exact same code used by the &lt;tt&gt;t/blog_hints.t&lt;/tt&gt; file in autodie's test suite.&lt;/p&gt;
&lt;pre&gt;
package my::autodie;
use strict;
use warnings;

use base qw(autodie);
use autodie::exception;
use autodie::hints;

autodie::hints-&amp;gt;set_hints_for(
    'Some::Module::some_sub' =&amp;gt; {
        scalar =&amp;gt; sub { 1 },
        list   =&amp;gt; sub { @_ == 2 and not defined $_[0] }
    },
);

autodie::exception-&amp;gt;register(
    'Some::Module::some_sub' =&amp;gt; sub {
        my ($E) = @_;

        if ($E-&amp;gt;context eq "scalar") {
            return "some_sub() can't be called in scalar context";
        }

        my $error = $E-&amp;gt;return-&amp;gt;[1];

        return "some_sub() failed: $error";
    }
);

1;
&lt;/pre&gt;
&lt;p&gt;It works exactly the same as regular autodie, except it also knows how to handle &lt;tt&gt;some_sub()&lt;/tt&gt;, and display good looking error messages. Here's how we'd use it:&lt;/p&gt;
&lt;pre&gt;
use Some::Module qw(some_sub);
use my::autodie qw( ! some_sub );

my @results = some_sub();  # Succeeds or dies with a useful error!
&lt;/pre&gt;
&lt;p&gt;There's a lot more you can do with autodie, and if you want to learn more, I'd suggest coming to my talk at &lt;a href="http://en.oreilly.com/oscon2009/public/schedule/detail/8165"&gt;OSCON&lt;/a&gt; or &lt;a href="http://yapceurope2009.org/ye2009/talk/2063"&gt;YAPC::EU&lt;/a&gt;, where I'll be covering all this and more, with a distinctive Star Trek twist. ;)&lt;/p&gt;
&lt;p&gt;Posted: 1st July 2009.&lt;/p&gt;
&lt;p&gt;Tags: &lt;a href="http://pjf.id.au/blog/toc.html?tag=autodie" rel="tag"&gt;autodie&lt;/a&gt; &lt;a href="http://pjf.id.au/blog/toc.html?tag=hints" rel="tag"&gt;hints&lt;/a&gt; &lt;a href="http://pjf.id.au/blog/toc.html?tag=perl" rel="tag"&gt;perl&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Bookmark:&lt;/p&gt;
&lt;a href="http://digg.com/submit?phase=2&amp;amp;url=http%3A%2F%2Fpjf.id.au%2Fblog%2F%3Fposition%3D577&amp;amp;title=Autodie%202.00%20released"&gt;&lt;img src="http://pjf.id.au/images/icons/digg.png" alt="Digg this"&gt;&lt;/a&gt; &lt;a href="http://www.technorati.com/faves?add=http%3A%2F%2Fpjf.id.au%2Fblog%2F%3Fposition%3D577"&gt;&lt;img src="http://pjf.id.au/images/icons/technorati.png" alt="Digg this"&gt;&lt;/a&gt;</content>
    <published>2009-07-01T00:00:00Z</published>
    <updated>2009-07-01T00:00:00Z</updated>
    <author>
      <name>nobody</name>
    </author>
    <id>tag:perlsphere.net,2006:http://pjf.id.au/blog/?position=577</id>
  </entry>
  <entry>
    <title>Calling All Test:: Authors</title>
    <link rel="alternate" href="http://use.perl.org/~Ovid/journal/39193?from=rss" type="text/html"/>
    <summary type="text">The latest developer release of Test::More allows subtests. Subtests are
great in that they solve a lot of problems in advanced Perl testing, but
they have required a change in Test::Builder. Previously you could do
stuff like this:

  package Test::StringReverse;

  use base 'Test::Builder::Module';
  our @EXPORT = qw(is_reversed);

  my $BUILDER = Test::Builder-&gt;new;

  sub is_reversed ($$;$) {
  my ( $have, $want, $name ) = @_;

  my $passed = $want eq scalar reverse $name;

  $BUILDER-&gt;ok($passed, $name);
  $BUILDER-&gt;diag(&lt;&lt;"  END_DIAG") if not $passed;
  have: $have
  want: $want
  END_DIAG

  return $passed;
  }

  1;

And you've have a simple (untested ;) test for whether or not strings are
reversed.

The reason that worked is that Test::Builder-&gt;new used to return a
singleton. This is no longer true. If someone uses your test library in a
subtest, the above code would break. Instead, you want to do this:

  sub is_reversed ($$;$) {
  my ( $have, $want, $name ) = @_;

  my $passed  = $want eq scalar reverse $name;
  my $builder = __PACKAGE__-&gt;builder;

  $builder-&gt;ok($passed, $name);
  $builder-&gt;diag(&lt;&lt;"  END_DIAG") if not $passed;
  have: $have
  want: $want
  END_DIAG

  return $passed;
  }

It's a minor change, it's completely backwards-compatible and it supports
subtests. There's a work-around being planned, but it's not out there
yet.</summary>
    <content type="html">&lt;p&gt;The latest developer release of &lt;a href="http://search.cpan.org/dist/Test-Simple/"&gt;Test::More&lt;/a&gt; allows subtests. Subtests are great in that they solve a lot of problems in advanced Perl testing, but they have required a change in &lt;a href="http://search.cpan.org/dist/Test-Simple/lib/Test/Builder.pm"&gt;Test::Builder&lt;/a&gt;. Previously you could do stuff like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;
&lt;p&gt;&lt;tt&gt;package Test::StringReverse;&lt;br /&gt;
&lt;br /&gt;
use base 'Test::Builder::Module';&lt;br /&gt;
our @EXPORT = qw(is_reversed);&lt;br /&gt;
&lt;br /&gt;
my $BUILDER = Test::Builder-&amp;gt;new;&lt;br /&gt;
&lt;br /&gt;
sub is_reversed ($$;$) {&lt;br /&gt;
&amp;nbsp; &amp;nbsp; my ( $have, $want, $name ) = @_;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; my $passed = $want eq scalar reverse $name;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; $BUILDER-&amp;gt;ok($passed, $name);&lt;br /&gt;
&amp;nbsp; &amp;nbsp; $BUILDER-&amp;gt;diag(&amp;lt;&amp;lt;"&amp;nbsp; &amp;nbsp; END_DIAG") if not $passed;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; have: $have&lt;br /&gt;
&amp;nbsp; &amp;nbsp; want: $want&lt;br /&gt;
&amp;nbsp; &amp;nbsp; END_DIAG&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; return $passed;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
1;&lt;/tt&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;p&gt;And you've have a simple (untested &lt;nobr&gt;&lt;wbr /&gt;&lt;/nobr&gt;;) test for whether or not strings are reversed.&lt;/p&gt;
&lt;p&gt;The reason that worked is that &lt;tt&gt;Test::Builder-&amp;gt;new&lt;/tt&gt; used to return a singleton. This is no longer true. If someone uses your test library in a subtest, the above code would break. Instead, you want to do this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;
&lt;p&gt;&lt;tt&gt;sub is_reversed ($$;$) {&lt;br /&gt;
&amp;nbsp; &amp;nbsp; my ( $have, $want, $name ) = @_;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; my $passed&amp;nbsp; = $want eq scalar reverse $name;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; my $builder = __PACKAGE__-&amp;gt;builder;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; $builder-&amp;gt;ok($passed, $name);&lt;br /&gt;
&amp;nbsp; &amp;nbsp; $builder-&amp;gt;diag(&amp;lt;&amp;lt;"&amp;nbsp; &amp;nbsp; END_DIAG") if not $passed;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; have: $have&lt;br /&gt;
&amp;nbsp; &amp;nbsp; want: $want&lt;br /&gt;
&amp;nbsp; &amp;nbsp; END_DIAG&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; return $passed;&lt;br /&gt;
}&lt;/tt&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;p&gt;It's a minor change, it's completely backwards-compatible and it supports subtests. There's a work-around being planned, but it's not out there yet.&lt;/p&gt;</content>
    <category term="journal"/>
    <published>2009-06-30T14:16:11Z</published>
    <updated>2009-06-30T14:16:11Z</updated>
    <author>
      <name>Ovid</name>
    </author>
    <id>tag:perlsphere.net,2006:http://use.perl.org/~Ovid/journal/39193?from=rss</id>
  </entry>
  <entry>
    <title>Never Let Them Read From Your Database</title>
    <link rel="alternate" href="http://use.perl.org/~Ovid/journal/39192?from=rss" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">An imaginary conversation synthesized from past discussions and the
responses I wish I made.

  * Customer: We need read-only access to your database.

  * Ovid: No.

  * Customer: Please?

  * Ovid: No.

  * Customer: But I need ad-hoc queries.

  * Ovid: Your ad-hoc cartesian join returning 12 billion rows was real
    fun.

  * Customer: I promise I won't do it again.

  * Ovid: That's what you said about the ad-hoc cartesian join returning
    10 billion rows.

  * Customer: But this time I mean it.

  * Ovid: So do I. We guarantee backwards-compatibility in our API, not
    our database. If we move a field from one table to another, your
    queries will break.

  * Customer: Then tell us when you do that.

  * Ovid: We did that with another team and had to keep delaying releases
    while they updated their system.

  * Customer: Then you can provide views to maintain
    backwards-compatibility.

  * Ovid: We do that already. "View" as in "Model-View-Controller". It's
    part of our REST API; you should check it out.

  * Customer: But your REST API doesn't provide all the information I
    need.

  * Ovid: It provides more than the information you need because much of
    it represents knowledge not stored in the database. If you need more
    information, let's see what we can do to add this to the API.

  * Customer: Why are you being so difficult?

  * Ovid: Because your temporary convenience is not more important than
    my long-term pain.

Don't let external customers read directly from your database. Just
don't. The usual justification is the need to support ad-hoc queries. Get
a few samples and try to figure out a general mechanism to support their
actual business needs. If you let them read from your database, they will
become dependent on this and beg you to hold off database changes or
complain if you don't. As your project grows larger, the pain grows more
severe. They will have the best of intentions, but good intentions mean
nothing when you need to coordinate your internals with people who should
know better than to violate encapsulation.

As a side note, ad-hoc queries, even if not causing performance issues,
could potentially be dangerous if the people making them aren't really
thinking them through. The problem is two-fold. One, they might not be
really paying attention to their core business needs (this is subtle and
hard to explain, but common). The other problem is that they might very
well be making a query that your API already supports, but because they
don't rely as much on your API, they don't know it.</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml"><p>An imaginary conversation synthesized from past discussions and the responses I wish I made.</p>
<ul>
<li><tt>Customer:</tt> We need read-only access to your database.</li>
<li><tt>Ovid:</tt> No.</li>
<li><tt>Customer:</tt> Please?</li>
<li><tt>Ovid:</tt> No.</li>
<li><tt>Customer:</tt> But I need ad-hoc queries.</li>
<li><tt>Ovid:</tt> Your ad-hoc cartesian join returning 12 billion rows was real fun.</li>
<li><tt>Customer:</tt> I promise I won't do it again.</li>
<li><tt>Ovid:</tt> That's what you said about the ad-hoc cartesian join returning 10 billion rows.</li>
<li><tt>Customer:</tt> But this time I mean it.</li>
<li><tt>Ovid:</tt> So do I. We guarantee backwards-compatibility in our API, not our database. If we move a field from one table to another, your queries will break.</li>
<li><tt>Customer:</tt> Then tell us when you do that.</li>
<li><tt>Ovid:</tt> We did that with another team and had to keep delaying releases while they updated their system.</li>
<li><tt>Customer:</tt> Then you can provide views to maintain backwards-compatibility.</li>
<li><tt>Ovid:</tt> We do that already. "View" as in "Model-View-Controller". It's part of our REST API; you should check it out.</li>
<li><tt>Customer:</tt> But your REST API doesn't provide all the information I need.</li>
<li><tt>Ovid:</tt> It provides more than the information you need because much of it represents knowledge not stored in the database. If you need more information, let's see what we can do to add this to the API.</li>
<li><tt>Customer:</tt> Why are you being so difficult?</li>
<li><tt>Ovid:</tt> Because your temporary convenience is not more important than my long-term pain.</li>
</ul>
<p>Don't let external customers read directly from your database. Just don't. The usual justification is the need to support ad-hoc queries. Get a few samples and try to figure out a general mechanism to support their actual business needs. If you let them read from your database, they <em>will</em> become dependent on this and beg you to hold off database changes or complain if you don't. As your project grows larger, the pain grows more severe. They will have the best of intentions, but good intentions mean nothing when you need to coordinate your internals with people who should know better than to violate encapsulation.</p>
<p>As a side note, ad-hoc queries, even if not causing performance issues, could potentially be dangerous if the people making them aren't really thinking them through. The problem is two-fold. One, they might not be really paying attention to their core business needs (this is subtle and hard to explain, but common). The other problem is that they might very well be making a query that your API already supports, but because they don't rely as much on your API, they don't know it.</p></div>
    </content>
    <category term="journal"/>
    <published>2009-06-30T11:48:19Z</published>
    <updated>2009-06-30T11:48:19Z</updated>
    <author>
      <name>Ovid</name>
    </author>
    <id>tag:perlsphere.net,2006:http://use.perl.org/~Ovid/journal/39192?from=rss</id>
  </entry>
  <entry>
    <title>The Ubuntu Business model and Perl</title>
    <link rel="alternate" href="http://szabgab.com/blog/2009/06/1246345109.html" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">After my little research into the Eclipse foundation (Comparing the
Eclipse Foundation with The Perl Foundation and EPO) I was told to take a
look at the success of Ubuntu. While I know there is a huge difference as
Ubuntu is an operating system while Perl is just a language but I got
interested and here are the results.

Ubuntu does not have a foundation. It has a strong and very enthusiastic
community and it is backed by Canonical, the company of Mark Shuttleworth.

That means the Perl community probably cannot learn much from the way
Ubuntu and Canonical are connected but we can still look at the larger
picture of how Ubuntu succeeded so far?

First I'll look at the business model of Canonical and later on the
elements that helped Ubuntu become one of the leading GNU/Linux
distributions in only a few years.


The Ubuntu Business model
-------------------------

So if we look closer I think we can safely say that Ubuntu is a product
Canonical is sponsoring in order to make money somehow. I would not say
by selling added value service as I am not exactly sure what is their
business model. I noticed a few areas where Canonical might be making
money:

  * Selling wearables and accessories.

  * Providing support contracts at nice sums.

  * Providing Training and Certification.

  * Distribution mechanism for software.

Selling T-shirts can bring in nice revenue to a small company but for
Canonical it is more part of the marketing mix than the revenue mix.

Providing support can be an interesting business model, IBM makes a lot
of money on it. I guess Canonical does too. This will just increase as
Ubuntu invades the corporate infrastructure.

Training and Certification can be a lucrative business if executed well
and I trust them to do it well. If they can convince companies that they
need Ubuntu Certified Engineers to run Ubuntu smoothly then will see a
huge number of people attending their classes and taking their
certificate exams.

Still the biggest business opportunity I think is the one that is not
even listed in the Canonical Store but only under Services. That is, they
offer to be a distribution channel for ISVs.

In the Microsoft world people are used to download software and
click-click-click install it. In the GNU/Linux world almost all the
important software is packaged and distributed by the Linux distributor.
It is especially true for Debian/Ubuntu but I think it is increasingly so
with Fedora and Mandriva as well. That means the most common installation
mode in these versions of Linux is via a mechanism similar to the
"Add/Remove Software" on Windows.

So if you have a software which you'd like to distribute to Linux users,
one of the best ways is to make sure each one of the Linux distributors
will package your software. Otherwise you'll need to build .deb and .rpm
files for each distribution or a stand-alone executable which is frowned
upon by most of the Linux system administrators.

If your software is not open source you don't have much chance that any
of the Linux distributors will add that package to their repository
making it almost impossible to penetrate the Linux Desktop market.

If Canonical manages to get a large chunk of the market share in the
Linux desktop market it effectively can open or close the distribution
channel of ISVs making them pay well for the right to use Ubuntu as their
distribution platform.

So what will happen to Ubuntu in 5 years?

I don't know.

If you look at the background of Mark Shuttleworth, he built Thawte and
more or less at the peak of the dot.com bubble he sold it to VeriSign the
only competitor in the digital certificates market. So he is a clever guy
who won't be afraid to sell Canonical to the market leader with a near
monopoly in the desktop business or to the competitor with the most money
making a few billions of dollars. The sky isn't the limit


The Perl aspect
---------------

Perl is not an operating system and it is not the open source arm of a
company. It cannot be sold but it can provide nice revenue streams to
individuals or companies offering service with Perl. There might be other
revenue sources as well but lets look at the 4 revenue streams that
Canonical has:

  * Selling wearables - on Perl conferences some stuff is auctioned which
    generates some revenue to organize the next conference. This could be
    further expanded but the income is very limited.

  * Providing support: ActiveState does it as do a number of other small
    companies mostly in the local markets or in specialized fields (e.g.
    Shadowcat providing web development services using Catalyst or
    Summersault providing web development services using Titanium.) This
    could be exploited further providing similar services in other fields
    as well, not only web application development.

  * Offering Perl training provides nice income to several people in the
    Perl community including myself. This does not seem to turn any of us
    rich but provides us with a reasonable income stream to support
    ourselves. Certification is a sour point in the Perl community. Some
    people say that they don't want to have any certification systems for
    Perl others see it as the Holy Grail to make Perl more accepted by
    corporations. In any case this could be a revenue stream but I don't
    think it will happen any time soon.

  * Unlike an Operating system Perl does not control any distribution
    channel but it could be used in a related way. Actually it could be
    used similar to how the JVM provides a platform of application
    development. I am sure one day we will have a binary package of Perl
    with tons of CPAN modules already installed. Something like
    Strawberry Perl but with many more modules that can be installed on
    all major OS-es. That thing could be used as a development and
    distribution platform for all kinds of software.

    I am not sure this can directly generate revenue but it will help
    enlarge the Perl user base and it could provide more opportunities
    for development, support and training services for more people in the
    Perl community.

I'll write about the success of Ubuntu in a separate post. for the
meantime you can read the Ubuntu Story between 2004 and 2006. They don't
keep their history up to date either.</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml"><p>After my little research into the Eclipse foundation (<a rel="nofollow">Comparing the Eclipse Foundation with The Perl Foundation and EPO</a>) I was told to take a look at the success of <a rel="nofollow" target="_blank" href="http://ubuntu.com/">Ubuntu</a>. While I know there is a huge difference as Ubuntu is an operating system while Perl is <i>just</i> a language but I got interested and here are the results.</p>
<p>Ubuntu does not have a foundation. It has a strong and very enthusiastic community and it is backed by <a rel="nofollow" target="_blank" href="http://www.canonical.com/">Canonical</a>, the company of <a rel="nofollow" target="_blank" href="http://www.markshuttleworth.com/">Mark Shuttleworth</a>.</p>
<p>That means the Perl community probably cannot learn much from the way Ubuntu and Canonical are connected but we can still look at the larger picture of how Ubuntu succeeded so far?</p>
<p>First I'll look at the business model of Canonical and later on the elements that helped Ubuntu become one of the leading GNU/Linux distributions in only a few years.</p>
<h2>The Ubuntu Business model</h2>
<p>So if we look closer I think we can safely say that Ubuntu is a product Canonical is sponsoring in order to make money somehow. I would not say by selling added value service as I am not exactly sure what is their business model. I noticed a few areas where Canonical might be making money:</p>
<ul>
<li>Selling wearables and accessories.</li>
<li>Providing support contracts at nice sums.</li>
<li>Providing Training and Certification.</li>
<li>Distribution mechanism for software.</li>
</ul>
<p>Selling T-shirts can bring in nice revenue to a small company but for Canonical it is more part of the marketing mix than the revenue mix.</p>
<p>Providing support can be an interesting business model, IBM makes a lot of money on it. I guess Canonical does too. This will just increase as Ubuntu invades the corporate infrastructure.</p>
<p>Training and Certification can be a lucrative business if executed well and I trust them to do it well. If they can convince companies that they need Ubuntu Certified Engineers to run Ubuntu smoothly then will see a huge number of people attending their classes and taking their certificate exams.</p>
<p>Still the biggest business opportunity I think is the one that is not even listed in the <a rel="nofollow" target="_blank" href="https://shop.canonical.com/">Canonical Store</a> but only under <a rel="nofollow" target="_blank" href="http://www.canonical.com/services">Services</a>. That is, they offer to be a distribution channel for ISVs.</p>
<p>In the Microsoft world people are used to download software and click-click-click install it. In the GNU/Linux world almost all the important software is packaged and distributed by the Linux distributor. It is especially true for Debian/Ubuntu but I think it is increasingly so with Fedora and Mandriva as well. That means the most common installation mode in these versions of Linux is via a mechanism similar to the "Add/Remove Software" on Windows.</p>
<p>So if you have a software which you'd like to distribute to Linux users, one of the best ways is to make sure each one of the Linux distributors will package your software. Otherwise you'll need to build .deb and .rpm files for each distribution or a stand-alone executable which is frowned upon by most of the Linux system administrators.</p>
<p>If your software is not open source you don't have much chance that any of the Linux distributors will add that package to their repository making it almost impossible to penetrate the Linux Desktop market.</p>
<p>If Canonical manages to get a large chunk of the market share in the Linux desktop market it effectively can open or close the distribution channel of ISVs making them pay well for the right to use Ubuntu as their distribution platform.</p>
<p>So what will happen to Ubuntu in 5 years?</p>
<p>I don't know.</p>
<p>If you look at the background of Mark Shuttleworth, he built <a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Thawte">Thawte</a> and more or less at the peak of the dot.com bubble he sold it to VeriSign the only competitor in the digital certificates market. So he is a clever guy who won't be afraid to sell Canonical to the <a rel="nofollow" target="_blank" href="http://www.microsoft.com/">market leader</a> with a near monopoly in the desktop business or to the <a rel="nofollow" target="_blank" href="http://www.oracle.com/">competitor with the most money</a> making a few billions of dollars. <a rel="nofollow" target="_blank" href="http://www.africaninspace.com/">The sky isn't the limit</a></p>
<h2>The Perl aspect</h2>
<p>Perl is not an operating system and it is not the open source arm of a company. It cannot be <i>sold</i> but it can provide nice revenue streams to individuals or companies offering service with Perl. There might be other revenue sources as well but lets look at the 4 revenue streams that Canonical has:</p>
<ul>
<li><b>Selling wearables</b> - on Perl conferences some stuff is auctioned which generates some revenue to organize the next conference. This could be further expanded but the income is very limited.</li>
<li><b>Providing support</b>: <a rel="nofollow" target="_blank" href="http://www.activestate.com/">ActiveState</a> does it as do a number of other small companies mostly in the local markets or in specialized fields (e.g. <a rel="nofollow" target="_blank" href="http://www.shadowcat.co.uk/">Shadowcat</a> providing web development services using <a rel="nofollow" target="_blank" href="http://www.catalystframework.org/">Catalyst</a> or <a rel="nofollow" target="_blank" href="http://www.summersault.com/">Summersault</a> providing web development services using <a rel="nofollow" target="_blank" href="http://cpan.uwinnipeg.ca/dist/Titanium">Titanium</a>.) This could be exploited further providing similar services in other fields as well, not only web application development.</li>
<li>Offering <b>Perl training</b> provides nice income to several people in the Perl community including myself. This does not seem to turn any of us rich but provides us with a reasonable income stream to support ourselves. <b>Certification</b> is a sour point in the Perl community. Some people say that they don't want to have any certification systems for Perl others see it as the Holy Grail to make Perl more accepted by corporations. In any case this could be a revenue stream but I don't think it will happen any time soon.</li>
<li>Unlike an Operating system Perl does not <i>control</i> any <b>distribution channel</b> but it could be used in a related way. Actually it could be used similar to how the JVM provides a platform of application development. I am sure one day we will have a binary package of Perl with tons of CPAN modules already installed. Something like <a rel="nofollow" target="_blank" href="http://www.strawberryperl.com/">Strawberry Perl</a> but with many more modules that can be installed on all major OS-es. That thing could be used as a development and distribution platform for all kinds of software.
<p>I am not sure this can directly generate revenue but it will help enlarge the Perl user base and it could provide more opportunities for development, support and training services for more people in the Perl community.</p>
</li>
</ul>
<p>I'll write about the success of Ubuntu in a separate post. for the meantime you can read the <a rel="nofollow" target="_blank" href="http://www.ubuntu.com/community/ubuntustory">Ubuntu Story</a> between 2004 and 2006. They don't keep their history up to date <a rel="nofollow" target="_blank" href="http://history.perl.org/">either</a>.</p></div>
    </content>
    <published>2009-06-30T02:58:29-07:00</published>
    <updated>2009-06-30T02:58:29-07:00</updated>
    <author>
      <name>nobody</name>
    </author>
    <id>tag:perlsphere.net,2006:ylxaLesS3hGLuL_IPm7D0g_7a8d6ba98d3c21dc761f13f437dbde21</id>
  </entry>
  <entry>
    <title>Imaginary, Integrated, and Ideal</title>
    <link rel="alternate" href="http://www.modernperlbooks.com/mt/2009/06/imaginary-integrated-and-ideal.html" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">My favorite project of the year may be Schwern's perl5i. His goal is to
fix as much of Perl 5 in one swoop. Unlike my Modern::Perl, he's not
limiting himself to core modules and pragmata. Anything on the CPAN that
fixes a deficiency or problem in the language is fair game.

That goal may remind you of the goals of modern Perl.

That means autobox and autobox::Core and signatures and Devel::Declare.

The i stands for imaginary in the same way that the square root of
negative one is an imaginary number. (Yes, clever Reddit and OSNews
kiddies. It can also stand for "irrational", thus Perl 5 is irrational.
Your scathing wit withers discussion. Have a lollipop.)

This is important for several reasons.

First, it's a great, grand experiment to discover what Perl 5 could be
right now. It's a great language and you can do amazing things with it,
but it has its flaws. What if someone could correct them? Perl 5.10.1
won't fix them. Perl 5.12 probably won't. The DarkPAN is too big and
scary to change Perl 5's defaults all even by the time of Perl 5.14 --
but if you choose to use perl5i, presumably you know what you're doing.
What would the language look like and how would it work then?

Perhaps some features will make their way into the core.

Second, it's a great, grand opportunity to make sure that all of these
new pragmata and features and syntaxes work together nicely. It's much
easier to makechanges now -- to discover incompatibilities and subtle
infelicities -- when they all get used together. Better yet, the perl5i
hackers can file bugs and work with individual distribution maintainers
to seek out consensus and compatibility.

Third, it's a great, grand educational tool to demonstrate corners of
CPAN that deserve far more popularity than they have. For example, today
I suggested the use of the Want module, which fixes a poorly named core
keyword and extends it to greater utility. This module may even help the
included autobox::Core handle reference contexts appropriately.

Right now it's not stable; it's experimental. It's worth downloading and
testing in your own code, however. Write software. See what happens. File
bugs. Suggest new features. See what's compatible and what isn't.
Explore. Explain. Enjoy.

To help with development, please visit perl5i on GitHub or visit #perl5i
on irc.perl.org.</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml"><p>My favorite project of the year may be Schwern's <a href="http://search.cpan.org/perldoc?perl5i">perl5i</a>. His goal is to fix as much of Perl 5 in one swoop. Unlike my <a href="http://search.cpan.org/perldoc?Modern::Perl">Modern::Perl</a>, he's not limiting himself to core modules and pragmata. Anything on the CPAN that fixes a deficiency or problem in the language is fair game.</p>
<p>That goal may remind you of the goals of modern Perl.</p>
<p>That means <a href="http://search.cpan.org/perldoc?autobox">autobox</a> and <a href="http://search.cpan.org/perldoc?autobox::Core">autobox::Core</a> and <a href="http://search.cpan.org/perldoc?signatures">signatures</a> and <a href="http://search.cpan.org/perldoc?Devel::Declare">Devel::Declare</a>.</p>
<p>The <em>i</em> stands for <em>imaginary</em> in the same way that the square root of negative one is an imaginary number. (Yes, clever Reddit and OSNews kiddies. It can also stand for "irrational", thus Perl 5 is irrational. Your scathing wit withers discussion. Have a lollipop.)</p>
<p>This is important for several reasons.</p>
<p>First, it's a great, grand experiment to discover what Perl 5 <em>could</em> be right now. It's a great language and you can do amazing things with it, but it has its flaws. What if someone could correct them? Perl 5.10.1 won't fix them. Perl 5.12 probably won't. The DarkPAN is too big and scary to change Perl 5's defaults all even by the time of Perl 5.14 -- but if you choose to use perl5i, presumably you know what you're doing. What would the language look like and how would it work then?</p>
<p>Perhaps some features will make their way into the core.</p>
<p>Second, it's a great, grand opportunity to make sure that all of these new pragmata and features and syntaxes work together nicely. It's much easier to makechanges now -- to discover incompatibilities and subtle infelicities -- when they all get used together. Better yet, the perl5i hackers can file bugs and work with individual distribution maintainers to seek out consensus and compatibility.</p>
<p>Third, it's a great, grand educational tool to demonstrate corners of CPAN that deserve far more popularity than they have. For example, today I suggested the use of the <a href="http://search.cpan.org/perldoc?Want">Want</a> module, which fixes a poorly named core keyword and extends it to greater utility. This module may even help the included <code>autobox::Core</code> handle reference contexts appropriately.</p>
<p>Right now it's not stable; it's experimental. It's worth downloading and testing in your own code, however. Write software. See what happens. File bugs. Suggest new features. See what's compatible and what isn't. Explore. Explain. Enjoy.</p>
<p>To help with development, please visit <a href="http://github.com/schwern/perl5i/tree/master">perl5i on GitHub</a> or visit <code>#perl5i</code> on <a href="http://irc.perl.org/">irc.perl.org</a>.</p></div>
    </content>
    <category term="modern perl perl perl 5 perl programming perl5i"/>
    <published>2009-06-30T00:17:59Z</published>
    <updated>2009-06-30T00:17:59Z</updated>
    <author>
      <name>chromatic</name>
    </author>
    <id>tag:perlsphere.net,2006:tag:www.modernperlbooks.com,2009:/mt//1.65</id>
  </entry>
  <entry>
    <title>more little git n-liners</title>
    <link rel="alternate" href="http://rjbs.manxome.org/rubric/entry/1777" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">I mean, they're not one-liners. They're full programs. They just do
something really really simple.

This one blows away all remotes (left over from, say, GitHub) and adds
all the remotes for users on our git.example.com git-on-ssh hosting box.

#!/usr/bin/perl
use strict;
use warnings;

{
  package Git::Our::Remotes;
  use base 'App::Cmd::Simple';

  use autodie qw(:default :system);
  use Cwd;
  use Getopt::Long::Descriptive;
  use Term::ReadKey;

  my $HOST = q{git.example.com};

  sub opt_spec {
    return (
      [ 'dry-run', "be like quality department; don't actually do anything" ],
    );
  }

  sub _runcmd {
    my ($self, $opt, $cmd) = @_;

    if ($opt-&gt;{dry_run}) {
      print "running: $cmd\n";
    } else {
      system($cmd);
    }
  }

  sub validate_args {
    my ($self, $opt, $args) = @_;

    my $user = $ENV{USER};

    unless (defined $args-&gt;[0]) {
      my $cwd = getcwd;
      $cwd =~ s{.*?/?([^/]+)\z}{$1};
      $args-&gt;[0] = $cwd;
    }

    my $repo = $args-&gt;[0];

    $self-&gt;usage_error("too many args given") if @$args &gt; 1;
    $self-&gt;usage_error("do not run as root")  if $user eq 'root';
    $self-&gt;usage_error("illegal repo name")   if $repo !~ /\A[-_a-z0-9]+\z/;
    $self-&gt;usage_error("you should run this in a repo") if ! -d '.git';
  }

  sub run {
    my ($self, $opt, $args) = @_;

    my $repo = $args-&gt;[0];

    # should be using a library!
    print "press any key to reset all remotes for repo '$repo'";
    Term::ReadKey::ReadMode 'cbreak';
    Term::ReadKey::ReadKey(0);
    Term::ReadKey::ReadMode 'normal';
    print "\n";

    my $user    = $ENV{USER};
    my @others  = grep { $_ ne $user }split / /, (getgrnam('staff'))[3];

    my @remotes = `git remote`;
    chomp @remotes;

    $self-&gt;_runcmd($opt, "git remote rm $_") for @remotes;

    $self-&gt;_runcmd($opt, "git remote add deploy git\@$HOST:$repo.git");
    $self-&gt;_runcmd($opt, "git remote add origin $user\@$HOST:git/$repo.git");

    for my $o (@others) {
      $self-&gt;_runcmd($opt, "git remote add $o $user\@$HOST:~$o/git/$repo.git");
    }

    print "remotes created!\n";
  }
}

Git::Our::Remotes-&gt;import;
Git::Our::Remotes-&gt;run;

...and that's it. Anyone can run git ourremotes to fix remotes setup. If
the user hasn't set up his own hosted ssh remote, he can just run git
hubclone --bare-only using the script I blogged about on Saturday. Done!</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml"><p>I mean, they're not one-liners. They're full programs. They just do something really really simple.</p>
<p>This one blows away all remotes (left over from, say, GitHub) and adds all the remotes for users on our <code>git.example.com</code> git-on-ssh hosting box.</p>
<pre>
<code>#!/usr/bin/perl
use strict;
use warnings;

{
  package Git::Our::Remotes;
  use base 'App::Cmd::Simple';

  use autodie qw(:default :system);
  use Cwd;
  use Getopt::Long::Descriptive;
  use Term::ReadKey;

  my $HOST = q{git.example.com};

  sub opt_spec {
    return (
      [ 'dry-run', "be like quality department; don't actually do anything" ],
    );
  }

  sub _runcmd {
    my ($self, $opt, $cmd) = @_;

    if ($opt-&gt;{dry_run}) {
      print "running: $cmd\n";
    } else {
      system($cmd);
    }
  }

  sub validate_args {
    my ($self, $opt, $args) = @_;

    my $user = $ENV{USER};

    unless (defined $args-&gt;[0]) {
      my $cwd = getcwd;
      $cwd =~ s{.*?/?([^/]+)\z}{$1};
      $args-&gt;[0] = $cwd;
    }

    my $repo = $args-&gt;[0];

    $self-&gt;usage_error("too many args given") if @$args &gt; 1;
    $self-&gt;usage_error("do not run as root")  if $user eq 'root';
    $self-&gt;usage_error("illegal repo name")   if $repo !~ /\A[-_a-z0-9]+\z/;
    $self-&gt;usage_error("you should run this in a repo") if ! -d '.git';
  }

  sub run {
    my ($self, $opt, $args) = @_;

    my $repo = $args-&gt;[0];

    # should be using a library!
    print "press any key to reset all remotes for repo '$repo'";
    Term::ReadKey::ReadMode 'cbreak';
    Term::ReadKey::ReadKey(0);
    Term::ReadKey::ReadMode 'normal';
    print "\n";

    my $user    = $ENV{USER};
    my @others  = grep { $_ ne $user }split / /, (getgrnam('staff'))[3];

    my @remotes = `git remote`;
    chomp @remotes;

    $self-&gt;_runcmd($opt, "git remote rm $_") for @remotes;

    $self-&gt;_runcmd($opt, "git remote add deploy git\@$HOST:$repo.git");
    $self-&gt;_runcmd($opt, "git remote add origin $user\@$HOST:git/$repo.git");

    for my $o (@others) {
      $self-&gt;_runcmd($opt, "git remote add $o $user\@$HOST:~$o/git/$repo.git");
    }

    print "remotes created!\n";
  }
}

Git::Our::Remotes-&gt;import;
Git::Our::Remotes-&gt;run;
</code>
</pre>
<p>...and that's it. Anyone can run <code>git ourremotes</code> to fix remotes setup. If the user hasn't set up his own hosted ssh remote, he can just run <code>git hubclone --bare-only</code> using the script I blogged about on Saturday. Done!</p></div>
    </content>
    <published>2009-06-29T16:15:37-05:00</published>
    <updated>2009-06-29T16:15:37-05:00</updated>
    <author>
      <name>rjbs</name>
    </author>
    <id>tag:perlsphere.net,2006:http://rjbs.manxome.org/rubric/entry/1777</id>
  </entry>
  <entry>
    <title>Mojo 0.991231 released</title>
    <link rel="alternate" href="http://labs.kraih.com/blog/2009/06/mojo-0991231-released.html" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">We have just released the last big milestone on the way towards Mojo 1.0,
everything from now on will be just documentation, artwork and other
polishing tasks.

As usual there are awesome new features such as HTTP 1.1 pipelining,
format handling, layout support and a brand new routes syntax.

Thanks to our GSOC Student Pascal Gaudette who squashed many RFC related
bugs we are now even further ahead of other HTTP implementations on CPAN.
And the best of all, after some refactoring the whole HTTP 1.1
client/server state machine is now completely reusable and independent
from the IO layer. This will make modules such as AnyEvent::Mojo
absolutely trivial in the future.

And while we are at it, here's a preview of the new "fluffy cloud" Mojo
logo! [IMAGE]

The complete changelog.

  - Rewrote MojoX::Renderer, it is not backward compatible and
  templates need to be renamed in the following 3 part format
  "index.html.tt"!
  - Added exception support to MojoX::Dispatcher::Routes, this change
  is not backward compatible and "dispatch" calls now return exception
  objects for errors and false otherwise.
  - Changed routes syntax, this change is not backward compatible and
  you need to change all your existing routes.
  "/:foo" becomes "/(foo)"
  "/^foo" becomes "/((foo))"
  "/*foo" becomes "/(((foo)))"
  - Added full HTTP 1.1 pipelining support to all Mojo layers.
  - Added layout support to MojoX::Renderer.
  - Made render call optional.
  - Added format support to MojoX::Routes.
  - Added Mojo::Loader::Exception.
  - Added wildcard symbol support to MojoX::Routes and rewrote many
  routes internals.
  - Added Makefile.PL generator.
  - Added HttpOnly support to Mojo::Cookie. (burak)
  - Support more CGI implementations.
  - Added support for namespaces only dispatching in
  MojoX::Dispatcher::Routes.
  - Added encoding support to Mojo::Template and made "utf8" the
  default.
  - Added HEAD support to Mojo::Server::Daemon. (acajou)
  - Added new relaxed placeholder to MojoX::Routes::Pattern.
  - Added Mojo::Template::Exception.
  - Added HEAD support to the Mojo::Transaction state machine and
  related modules. (acajou)
  - Added safe_post option to Mojo::Pipeline. (acajou)
  - Made chained =&gt; 1 the default in Mojo::Base.
  - Fixed compiler bug in Mojo::Template that prevented more advanced
  control structures, you might have to add additional semicolons to
  some of your templates.
  - Fixed Mojo::Date to not crash on invalid dates. (vti)
  - Fixed chunked support in Mojo::Server::Daemon and Mojo::Client.
  - Fixed tokenizer in MojoX::Routes::Pattern to support "0" values.
  (Anatoly Sharifulin)
  - Fixed parsing of "0" in Mojo::Path. (charsbar)
  - Fix server tests on win32. (charsbar)
  - Fixed leading whitespace problem in the request parser. (acajou)
  - Fixed broken pipe problem in Mojo::Server::CGI. (vti)
  - Added more diagnostics options to Mojo::HelloWorld. (uwe)
  - Fixed empty cookie parsing. (vti)
  - Fixed a case where child processes migth hang in
  Mojo::Server::Daemon::Prefork. (gbarr)
  - Fixed a bug in MojoX::Dispatcher::Routes where the renderer would
  be called with an empty stack. (melo)
  - Fixed a escaping problem in Mojo::Parameters. (vti)
  - Updated Mojo::URL to be more template friendly.
  - Improved Solaris compatibility.



P.S. In case you were wondering, the version number is the date of the
first futurama episode. ;)</div>
    </summary>
    <content type="text">We have just released the last big milestone on the way towards &lt;a href="http://mojolicious.org"&gt;Mojo&lt;/a&gt; 1.0, everything from now on will be just documentation, artwork and other polishing tasks.&lt;br /&gt;
&lt;br /&gt;
As usual there are awesome new features such as &lt;a href="http://labs.kraih.com/blog/2009/04/http-11-pipelining-in-mojo.html"&gt;HTTP 1.1 pipelining&lt;/a&gt;, format handling, layout support and a brand new routes syntax.&lt;br /&gt;
&lt;br /&gt;
Thanks to our &lt;a href="http://code.google.com/soc/"&gt;GSOC&lt;/a&gt; Student &lt;a href="http://fooko.blogspot.com/"&gt;Pascal Gaudette&lt;/a&gt; who squashed many &lt;a href="http://www.ietf.org/rfc/rfc2616.txt"&gt;RFC&lt;/a&gt; related bugs we are now even further ahead of other HTTP implementations on CPAN. And the best of all, after some refactoring the whole HTTP 1.1 client/server state machine is now completely reusable and independent from the IO layer. This will make modules such as &lt;a href="http://search.cpan.org/dist/AnyEvent-Mojo/"&gt;AnyEvent::Mojo&lt;/a&gt; absolutely trivial in the future.&lt;br /&gt;
&lt;br /&gt;
And while we are at it, here's a preview of the new "fluffy cloud" Mojo logo! &lt;img src="http://kraih.com/mojo-pinstripe.png"&gt;&lt;br /&gt;
&lt;br /&gt;
The complete changelog.
&lt;blockquote&gt;- Rewrote MojoX::Renderer, it is not backward compatible and templates need to be renamed in the following 3 part format "index.html.tt"!&lt;br /&gt;
- Added exception support to MojoX::Dispatcher::Routes, this change is not backward compatible and "dispatch" calls now return exception objects for errors and false otherwise.&lt;br /&gt;
- Changed routes syntax, this change is not backward compatible and you need to change all your existing routes.&lt;br /&gt;
"/:foo" becomes "/(foo)"&lt;br /&gt;
"/^foo" becomes "/((foo))"&lt;br /&gt;
"/*foo" becomes "/(((foo)))"&lt;br /&gt;
- Added full HTTP 1.1 pipelining support to all Mojo layers.&lt;br /&gt;
- Added layout support to MojoX::Renderer.&lt;br /&gt;
- Made render call optional.&lt;br /&gt;
- Added format support to MojoX::Routes.&lt;br /&gt;
- Added Mojo::Loader::Exception.&lt;br /&gt;
- Added wildcard symbol support to MojoX::Routes and rewrote many routes internals.&lt;br /&gt;
- Added Makefile.PL generator.&lt;br /&gt;
- Added HttpOnly support to Mojo::Cookie. (burak)&lt;br /&gt;
- Support more CGI implementations.&lt;br /&gt;
- Added support for namespaces only dispatching in MojoX::Dispatcher::Routes.&lt;br /&gt;
- Added encoding support to Mojo::Template and made "utf8" the default.&lt;br /&gt;
- Added HEAD support to Mojo::Server::Daemon. (acajou)&lt;br /&gt;
- Added new relaxed placeholder to MojoX::Routes::Pattern.&lt;br /&gt;
- Added Mojo::Template::Exception.&lt;br /&gt;
- Added HEAD support to the Mojo::Transaction state machine and related modules. (acajou)&lt;br /&gt;
- Added safe_post option to Mojo::Pipeline. (acajou)&lt;br /&gt;
- Made chained =&amp;gt; 1 the default in Mojo::Base.&lt;br /&gt;
- Fixed compiler bug in Mojo::Template that prevented more advanced control structures, you might have to add additional semicolons to some of your templates.&lt;br /&gt;
- Fixed Mojo::Date to not crash on invalid dates. (vti)&lt;br /&gt;
- Fixed chunked support in Mojo::Server::Daemon and Mojo::Client.&lt;br /&gt;
- Fixed tokenizer in MojoX::Routes::Pattern to support "0" values. (Anatoly Sharifulin)&lt;br /&gt;
- Fixed parsing of "0" in Mojo::Path. (charsbar)&lt;br /&gt;
- Fix server tests on win32. (charsbar)&lt;br /&gt;
- Fixed leading whitespace problem in the request parser. (acajou)&lt;br /&gt;
- Fixed broken pipe problem in Mojo::Server::CGI. (vti)&lt;br /&gt;
- Added more diagnostics options to Mojo::HelloWorld. (uwe)&lt;br /&gt;
- Fixed empty cookie parsing. (vti)&lt;br /&gt;
- Fixed a case where child processes migth hang in Mojo::Server::Daemon::Prefork. (gbarr)&lt;br /&gt;
- Fixed a bug in MojoX::Dispatcher::Routes where the renderer would be called with an empty stack. (melo)&lt;br /&gt;
- Fixed a escaping problem in Mojo::Parameters. (vti)&lt;br /&gt;
- Updated Mojo::URL to be more template friendly.&lt;br /&gt;
- Improved Solaris compatibility.&lt;br /&gt;&lt;/blockquote&gt;
&lt;br /&gt;
&lt;br /&gt;
P.S. In case you were wondering, the version number is the date of the first futurama episode. ;)</content>
    <category term="Perl"/>
    <published>2009-06-29T19:39:04+02:00</published>
    <updated>2009-06-29T19:39:04+02:00</updated>
    <author>
      <name>Sebastian</name>
    </author>
    <id>tag:perlsphere.net,2006:tag:labs.kraih.com,2009:/blog//1.29</id>
  </entry>
  <entry>
    <title>even more lazyness with dist::zilla::plugin::autoprereq</title>
    <link rel="alternate" href="http://jquelin.blogspot.com/2009/06/even-more-lazyness-with.html" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">who never forgot to list a prereq in their makefile.pl / build.pl /
whatever? it happens to me on a regular basis.

now that i started using dist::zilla, prereqs are not listed in a build
script, but in dist zilla configuration file. but the problem is the
same: prereqs are listed manually. and doing stuff manually sucks.

i had to do something. so i used dist-zilla's plugin infrastructure and
just uploaded dist::zilla::plugin::autoprereq. just add:

  [AutoPrereq]

in your dist.ini, and it will automatically find your prereqs for
dist::zilla to use.

the parsing is somehow very rough: it will just find the lines beginning
by use or require. for more advanced / hackish stuff,
dist::zilla::plugin::prereq is still available. i still think that it
should cover 80+% of the cases. i considered using module::info, but it
evals the modules to find the prereqs and the result is damn slow... and
speed was more important imo.

note that i plan to add the possibility to add modules manually, in order
to add missing modules (or maybe we can use both prereq and autoprereq?),
and a skip option to trim modules that should not be added to the list of
prereqs.

also, i may change the algorithm used to find prereqs: maybe ppi will be
fast enough? we'll see.

but in the meantime, just enjoy not writing anymore those prereqs by
hand! :-) [IMAGE]</div>
    </summary>
    <content type="text">who never forgot to list a prereq in their makefile.pl / build.pl / whatever? it happens to me on a regular basis.&lt;br /&gt;
&lt;br /&gt;
now that i started using &lt;a href="http://search.cpan.org/dist/Dist-Zilla/"&gt;dist::zilla&lt;/a&gt;, prereqs are not listed in a build script, but in dist zilla configuration file. but the problem is the same: prereqs are listed manually. and doing stuff manually sucks.&lt;br /&gt;
&lt;br /&gt;
i had to do something. so i used dist-zilla's plugin infrastructure and just uploaded &lt;a href="http://search.cpan.org/dist/Dist-Zilla-Plugin-AutoPrereq/"&gt;dist::zilla::plugin::autoprereq&lt;/a&gt;. just add:
&lt;blockquote&gt;
&lt;pre&gt;
[AutoPrereq]
&lt;/pre&gt;&lt;/blockquote&gt;
in your dist.ini, and it will automatically find your prereqs for dist::zilla to use.&lt;br /&gt;
&lt;br /&gt;
the parsing is somehow very rough: it will just find the lines beginning by use or require. for more advanced / hackish stuff, dist::zilla::plugin::prereq is still available. i still think that it should cover 80+% of the cases. i considered using &lt;a href="http://search.cpan.org/dist/Module-Info/"&gt;module::info&lt;/a&gt;, but it evals the modules to find the prereqs and the result is damn slow... and speed was more important imo.&lt;br /&gt;
&lt;br /&gt;
note that i plan to add the possibility to add modules manually, in order to add missing modules (or maybe we can use both prereq and autoprereq?), and a skip option to trim modules that should not be added to the list of prereqs.&lt;br /&gt;
&lt;br /&gt;
also, i may change the algorithm used to find prereqs: maybe &lt;a href="http://search.cpan.org/dist/PPI/"&gt;ppi&lt;/a&gt; will be fast enough? we'll see.&lt;br /&gt;
&lt;br /&gt;
but in the meantime, just enjoy not writing anymore those prereqs by hand! :-)
&lt;div class="blogger-post-footer"&gt;&lt;img&gt;&lt;/div&gt;</content>
    <category term="plugin dzill dist perl"/>
    <published>2009-06-29T16:45:00Z</published>
    <updated>2009-06-29T16:45:00Z</updated>
    <author>
      <name>jquelin@gmail.com (Jérôme Quelin)</name>
    </author>
    <id>tag:perlsphere.net,2006:tag:blogger.com,1999:blog-6162910877268067002.post-4882795062435787414</id>
  </entry>
  <entry>
    <title>Guess Who Loses: Test::More::subtest versus Test::XML</title>
    <link rel="alternate" href="http://use.perl.org/~Ovid/journal/39188?from=rss" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">I've found that one of the best ways to try new testing ideas is to run
them against our test suite at work. We've over 30,000 tests at this
point, with several test harnesses integrating together, along with two
fundamentally different test systems. This means that when I throw
something at this test suite, I often shake out bugs. My new
Test::Aggregate::Nested combined with our test suite managed to find a
rather serious issue with the new subtest function in Test::More. The
following, for example, fails:

  use Test::More tests =&gt; 2;
  use Test::XML;

  ok 1;
  subtest 'FAIL!' =&gt; sub {
  plan tests =&gt; 1;
  is_xml '<foo/>', '<foo/>', 'Singleton fail';
  };
  __END__
  xml.t ..
  1..2
  ok 1
  1..1
  Cannot run test (Singleton fail) with active children at
  /home/ovid/pips_dev/work/Pips3/branches/rights_modeling/deps/lib/perl5/Test/XML.
  pm line 57.
  # Child (FAIL!) exited without calling finalize()

There's nothing wrong with the code as it's written, but Test::XML knows
that the Test::Builder object is a singleton, so there's a false
optimization in the code. Near the top of the package, you see this line,
defined outside of all functions:

  my $Test = Test::Builder-&gt;new;

If every Test::XML function simply had that line in the function rather
than trying to share this across all test functions, the subtest code
would work fine. Instead, the author knew he had a singleton and there's
no point in re-instantiating, is there?

To be fair, I've done the same thing before (see Test::JSON), even though
I knew it might be a bad idea. Heck, lots and lots of testing libraries
have this issue. Now we need to figure out how to deal with this problem
or else subtests aren't going to play well with a lot of code. Damn.</div>
    </summary>
    <content type="html">&lt;p&gt;I've found that one of the best ways to try new testing ideas is to run them against our test suite at work. We've over 30,000 tests at this point, with several test harnesses integrating together, along with two fundamentally different test systems. This means that when I throw something at this test suite, I often shake out bugs. My new &lt;tt&gt;Test::Aggregate::Nested&lt;/tt&gt; combined with our test suite managed to find a rather serious issue with the new &lt;tt&gt;subtest&lt;/tt&gt; function in &lt;tt&gt;Test::More&lt;/tt&gt;. The following, for example, fails:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;
&lt;p&gt;&lt;tt&gt;&amp;nbsp; &amp;nbsp; use Test::More tests =&amp;gt; 2;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; use Test::XML;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; ok 1;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; subtest 'FAIL!' =&amp;gt; sub {&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; plan tests =&amp;gt; 1;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; is_xml '&amp;lt;foo/&amp;gt;', '&amp;lt;foo/&amp;gt;', 'Singleton fail';&lt;br /&gt;
&amp;nbsp; &amp;nbsp; };&lt;br /&gt;
&amp;nbsp; &amp;nbsp; __END__&lt;br /&gt;
&amp;nbsp; &amp;nbsp; xml.t &lt;nobr&gt;&lt;wbr /&gt;&lt;/nobr&gt;..&lt;br /&gt;
&amp;nbsp; &amp;nbsp; 1..2&lt;br /&gt;
&amp;nbsp; &amp;nbsp; ok 1&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 1..1&lt;br /&gt;
&amp;nbsp; &amp;nbsp; Cannot run test (Singleton fail) with active children at &lt;nobr&gt;&lt;wbr /&gt;&lt;/nobr&gt;/home/ovid/pips_dev/work/Pips3/branches/rights_modeling/deps/lib/perl5/Test/XML&lt;nobr&gt;.&lt;wbr /&gt;&lt;/nobr&gt; pm line 57.&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # Child (FAIL!) exited without calling finalize()&lt;/tt&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;p&gt;There's nothing wrong with the code as it's written, but &lt;tt&gt;Test::XML&lt;/tt&gt; knows that the &lt;tt&gt;Test::Builder&lt;/tt&gt; object is a singleton, so there's a false optimization in the code. Near the top of the package, you see this line, defined outside of all functions:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;
&lt;p&gt;&lt;tt&gt;&amp;nbsp; &amp;nbsp; my $Test = Test::Builder-&amp;gt;new;&lt;/tt&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;p&gt;If every &lt;tt&gt;Test::XML&lt;/tt&gt; function simply had that line in the function rather than trying to share this across all test functions, the subtest code would work fine. Instead, the author knew he had a singleton and there's no point in re-instantiating, is there?&lt;/p&gt;
&lt;p&gt;To be fair, I've done the same thing before (see &lt;tt&gt;Test::JSON&lt;/tt&gt;), even though I knew it might be a bad idea. Heck, lots and lots of testing libraries have this issue. Now we need to figure out how to deal with this problem or else subtests aren't going to play well with a lot of code. Damn.&lt;/p&gt;</content>
    <category term="journal"/>
    <published>2009-06-29T14:00:00Z</published>
    <updated>2009-06-29T14:00:00Z</updated>
    <author>
      <name>Ovid</name>
    </author>
    <id>tag:perlsphere.net,2006:http://use.perl.org/~Ovid/journal/39188?from=rss</id>
  </entry>
  <entry>
    <title>Reflections on YAPC::NA 2009</title>
    <link rel="alternate" href="http://blog.sartak.org/2009/06/reflections-on-yapcna-2009.html" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">I had a lot of fun at YAPC::NA this year. I met some forest friends that
didn't make it last year, such as ilmari, Nick Perez, and Dylan Hardison.
I also laughed until it hurt. A few times.

I was a hermit on Sunday and Monday nights because I had not finished my
slides. That was very unfortunate, so I will have future talks ready well
in advance. Jitting slides is so not my style.


Moose Course

The eight hour Moose course went very well. I was a passable
Rolsky-substitute. The feedback I recieved was (nearly) unanimously good,
so I'm thrilled that people enjoyed it. There were some minor complaints,
so if I ever teach a course again I'll be sure to keep them in mind. This
year, YAPC::NA is running surveys on talks and courses, so I expect I'll
learn more ways that the class could be improved. If you attended the
class, please do not worry about offending Dave or me if you disliked
something.

I was under-prepared for the class, but the course material was very
good. I got the impression that the exercises were extremely helpful. In
particular, having a good test suite (powered by the metaobject
protocol!) was very useful. The exercises were also useful for me because
they let me sit down. Speaking on your feet for so many hours is tough.

Like the first version of anything, the course material contained some
typos, inconsistencies, and bugs. It was pleasant to fix these and push
them back to the source repository while people worked on the exercises.
For some reason, we could not get public (i.e. noncommitter) access to
the repository working, perhaps due to DNS issues. It would have been
useful to have people pull my changes to fix the exercises. Instead, I
settled for announcing what the problems were and how to fix them.

Context

Early in the course I had a vitriolic rant about Perl's notion of context.
On the whole I think context is a nice solution to a certain class of
problems, but it definitely has some edge cases where it really bites
programmers. For example, propagating context is very fiddly. You must
propagate context if you wrap a function to do work after it is called
without affecting its return value.

sub method {
    my $self = shift;

    # call SUPER::method in the right context.
    # not handling void context is a BUG!
    my @ret;
    if (wantarray) {
        @ret = $self-&gt;SUPER::method(@_);
    } elsif (defined wantarray) {
        $ret[0] = $self-&gt;SUPER::method(@_);
    } else {
        $self-&gt;SUPER::method(@_);
    }

    $self-&gt;called_method($self-&gt;called_method + 1);

    # return what the caller asked for.
    # void context doesn't need to be explicitly handled here
    # .. or does it? maybe!
    return @ret if wantarray;
    return $ret[0];
}

I don't recall mentioning in the class that Moose does all of this for us
in the after method modifier:

after method =&gt; sub {
    my $self = shift;
    $self-&gt;called_method($self-&gt;called_method + 1);
};

The other painful detail about context is in returning a list in scalar
context. Most people know that an array in scalar context evaluates to
the number of elements:

sub users {
    my $self = shift;
    my @users = $self-&gt;objects('users');
    return @users;
}

my $users = $game-&gt;users; # 51

However, a lot of people don't know that there is an irritating amount of
subtlety in evaluating a list in scalar context:

sub administrators {
    my $self = shift;
    return ('Sartak', 'autarch');
}

my $admins = $game-&gt;administrators; # autarch

Instead of receiving the count of administrators, we get the last element
of the list. The problem is actually the comma. Due to C's strong
influence on Perl 5, the comma is not just a list separator. In scalar
context it acts as a sequencing operator. We're evaluating the string
'Sartak', throwing it away, then evaluating the string 'autarch'. There
is no list at all here!

  Binary "," is the comma operator. In scalar context it evaluates its
  left argument, throws that value away, then evaluates its right
  argument and returns that value. This is just like C's comma
  operator.

  – perldoc perlop

Almost everywhere else in the language, arrays and lists are
interchangeable. I wish this inconsistency could be excised. Thanks to do
BLOCK, we do not need C's comma operator at all.


Extending Moose

On Tuesday morning I presented Extending Moose for Applications (keynote
source). There were maybe 20 attendees. I blame the 8AM start time. Oh
well.

I'm told that at one point someone walked out saying the talk got "too
abstract". It certainly is a very abstract topic, but I hope the examples
showed that there is value to be had in using the ideas I presented.

Some good questions were asked, and some people did get it. I conveyed
the point I wanted to make, which is that the metaobject protocol uses
concepts you already know well.

I encourage you to read the slides. There are notes which is basically
what I spoke when I was presenting, so they should be pretty readable.
Please let me know how I did. I've received very little feedback on this
talk.


TAEB

One of my good friends Jesse Luehrs (doy) gave a lightning talk about our
NetHack bot, TAEB.

[IMAGE]

The line "The code I'm working on isn't really a NetHack bot; it's more
of a framework for writing NetHack bots" got quite a few laughs. It's
completely true, too. The topic of the talk was writing a new AI for this
bot framework.

The bitrotted web interface seemed to please people. It's too bad they
saw how it was when I first wrote it. Since I took those screenshots, I
improved it quite a bit, making it use NetHack's colors and providing an
AJAXy interface. Oh well, I should really get that working again.

This lightning talk was a hit. Several people cheered! Great job, Jesse.


Others' Talks

My favorite talk, by far, was Brock Wilcox's CGI::Inspect talk. As I said
during the talk, when I wrote Carp::REPL, I was actually aiming for
exactly what CGI::Inspect is. And I meant it! About two years ago, it was
mentioned to me how when there's an error in your Django application, it
opens an AJAXy REPL for you. I figured out how to do some of that - REPL
on error - but I never actually hooked it up to Jifty. Now I don't have
to. Bravo, Brock!

Another talk I enjoyed was Ricardo Signes's Git is Easy talk. I knew most
of the material presented, but since seeing that talk I have had a lot
more confidence in using git. In particular, remotes now make sense to
me. I also now use GitX to visualize where other developers are relative
to me.

Scott Walter's Perl in Vegas talk was fascinating. He drew an interesting
parallel between the incredible strictures of Vegas slot machines versus
America's completely opaque and mostly unregulated voting machines. One
strange requirement of the slot machines is that code must be compiled.
Though Perl is an interpreted language, it provides a perlcc utility to
"compile" the code.

Hans Dieter Pearcey's Dist::Zilla - Automating quality since 2008
reminded me of its excellent plugin-centric design:

[IMAGE]

This slide directly caused me to submit a talk about API Design to
YAPC::Asia 2009.

Finally, miyagawa's Build a desktop application with Perl, HTTP::Engine,
SQLite and jQuery talk was exciting. I've been working toward using his
perl-app-builder for TAEB since he blogged about it. The talk showed how
we can write standalone, web-based, GUI apps, in Perl, without inflicting
CPAN on our users. Because Perl has been a web language ever since the
web has had languages, the tools for generating HTML, serving pages, etc.
are very good. The traditional GUI tools are mediocre at best. They are
why my applications have been strictly web- and curses-based.


Thanks!

Thank you Robert Blackwell, Casey West, Tom Moertel, Dan Wright, and
anyone else who helped! This YAPC was fantastic.

If you have never been to YAPC, you should seriously consider going to
the next one!

[IMAGE]</div>
    </summary>
    <content type="html">&lt;p&gt;I had a lot of fun at &lt;a href="http://yapc10.org/yn2009/"&gt;YAPC::NA&lt;/a&gt; this year. I met some &lt;a href="http://pbfcomics.com/?cid=PBF152-Scorpy_the_Forest_Friend.gif"&gt;forest friends&lt;/a&gt; that didn't make it last year, such as &lt;a href="http://ilmari.org/"&gt;ilmari&lt;/a&gt;, &lt;a href="http://clownpenis.fart/"&gt;Nick Perez&lt;/a&gt;, and &lt;a href="http://dylan.hardison.net"&gt;Dylan Hardison&lt;/a&gt;. I also laughed until it hurt. A few times.&lt;/p&gt;
&lt;p&gt;I was a hermit on Sunday and Monday nights because I had not finished my slides. That was very unfortunate, so I will have future talks ready well in advance. Jitting slides is so not my style.&lt;/p&gt;
&lt;h3&gt;Moose Course&lt;/h3&gt;
&lt;p&gt;The eight hour Moose course went very well. I was a passable &lt;a href="http://blog.urth.org/2009/06/i-wont-be-at-yapc-10.html"&gt;Rolsky-substitute&lt;/a&gt;. The &lt;a href="http://blog.afoolishmanifesto.com/archives/844"&gt;feedback&lt;/a&gt; I recieved was (nearly) unanimously good, so I'm thrilled that people enjoyed it. There were some minor complaints, so if I ever teach a course again I'll be sure to keep them in mind. This year, YAPC::NA is running surveys on talks and courses, so I expect I'll learn more ways that the class could be improved. If you attended the class, please do not worry about offending Dave or me if you disliked something.&lt;/p&gt;
&lt;p&gt;I was under-prepared for the class, but &lt;a href="http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=gitmo/moose-presentations.git;a=tree;f=moose-class"&gt;the course material&lt;/a&gt; was very good. I got the impression that the exercises were extremely helpful. In particular, having a good test suite (powered by the metaobject protocol!) was very useful. The exercises were also useful for me because they let me sit down. Speaking on your feet for so many hours is tough.&lt;/p&gt;
&lt;p&gt;Like the first version of anything, the course material contained some typos, inconsistencies, and bugs. It was pleasant to fix these &lt;em&gt;and push them back to the source repository&lt;/em&gt; while people worked on the exercises. For some reason, we could not get public (i.e. noncommitter) access to the repository working, perhaps due to DNS issues. It would have been useful to have people pull my changes to fix the exercises. Instead, I settled for announcing what the problems were and how to fix them.&lt;/p&gt;
&lt;h4 id="context"&gt;Context&lt;/h4&gt;
&lt;p&gt;Early in the course I had a vitriolic rant about Perl's notion of &lt;i&gt;context&lt;/i&gt;. On the whole I think context is a nice solution to a certain class of problems, but it definitely has some edge cases where it really bites programmers. For example, propagating context is very fiddly. You &lt;em&gt;must&lt;/em&gt; propagate context if you wrap a function to do work after it is called without affecting its return value.&lt;/p&gt;
&lt;pre&gt;
sub method {
    my $self = shift;

    # call SUPER::method in the right context.
    # not handling void context is a BUG!
    my @ret;
    if (wantarray) {
        @ret = $self-&amp;gt;SUPER::method(@_);
    } elsif (defined wantarray) {
        $ret[0] = $self-&amp;gt;SUPER::method(@_);
    } else {
        $self-&amp;gt;SUPER::method(@_);
    }

    $self-&amp;gt;called_method($self-&amp;gt;called_method + 1);

    # return what the caller asked for.
    # void context doesn't need to be explicitly handled here
    # .. or does it? maybe!
    return @ret if wantarray;
    return $ret[0];
}
&lt;/pre&gt;
&lt;p&gt;I don't recall mentioning in the class that Moose does all of this for us in the &lt;tt&gt;after&lt;/tt&gt; method modifier:&lt;/p&gt;
&lt;pre&gt;
after method =&amp;gt; sub {
    my $self = shift;
    $self-&amp;gt;called_method($self-&amp;gt;called_method + 1);
};
&lt;/pre&gt;
&lt;p&gt;The other painful detail about context is in returning a list in scalar context. Most people know that an &lt;strong&gt;array&lt;/strong&gt; in scalar context evaluates to the number of elements:&lt;/p&gt;
&lt;pre&gt;
sub users {
    my $self = shift;
    my @users = $self-&amp;gt;objects('users');
    return @users;
}

my $users = $game-&amp;gt;users; # 51
&lt;/pre&gt;
&lt;p&gt;However, a lot of people don't know that there is an irritating amount of subtlety in evaluating a &lt;strong&gt;list&lt;/strong&gt; in scalar context:&lt;/p&gt;
&lt;pre&gt;
sub administrators {
    my $self = shift;
    return ('Sartak', 'autarch');
}

my $admins = $game-&amp;gt;administrators; # autarch
&lt;/pre&gt;
&lt;p&gt;Instead of receiving the &lt;em&gt;count&lt;/em&gt; of administrators, we get the last element of the list. The problem is actually the &lt;em&gt;comma&lt;/em&gt;. Due to C's strong influence on Perl 5, the comma is not just a list separator. In scalar context it acts as a sequencing operator. We're evaluating the string 'Sartak', throwing it away, then evaluating the string 'autarch'. &lt;strong&gt;There is no list at all here!&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;Binary "," is the comma operator. In scalar context it evaluates its left argument, throws that value away, then evaluates its right argument and returns that value. This is just like C's comma operator.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="attribution"&gt;– &lt;tt&gt;&lt;a href="http://perldoc.perl.org/perlop.html#Comma-Operator"&gt;perldoc perlop&lt;/a&gt;&lt;/tt&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;Almost everywhere else in the language, arrays and lists are interchangeable. I wish this inconsistency could be excised. Thanks to &lt;tt&gt;do BLOCK&lt;/tt&gt;, we do not need C's comma operator at all.&lt;/p&gt;
&lt;h3&gt;Extending Moose&lt;/h3&gt;
&lt;p&gt;On Tuesday morning I presented &lt;a href="http://sartak.org/talks/yapc-na-2009/extending-moose/extending-moose.pdf"&gt;Extending Moose for Applications&lt;/a&gt; &lt;a href="http://sartak.org/talks/yapc-na-2009/extending-moose/extending-moose.key"&gt;(keynote source)&lt;/a&gt;. There were maybe 20 attendees. I blame the 8AM start time. Oh well.&lt;/p&gt;
&lt;p&gt;I'm told that at one point someone walked out saying the talk got "too abstract". It certainly is a very abstract topic, but I hope the examples showed that there is value to be had in using the ideas I presented.&lt;/p&gt;
&lt;p&gt;Some good questions were asked, and some people did get it. I conveyed the point I wanted to make, which is that the metaobject protocol uses concepts you already know well.&lt;/p&gt;
&lt;p&gt;I encourage you to read the slides. There are notes which is basically what I spoke when I was presenting, so they should be pretty readable. Please let me know how I did. I've received very little feedback on this talk.&lt;/p&gt;
&lt;h3&gt;TAEB&lt;/h3&gt;
&lt;p&gt;One of my good friends &lt;a href="http://tozt.net/"&gt;Jesse Luehrs (doy)&lt;/a&gt; gave a lightning talk about our NetHack bot, &lt;a href="http://taeb.sartak.org/"&gt;TAEB&lt;/a&gt;.&lt;/p&gt;
&lt;img src="http://sartak.org/misc/blog/doy-taeb.jpg"&gt;
&lt;p&gt;The line "The code I'm working on isn't really a NetHack bot; it's more of a framework for writing NetHack bots" got quite a few laughs. It's completely true, too. The topic of the talk was writing a new AI for this bot framework.&lt;/p&gt;
&lt;p&gt;The bitrotted web interface seemed to please people. It's too bad they saw how it was when I first wrote it. Since I took those screenshots, I improved it quite a bit, making it use NetHack's colors and providing an AJAXy interface. Oh well, I should really get that working again.&lt;/p&gt;
&lt;p&gt;This lightning talk was a hit. Several people &lt;em&gt;cheered&lt;/em&gt;! Great job, Jesse.&lt;/p&gt;
&lt;h3&gt;&lt;a name="others_talks" id="others_talks"&gt;Others' Talks&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a name="others_talks" id="others_talks"&gt;&lt;/a&gt;My favorite talk, by far, was &lt;a href="http://thelackthereof.org"&gt;Brock Wilcox&lt;/a&gt;'s &lt;a href="http://thelackthereof.org/CGI_Inspect"&gt;CGI::Inspect talk&lt;/a&gt;. As I said during the talk, when I wrote &lt;a href="http://search.cpan.org/perldoc?Carp::REPL"&gt;Carp::REPL&lt;/a&gt;, I was &lt;em&gt;actually&lt;/em&gt; aiming for exactly what &lt;a href="http://search.cpan.org/perldoc?CGI::Inspect"&gt;CGI::Inspect&lt;/a&gt; &lt;em&gt;is&lt;/em&gt;. And I meant it! About two years ago, it was mentioned to me how when there's an error in your Django application, it opens an AJAXy REPL for you. I figured out how to do some of that - REPL on error - but I never actually hooked it up to &lt;a href="http://jifty.org"&gt;Jifty&lt;/a&gt;. Now I don't have to. Bravo, Brock!&lt;/p&gt;
&lt;p&gt;Another talk I enjoyed was &lt;a href="http://rjbs.manxome.org/"&gt;Ricardo Signes&lt;/a&gt;'s &lt;a href="http://yapc10.org/yn2009/talk/1942"&gt;Git is Easy talk&lt;/a&gt;. I knew most of the material presented, but since seeing that talk I have had a lot more confidence in using git. In particular, remotes now make sense to me. I also now use &lt;a href="http://gitx.frim.nl/"&gt;GitX&lt;/a&gt; to visualize where other developers are relative to me.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://slowass.net/~scott/"&gt;Scott Walter&lt;/a&gt;'s &lt;a href="http://yapc10.org/yn2009/talk/1974"&gt;Perl in Vegas talk&lt;/a&gt; was fascinating. He drew an interesting parallel between the incredible strictures of Vegas slot machines versus America's completely opaque and mostly unregulated voting machines. One strange requirement of the slot machines is that code must be compiled. Though Perl is an interpreted language, it provides a &lt;a href="http://www.perl.com/doc/manual/html/utils/perlcc.html"&gt;perlcc&lt;/a&gt; utility to "compile" the code.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://weftsoar.net/~hdp/"&gt;Hans Dieter Pearcey&lt;/a&gt;'s &lt;a href="http://yapc10.org/yn2009/talk/1986"&gt;Dist::Zilla - Automating quality since 2008&lt;/a&gt; reminded me of its excellent plugin-centric design:&lt;/p&gt;
&lt;img src="http://sartak.org/misc/blog/dist-zilla-plugins.png"&gt;
&lt;p&gt;This slide &lt;em&gt;directly&lt;/em&gt; caused me to submit a talk about &lt;a href="http://sartak.org/talks/yapc-asia-2009/api-design/abstract.txt"&gt;API Design&lt;/a&gt; to &lt;a href="http://conferences.yapcasia.org/ya2009/"&gt;YAPC::Asia 2009&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Finally, &lt;a href="http://bulknews.vox.com/"&gt;miyagawa&lt;/a&gt;'s &lt;a href="http://yapc10.org/yn2009/talk/2018"&gt;Build a desktop application with Perl, HTTP::Engine, SQLite and jQuery&lt;/a&gt; talk was exciting. I've been working toward using his &lt;a href=""&gt;perl-app-builder&lt;/a&gt; for TAEB since he &lt;a href="http://remediecode.org/2009/06/binary-builds-for-os-x-leopard-users.html"&gt;blogged about it&lt;/a&gt;. The talk showed how we can write standalone, web-based, GUI apps, in Perl, without inflicting CPAN on our users. Because Perl has been a web language ever since the web has had languages, the tools for generating HTML, serving pages, etc. are &lt;em&gt;very good&lt;/em&gt;. The traditional GUI tools are mediocre at best. They are why my applications have been strictly web- and curses-based.&lt;/p&gt;
&lt;h3&gt;Thanks!&lt;/h3&gt;
&lt;p&gt;Thank you Robert Blackwell, Casey West, Tom Moertel, Dan Wright, and anyone else who helped! This YAPC was fantastic.&lt;/p&gt;
&lt;p&gt;If you have never been to YAPC, you should seriously consider going to the next one!&lt;/p&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img&gt;&lt;/div&gt;</content>
    <category term="moose yapc cgi-inspect perl TAEB dist-zilla"/>
    <published>2009-06-29T03:13:00Z</published>
    <updated>2009-06-29T03:13:00Z</updated>
    <author>
      <name>Shawn M Moore</name>
    </author>
    <id>tag:perlsphere.net,2006:tag:blogger.com,1999:blog-8877785637728778345.post-8971504042521670601</id>
  </entry>
  <entry>
    <title>Moose fairy dust: Now with diagrams!</title>
    <link rel="alternate" href="http://transfixedbutnotdead.com/2009/06/28/moose-fairy-dust-now-with-diagrams/" type="text/html"/>
    <summary type="text">Moritz Lenz mentions in his excellent Perlgeek.de blog that there is not
enough pictures being used alongside posts in the Perl blogosphere.

Moritz is absolutely correct so I’ll make immediate amends by reproducing
the core of my last post about how Moose Roles implemented singleton
methods with some helpful diagrams.

So first here is the initial Animal class code again:


use MooseX::Declare;

class Animal {
    method walk { "unknown" }
    method wild { "wild?... I'm bliming livid!" }
}

my $baz = Animal-&gt;new;

Here is a diagram which shows the object ($baz) &amp; each class with its
methods:

fig1

From this we can see that:

  * $baz is the instantiated object of the Animal class.

  * The Animal class contains all the methods we defined (along with
    “new” &amp; “meta”) and its superclass is Moose::Object.

NB. Moose::Object is the ultimate superclass which all Moose classes
relate back to. In Moose::Object we can see all the base methods.

Next is the DoesHuman role and it being applied to the $baz object:


role DoesHuman {
    method walk { "when not drunk!" }
    method legs { 2 }
}

DoesHuman-&gt;meta-&gt;apply( $baz );

fig2

And finally this is how the class relationship now looks for $baz object
after the above role was applied:
fig3

The anonymous class was created when the DoesHuman role was applied to
$baz object and it now stands proudly at the front of the inheritance
chain for $baz object.

Thus we have added singleton method(s) to an object by using Moose roles.

This is a clear example of a picture being definitely worth a thousand
words ;-)</summary>
    <content type="html">&lt;div class="snap_preview"&gt;&lt;br /&gt;
&lt;p&gt;Moritz Lenz mentions in his excellent &lt;a href="http://perlgeek.de/blog-en/misc/am-i-a-stone-man.html"&gt;Perlgeek.de blog&lt;/a&gt; that there is not enough pictures being used alongside posts in the Perl blogosphere.&lt;/p&gt;
&lt;p&gt;Moritz is absolutely correct so I’ll make immediate amends by reproducing the core of my last post about &lt;a href="http://transfixedbutnotdead.com/2009/06/19/moose-fairy-dust/"&gt;how Moose Roles implemented singleton methods&lt;/a&gt; with some helpful diagrams.&lt;/p&gt;
&lt;p&gt;So first here is the initial Animal class code again:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;

use MooseX::Declare;

class Animal {
    method walk { "unknown" }
    method wild { "wild?... I'm bliming livid!" }
}

my $baz = Animal-&amp;gt;new;
&lt;/pre&gt;
&lt;p&gt;Here is a diagram which shows the object ($baz) &amp;amp; each class with its methods:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.flickr.com/photos/draegtun/3668317009/" title="fig1 by draegtun, on Flickr"&gt;&lt;img src="http://farm4.static.flickr.com/3604/3668317009_64060cbd5c_o.jpg" alt="fig1"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;From this we can see that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$baz is the instantiated object of the Animal class.&lt;/li&gt;
&lt;li&gt;The Animal class contains all the methods we defined (along with “new” &amp;amp; “meta”) and its superclass is Moose::Object.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;NB. Moose::Object is the ultimate superclass which all Moose classes relate back to. In Moose::Object we can see all the base methods.&lt;/p&gt;
&lt;p&gt;Next is the DoesHuman role and it being applied to the $baz object:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;

role DoesHuman {
    method walk { "when not drunk!" }
    method legs { 2 }
}

DoesHuman-&amp;gt;meta-&amp;gt;apply( $baz );
&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://www.flickr.com/photos/draegtun/3668316549/" title="fig2 by draegtun, on Flickr"&gt;&lt;img src="http://farm3.static.flickr.com/2452/3668316549_68de35e8a0_o.jpg" alt="fig2"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And finally this is how the class relationship now looks for $baz object after the above role was applied:&lt;br /&gt;
&lt;a href="http://www.flickr.com/photos/draegtun/3669124144/" title="fig3 by draegtun, on Flickr"&gt;&lt;img src="http://farm4.static.flickr.com/3637/3669124144_661a4ab547_o.jpg" alt="fig3"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The anonymous class was created when the DoesHuman role was applied to $baz object and it now stands proudly at the front of the inheritance chain for $baz object.&lt;/p&gt;
&lt;p&gt;Thus we have added singleton method(s) to an object by using Moose roles.&lt;/p&gt;
&lt;p&gt;This is a clear example of a picture being definitely worth a thousand words &lt;img src="http://s.wordpress.com/wp-includes/images/smilies/icon_wink.gif" alt=";-)"&gt;&lt;/p&gt;
&lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/draegtun.wordpress.com/450/"&gt;&lt;img alt="" src="http://feeds.wordpress.com/1.0/comments/draegtun.wordpress.com/450/"&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/draegtun.wordpress.com/450/"&gt;&lt;img alt="" src="http://feeds.wordpress.com/1.0/delicious/draegtun.wordpress.com/450/"&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/draegtun.wordpress.com/450/"&gt;&lt;img alt="" src="http://feeds.wordpress.com/1.0/stumble/draegtun.wordpress.com/450/"&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/draegtun.wordpress.com/450/"&gt;&lt;img alt="" src="http://feeds.wordpress.com/1.0/digg/draegtun.wordpress.com/450/"&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/draegtun.wordpress.com/450/"&gt;&lt;img alt="" src="http://feeds.wordpress.com/1.0/reddit/draegtun.wordpress.com/450/"&gt;&lt;/a&gt; &lt;img alt="" src="http://stats.wordpress.com/b.gif?host=transfixedbutnotdead.com&amp;amp;blog=351142&amp;amp;post=450&amp;amp;subd=draegtun&amp;amp;ref=&amp;amp;feed=1"&gt;&lt;/div&gt;</content>
    <category term="Programming moose MooseX::Declare perl roles singleton methods"/>
    <published>2009-06-28T19:24:46Z</published>
    <updated>2009-06-28T19:24:46Z</updated>
    <author>
      <name>draegtun</name>
    </author>
    <id>tag:perlsphere.net,2006:http://transfixedbutnotdead.com/?p=450</id>
    <link xmlns="http://purl.org/atom/ns#" rel="enclosure" type="" href="" length=""/>
    <link xmlns="http://purl.org/atom/ns#" rel="enclosure" type="" href="" length=""/>
    <link xmlns="http://purl.org/atom/ns#" rel="enclosure" type="" href="" length=""/>
    <link xmlns="http://purl.org/atom/ns#" rel="enclosure" type="" href="" length=""/>
  </entry>
  <entry>
    <title>Perl 5 Personal Service</title>
    <link rel="alternate" href="http://szabgab.com/blog/2009/06/1246181645.html" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">I thought about this on and off for some time but have not done anything
with it yet. Maybe someone else with better ideas can do something like
this.

I was sondering if it would be interesting to create a web application
that on one hand would allow people using Perl to get some personalized
services on the other hand it would allow the ongoing collection of some
statistical data about the Perl community and about the usage of Perl.

The services that would be offered could include alert when one of the
modules used by the person gets a new version. It could include a
Google-alert like service when the modules are mentioned in one of the
perl related sources.

It could allow the notification about Perl related events in their
city/country/continent.

It could allow people to mark their favorite modules. It could allow to
follow other people whose judgement they trust for modules which in turn
would provide a better way to search for modules on CPAN for everyone.

It would allow an on-going survey similar to the one that was a year or
two ago but that would allow people to change the data they provide and
allow the site maintainers to provide information regarding the changes
as well.</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml"><p>I thought about this on and off for some time but have not done anything with it yet. Maybe someone else with better ideas can do something like this.</p>
<p>I was sondering if it would be interesting to create a web application that on one hand would allow people using Perl to get some personalized services on the other hand it would allow the ongoing collection of some statistical data about the Perl community and about the usage of Perl.</p>
<p>The services that would be offered could include alert when one of the modules used by the person gets a new version. It could include a Google-alert like service when the modules are mentioned in one of the perl related sources.</p>
<p>It could allow the notification about Perl related events in their city/country/continent.</p>
<p>It could allow people to mark their favorite modules. It could allow to <i>follow</i> other people whose judgement they trust for modules which in turn would provide a better way to search for modules on CPAN for everyone.</p>
<p>It would allow an on-going survey similar to the one that was a year or two ago but that would allow people to change the data they provide and allow the site maintainers to provide information regarding the changes as well.</p></div>
    </content>
    <published>2009-06-28T05:34:05-07:00</published>
    <updated>2009-06-28T05:34:05-07:00</updated>
    <author>
      <name>nobody</name>
    </author>
    <id>tag:perlsphere.net,2006:ylxaLesS3hGLuL_IPm7D0g_43793273d57cf52b68316116ffbd01a4</id>
  </entry>
  <entry>
    <title>Introducing CPANHQ and a Response to Limbic Region's "Improving search.cpan.org (Advanced Search)"</title>
    <link rel="alternate" href="http://community.livejournal.com/shlomif_tech/28209.html" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">Limbic Region recently wrote a post on his use Perl journal titled
"Improving search.cpan.org (Advanced Search)". The post concludes by
saying that "Feel free to add your own [ideas] - I know someone who may
actually be motivated to implement some of them as an alternate to
search.cpan.org is reading :-)". Since I talked with L~R about CPANHQ, a
seacrch.capn.org alternative in question, that I have been contributing
to, I can assume meant me.

Before I reply to L~R's points, let me introduce CPANHQ. As documented in
the first and only wiki page it has so far (which I wrote two days ago),
"CPANHQ aims to be a community-driven, meta-data-enhanced alternative to
such sites as http://search.cpan.org/ and http://kobesearch.cpan.org/.
Currently, the functionality is very basic, but we have great ambitions."

I learned about CPANHQ by overhearing a conversation on Freenode's #perl
channel. I joined the effort, and made several enhancements to the
Catalyst and DBIx-Class-based code, which was a useful learning
experience. The functionality is still very basic, and there's a lot of
work to do, so any help would be appreciated. Just fork the github
repository ( or my repository, which I tend to keep somewhat more
up-to-date ), and play with the code.

Now back to L~R's suggestions. At first I was a bit sceptical of them and
they seemed like an overkill, and not really useful. When I'm using
search.cpan.org to search for a distribution, either I know the name of
the module that I'm looking for and just perform a search to be directed
to the location of the exact page, or I usually find the order of the
search sufficient for my needs.

However, on a second reading, it seems like what Limbic suggests (like
being able to sort results by Kwalitee, creation date, number of
downloads, last update date, rating, etc., providing a code search, or
recommendations) actually has some merit and should be considered. One
thing I'm sure about is that the default CPAN search should remain
simple, while only giving an option for an advances search using a
different form, where it might be possible to formulate a more complex
query using a specialised language. Otherwise, if we complicate the
existing search, it could prove confusing to many users.

L~R's suggestions remind me of my CPAN Module-Rank thought experiment,
that aimed to define an automatically calculated metric for the relevance
of CPAN modules.

L~R later referred me to a post to Perlmonks.org titled "Advanced CPAN
Search?" where someone asks a similar question.

To sum up, please consider monitoring or even contributing to CPANHQ if
you want to improve the future of finding stuff and interacting with
CPAN. It seems that some people have issue with the current CPAN search
state-of-the-art, and would like to see it improved. We'd be happy to
hear what you think.</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml"><p>Limbic Region recently wrote a post on his use Perl journal titled <a href="http://use.perl.org/~Limbic+Region/journal/39132">"Improving search.cpan.org (Advanced Search)"</a>. The post concludes by saying that "Feel free to add your own [ideas] - I know someone who may actually be motivated to implement some of them as an alternate to search.cpan.org is reading :-)". Since I talked with L~R about CPANHQ, a seacrch.capn.org alternative in question, that I have been contributing to, I can assume meant me.</p>
<p>Before I reply to L~R's points, let me introduce <a href="http://github.com/bricas/cpanhq/tree/master">CPANHQ</a>. As documented in <a href="http://wiki.github.com/bricas/cpanhq">the first and only wiki page it has so far</a> (which I wrote two days ago), "CPANHQ aims to be a community-driven, meta-data-enhanced alternative to such sites as <a href="http://search.cpan.org/">http://search.cpan.org/</a> and <a href="http://kobesearch.cpan.org/">http://kobesearch.cpan.org/</a>. Currently, the functionality is very basic, but we have great ambitions."</p>
<p>I learned about CPANHQ by overhearing a conversation on Freenode's #perl channel. I joined the effort, and made several enhancements to the <a href="http://www.catalystframework.org/">Catalyst</a> and <a href="http://www.perlfoundation.org/perl5/index.cgi?dbix_class">DBIx-Class</a>-based code, which was a useful learning experience. The functionality is still very basic, and there's a lot of work to do, so any help would be appreciated. Just fork the github repository ( or <a href="http://github.com/shlomif/cpanhq/tree/master">my repository</a>, which I tend to keep somewhat more up-to-date ), and play with the code.</p>
<p>Now back to L~R's suggestions. At first I was a bit sceptical of them and they seemed like an overkill, and not really useful. When I'm using search.cpan.org to search for a distribution, either I know the name of the module that I'm looking for and just perform a search to be directed to the location of the exact page, or I usually find the order of the search sufficient for my needs.</p>
<p>However, on a second reading, it seems like what Limbic suggests (like being able to sort results by Kwalitee, creation date, number of downloads, last update date, rating, etc., providing a code search, or recommendations) actually has some merit and should be considered. One thing I'm sure about is that the default CPAN search should remain simple, while only giving an option for an advances search using a different form, where it might be possible to formulate a more complex query using a specialised language. Otherwise, if we complicate the existing search, it could prove confusing to many users.</p>
<p>L~R's suggestions remind me of my <a href="http://perl.net.au/wiki/Finding_a_Module_on_CPAN/Module-Rank">CPAN Module-Rank</a> thought experiment, that aimed to define an automatically calculated metric for the relevance of CPAN modules.</p>
<p>L~R later referred me to <a href="http://perlmonks.org/?node_id=773093">a post to Perlmonks.org titled "Advanced CPAN Search?"</a> where someone asks a similar question.</p>
<p>To sum up, please consider monitoring or even contributing to CPANHQ if you want to improve the future of finding stuff and interacting with CPAN. It seems that some people have issue with the current CPAN search state-of-the-art, and would like to see it improved. We'd be happy to hear what you think.</p></div>
    </content>
    <category term="search limbic region dbix-class cpanhq catalyst region kobesearch perl search.cpan.org limbic github cpan"/>
    <published>2009-06-28T11:58:28Z</published>
    <updated>2009-06-28T11:58:28Z</updated>
    <author>
      <name>shlomif@iglu.org.il (Shlomi Fish)</name>
    </author>
    <id>tag:perlsphere.net,2006:http://community.livejournal.com/shlomif_tech/28209.html</id>
  </entry>
  <entry>
    <title>Test::Aggregate::Nested Almost Done</title>
    <link rel="alternate" href="http://use.perl.org/~Ovid/journal/39184?from=rss" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">Boy oh boy, does nested TAP make Test::Aggregate much cleaner. It's not
uploaded yet -- still documenting and working out corner cases for the
new Test::Aggregate::Nexted -- but here's what aggregated test output
used to look like. Remember, this is five separate test programs. Can you
tell where each starts and ends?

  Test-Aggregate  $ prove -lv t/pre_post.t
  t/pre_post.t .. # ******** running tests for aggtests/check_plan.t
  ********

  ok 1 - aggtests/check_plan.t ***** 1
  ok 2 - aggtests/check_plan.t ***** 2
  ok 3 # skip checking plan (aggtests/check_plan.t ***** 3)
  ok 4 - env variables should not hang around
  ok 5 - aggtests/check_plan.t ***** 4
  ok 6 - findbin is reinitialized for every test
  ok 7 # skip Testing skip all
  #   ok - aggtests/check_plan.t (1 out of 5)
  # ******** running tests for aggtests/findbin.t ********
  #   ok - aggtests/findbin.t (2 out of 5)
  # ******** running tests for aggtests/skip_all.t ********
  #   ok - aggtests/skip_all.t (3 out of 5)
  # ******** running tests for aggtests/slow_load.t ********
  ok 8 - slow loading module loaded
  ok 9 - env variables should not hang around
  ok 10 - subs work!
  ok 11 - Startup should be called once
  ok 12 - ... as should shutdown
  ok 13 - Setup should be called once for each test program
  ok 14 - ... as should teardown
  1..14
  #   ok - aggtests/slow_load.t (4 out of 5)
  # ******** running tests for aggtests/subs.t ********
  #   ok - aggtests/subs.t (5 out of 5)
  ok
  All tests successful.
  Files=1, Tests=14,  1 wallclock secs ( 0.02 usr  0.01 sys +  0.11
  cusr  0.01 csys =  0.15 CPU)
  Result: PASS

Now let's run that with Test::Aggregate::Nested (requires the development
version of Test::More):

  Test-Aggregate  $ prove -lv t/pre_post_nested.t
  t/pre_post_nested.t ..
  1..5
  1..5
  1..0 # SKIP Testing skip all
  ok 1 # skip Testing skip all
  1..1
  ok 1 - findbin is reinitialized for every test
  ok 2 - aggtests/findbin.t
  1..1
  ok 1 - subs work!
  ok 3 - aggtests/subs.t
  1..2
  ok 1 - slow loading module loaded
  ok 2 - env variables should not hang around
  ok 4 - aggtests/slow_load.t
  1..5
  ok 1 - aggtests/check_plan.t ***** 1
  ok 2 - aggtests/check_plan.t ***** 2
  ok 3 # skip checking plan (aggtests/check_plan.t ***** 3)
  ok 4 - env variables should not hang around
  ok 5 - aggtests/check_plan.t ***** 4
  ok 5 - aggtests/check_plan.t
  ok 1 - nested tests
  ok 2 - Startup should be called once
  ok 3 - ... as should shutdown
  ok 4 - Setup should be called once for each test program
  ok 5 - ... as should teardown
  ok
  All tests successful.
  Files=1, Tests=5,  2 wallclock secs ( 0.03 usr  0.01 sys +  0.11
  cusr  0.02 csys =  0.17 CPU)
  Result: PASS

Much, much nicer. As an added bonus, plans can now be cleanly asserted. I
hope to have it on github soon, and later on the CPAN.</div>
    </summary>
    <content type="html">&lt;p&gt;Boy oh boy, does nested TAP make &lt;tt&gt;Test::Aggregate&lt;/tt&gt; much cleaner. It's not uploaded yet -- still documenting and working out corner cases for the new &lt;tt&gt;Test::Aggregate::Nexted&lt;/tt&gt; -- but here's what aggregated test output used to look like. Remember, this is five separate test programs. Can you tell where each starts and ends?&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;
&lt;p&gt;&lt;tt&gt;Test-Aggregate&amp;nbsp; $ prove -lv t/pre_post.t&lt;br /&gt;
t/pre_post.t &lt;nobr&gt;&lt;wbr /&gt;&lt;/nobr&gt;.. # ******** running tests for aggtests/check_plan.t ********&lt;br /&gt;
&lt;br /&gt;
ok 1 - aggtests/check_plan.t ***** 1&lt;br /&gt;
ok 2 - aggtests/check_plan.t ***** 2&lt;br /&gt;
ok 3 # skip checking plan (aggtests/check_plan.t ***** 3)&lt;br /&gt;
ok 4 - env variables should not hang around&lt;br /&gt;
ok 5 - aggtests/check_plan.t ***** 4&lt;br /&gt;
ok 6 - findbin is reinitialized for every test&lt;br /&gt;
ok 7 # skip Testing skip all&lt;br /&gt;
#&amp;nbsp; &amp;nbsp; &amp;nbsp;ok - aggtests/check_plan.t (1 out of 5)&lt;br /&gt;
# ******** running tests for aggtests/findbin.t ********&lt;br /&gt;
#&amp;nbsp; &amp;nbsp; &amp;nbsp;ok - aggtests/findbin.t (2 out of 5)&lt;br /&gt;
# ******** running tests for aggtests/skip_all.t ********&lt;br /&gt;
#&amp;nbsp; &amp;nbsp; &amp;nbsp;ok - aggtests/skip_all.t (3 out of 5)&lt;br /&gt;
# ******** running tests for aggtests/slow_load.t ********&lt;br /&gt;
ok 8 - slow loading module loaded&lt;br /&gt;
ok 9 - env variables should not hang around&lt;br /&gt;
ok 10 - subs work!&lt;br /&gt;
ok 11 - Startup should be called once&lt;br /&gt;
ok 12 - &lt;nobr&gt;&lt;wbr /&gt;&lt;/nobr&gt;... as should shutdown&lt;br /&gt;
ok 13 - Setup should be called once for each test program&lt;br /&gt;
ok 14 - &lt;nobr&gt;&lt;wbr /&gt;&lt;/nobr&gt;... as should teardown&lt;br /&gt;
1..14&lt;br /&gt;
#&amp;nbsp; &amp;nbsp; &amp;nbsp;ok - aggtests/slow_load.t (4 out of 5)&lt;br /&gt;
# ******** running tests for aggtests/subs.t ********&lt;br /&gt;
#&amp;nbsp; &amp;nbsp; &amp;nbsp;ok - aggtests/subs.t (5 out of 5)&lt;br /&gt;
ok&lt;br /&gt;
All tests successful.&lt;br /&gt;
Files=1, Tests=14,&amp;nbsp; 1 wallclock secs ( 0.02 usr&amp;nbsp; 0.01 sys +&amp;nbsp; 0.11 cusr&amp;nbsp; 0.01 csys =&amp;nbsp; 0.15 CPU)&lt;br /&gt;
Result: PASS&lt;/tt&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now let's run that with &lt;tt&gt;Test::Aggregate::Nested&lt;/tt&gt; (requires the development version of &lt;a href="http://search.cpan.org/~mschwern/Test-Simple-0.89_01/"&gt;Test::More&lt;/a&gt;):&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;
&lt;p&gt;&lt;tt&gt;Test-Aggregate&amp;nbsp; $ prove -lv t/pre_post_nested.t&lt;br /&gt;
t/pre_post_nested.t &lt;nobr&gt;&lt;wbr /&gt;&lt;/nobr&gt;..&lt;br /&gt;
1..5&lt;br /&gt;
&amp;nbsp; &amp;nbsp; 1..5&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 1..0 # SKIP Testing skip all&lt;br /&gt;
&amp;nbsp; &amp;nbsp; ok 1 # skip Testing skip all&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 1..1&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ok 1 - findbin is reinitialized for every test&lt;br /&gt;
&amp;nbsp; &amp;nbsp; ok 2 - aggtests/findbin.t&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 1..1&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ok 1 - subs work!&lt;br /&gt;
&amp;nbsp; &amp;nbsp; ok 3 - aggtests/subs.t&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 1..2&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ok 1 - slow loading module loaded&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ok 2 - env variables should not hang around&lt;br /&gt;
&amp;nbsp; &amp;nbsp; ok 4 - aggtests/slow_load.t&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 1..5&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ok 1 - aggtests/check_plan.t ***** 1&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ok 2 - aggtests/check_plan.t ***** 2&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ok 3 # skip checking plan (aggtests/check_plan.t ***** 3)&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ok 4 - env variables should not hang around&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ok 5 - aggtests/check_plan.t ***** 4&lt;br /&gt;
&amp;nbsp; &amp;nbsp; ok 5 - aggtests/check_plan.t&lt;br /&gt;
ok 1 - nested tests&lt;br /&gt;
ok 2 - Startup should be called once&lt;br /&gt;
ok 3 - &lt;nobr&gt;&lt;wbr /&gt;&lt;/nobr&gt;... as should shutdown&lt;br /&gt;
ok 4 - Setup should be called once for each test program&lt;br /&gt;
ok 5 - &lt;nobr&gt;&lt;wbr /&gt;&lt;/nobr&gt;... as should teardown&lt;br /&gt;
ok&lt;br /&gt;
All tests successful.&lt;br /&gt;
Files=1, Tests=5,&amp;nbsp; 2 wallclock secs ( 0.03 usr&amp;nbsp; 0.01 sys +&amp;nbsp; 0.11 cusr&amp;nbsp; 0.02 csys =&amp;nbsp; 0.17 CPU)&lt;br /&gt;
Result: PASS&lt;/tt&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;p&gt;Much, much nicer. As an added bonus, plans can now be cleanly asserted. I hope to have it on &lt;a href="http://github.com/Ovid/test-aggregate/tree/master"&gt;github&lt;/a&gt; soon, and later on the CPAN.&lt;/p&gt;</content>
    <category term="journal"/>
    <published>2009-06-28T09:48:55Z</published>
    <updated>2009-06-28T09:48:55Z</updated>
    <author>
      <name>Ovid</name>
    </author>
    <id>tag:perlsphere.net,2006:http://use.perl.org/~Ovid/journal/39184?from=rss</id>
  </entry>
  <entry>
    <title>More theft from Padre</title>
    <link rel="alternate" href="http://code-and-hacks.blogspot.com/2009/06/more-theft-from-padre.html" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">I was pleasantly surprise at the positive response to my last post on
Stealing from Padre for Vim--particularly from the Padre developers!
Seems they had hoped/planned on separating some of the tools out of the
Padre core from the beginning (and many seem to be vimmers). With their
blessing and encouragement, I have pulled the editor independent parts of
their PPI::Task tools into its own
distribution--PPIx::EditorTools--available now on CPAN. I also adapted
the current version of Padre to work wit the external package and
released App::EditorTools to provide a command line interface for those
editors that need it (i.e., vim). I'll post another screencast and the
Vim scripts needed to integrate it shortly.

As a result, I'm depreciating App::LexVarRepl--which was only ever
available on github.

Sorry for the short post which is light on links and code, but we are in
the process of moving so I'm dedicating the few moments I have to coding
this rather than blogging about it...for now at least! [IMAGE]</div>
    </summary>
    <content type="text">I was pleasantly surprise at the positive response to my last post on Stealing from Padre for Vim--particularly from the Padre developers! Seems they had hoped/planned on separating some of the tools out of the Padre core from the beginning (and many seem to be vimmers). With their blessing and encouragement, I have pulled the editor independent parts of their PPI::Task tools into its own distribution--PPIx::EditorTools--available now on CPAN. I also adapted the current version of Padre to work wit the external package and released App::EditorTools to provide a command line interface for those editors that need it (i.e., vim). I'll post another screencast and the Vim scripts needed to integrate it shortly.&lt;br /&gt;
&lt;br /&gt;
As a result, I'm depreciating App::LexVarRepl--which was only ever available on github.&lt;br /&gt;
&lt;br /&gt;
Sorry for the short post which is light on links and code, but we are in the process of moving so I'm dedicating the few moments I have to coding this rather than blogging about it...for now at least!
&lt;div class="blogger-post-footer"&gt;&lt;img&gt;&lt;/div&gt;</content>
    <category term="vim perl"/>
    <published>2009-06-28T05:54:00Z</published>
    <updated>2009-06-28T05:54:00Z</updated>
    <author>
      <name>Mark</name>
    </author>
    <id>tag:perlsphere.net,2006:tag:blogger.com,1999:blog-533407576171979325.post-8917847753781731799</id>
  </entry>
  <entry>
    <title>GSoC Bird of Feather Session at OpenSourceBridge</title>
    <link rel="alternate" href="http://leto.net/dukeleto.pl/2009/06/gsoc-bird-of-feather-session-at-opensourcebridge.html" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">The first day of OpenSourceBridge was amazing and we finished it off by
having a Bird of Feather session for people involved and/or interested in
Google Summer of Code.

gsoc_bof_osbridge1.jpgI know that it was very helpful to hear and talk
about how the current GSoC is going with my fellow organization admins,
mentors and students. Cat Allman, Ellen Ko and Leslie Hawthorn
contributed a lot of knowledge and experience about how to deal with
things when they go pear-shaped, and I even met an organization and
mentor that are my neighbors! Some of the great ideas that came out of
this were that first-year organizations would be greatly helped by having
a "buddy" organization that has been involved in GSoC before, so that a
brand-new organization admin can have a friendly ear to bend when they
need help. I mentioned this because I usually bend Bart Massey's ear when
I need some GSoC guidance, and I thought that other first-year admins
could also greatly benefit from something like this.

I was a mentor for the The Perl Foundation last year, with the Math::GSL
project and this year I find myself the organization admin as well as a
mentor for the Math::Primality project, which implements advanced
prime-checking algorithms for Perl 5. It is definitely a big step to go
from mentor to admin and meeting up with people in the same situation
really helps!

I will definitely be going to OpenSourceBridge next year and hope that we
have a GSoC meetup there again.</div>
    </summary>
    <content type="html">&lt;br /&gt;
The first day of &lt;a href="http://opensourcebridge.org/"&gt;OpenSourceBridge&lt;/a&gt; was amazing and we finished it off by having a &lt;a href="http://opensourcebridge.org/sessions/282"&gt;Bird of Feather session&lt;/a&gt; for people involved and/or interested in &lt;a href="http://code.google.com/soc/"&gt;Google Summer of Code&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="mt-enclosure mt-enclosure-image"&gt;&lt;a href="http://leto.net/dukeleto.pl/pics/2009/gsoc_bof_osbridge1.html"&gt;&lt;img src="http://leto.net/dukeleto.pl/pics/2009/gsoc_bof_osbridge1-thumb-400x300.jpg" alt="gsoc_bof_osbridge1.jpg"&gt;&lt;/a&gt;&lt;/span&gt;I know that it was very helpful to hear and talk about how the current GSoC is going with my fellow organization admins, mentors and students. Cat Allman, Ellen Ko and &lt;a href="http://www.hawthornlandings.org/"&gt;Leslie Hawthorn&lt;/a&gt; contributed a lot of knowledge and experience about how to deal with things when they go pear-shaped, and I even met an organization and mentor that are my neighbors! Some of the great ideas that came out of this were that first-year organizations would be greatly helped by having a "buddy" organization that has been involved in GSoC before, so that a brand-new organization admin can have a friendly ear to bend when they need help. I mentioned this because I usually bend &lt;a href="http://web.cecs.pdx.edu/%7Ebart/"&gt;Bart Massey&lt;/a&gt;'s ear when I need some GSoC guidance, and I thought that other first-year admins could also greatly benefit from something like this.&lt;br /&gt;
&lt;br /&gt;
I was a mentor for the &lt;a href="http://www.perlfoundation.org/"&gt;The Perl Foundation&lt;/a&gt; last year, with the &lt;a href="http://leto.net/code/Math-GSL/"&gt;Math::GSL&lt;/a&gt; project and this year I find myself the organization admin as well as a mentor for the &lt;a href="http://github.com/leto/math--primality/tree/master"&gt;Math::Primality&lt;/a&gt; project, which implements advanced prime-checking algorithms for Perl 5. It is definitely a big step to go from mentor to admin and meeting up with people in the same situation really helps!&lt;br /&gt;
&lt;br /&gt;
I will definitely be going to OpenSourceBridge next year and hope that we have a GSoC meetup there again.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</content>
    <category term="gsoc osbridge gsoc2009 osb09"/>
    <published>2009-06-27T21:25:21Z</published>
    <updated>2009-06-27T21:25:21Z</updated>
    <author>
      <name>Jonathan Leto</name>
    </author>
    <id>tag:perlsphere.net,2006:tag:leto.net,2009:/dukeleto.pl//9.193</id>
  </entry>
  <entry>
    <title>replacing github with a very small shell script</title>
    <link rel="alternate" href="http://rjbs.manxome.org/rubric/entry/1776" type="text/html"/>
    <summary type="text">...not really. I still really like using GitHub, and (obviously) they do
much more than I could churn out in a weekend, let alone an hour. Also, I
used Perl.

That said, we've recently stopped using them for work code. Things just
didn't work out. I hope we can migrate back to them someday, but for now
we needed to make a change.

We're using gitosis, now. I've used it before, and it's a really
fantastic little tool. As with most good tools, it does one job and does
it very well. That means that it doesn't get in the way of the workflow
you want to use.

That also means it doesn't go out of its way to make any particular
workflow easy. That's fine!

I had originally thought we'd be fine having users share their repos from
their home directories, as everyone has read access to every other user's
homedir. This ended up being tedious and stupid, for a number of reasons,
including that each user puts his code in a different subdirectory under
home. (Each choice other than my own just seems so unnatural!)

When we were using GitHub, we had a program that did something like this:

  * ensure that master-user/repository existed

  * fork it to you/repository if needed

  * clone you/repository to cwd

I updated this program to work on our gitosis setup with uniform per-user
repository URLs. After all, a GitHub fork is just a clone with a tiny
smidge of added metadata, near as I can tell.

The master user in our scenario is gitosis@git.example.com, and every
user also has a login on that box. Here's the program:

#!/usr/bin/perl
use strict;
use warnings;

{
  package Git::Hubclone;
  use base 'App::Cmd::Simple';

  use autodie qw(:default :system);
  use Getopt::Long::Descriptive;
  use Sys::Hostname::Long;

  my $HOST = q{git.example.com};

  sub usage_desc { '%c %o &lt;repo&gt;' }
  sub opt_spec {
    return (
      [ 'bare-only', "do not create a local clone, only hub copy" ],
    );
  }

  sub validate_args {
    my ($self, $opt, $args) = @_;

    my $user = $ENV{USER};
    my $repo = $args-&gt;[0];

    $self-&gt;usage_error("no repo name given") unless $repo;
    $self-&gt;usage_error("do not run as root") if $user eq 'root';
    $self-&gt;usage_error("illegal repo name")  if $repo !~ /\A[-_a-z0-9]+\z/;

    if (! $opt-&gt;{bare_only}) {
      $self-&gt;usage_error("already in a git repository!")       if -d '.git';
      $self-&gt;usage_error("directory './$repo' already exists") if -d $repo;
    }
  }

  sub run {
    my ($self, $opt, $args) = @_;

    my $user = $ENV{USER};
    my $repo = $args-&gt;[0];

    if (hostname_long eq $HOST) {
      require File::HomeDir;
      require File::Path;
      require File::Spec;

      my $git_dir  = File::Spec-&gt;catfile( File::HomeDir-&gt;my_home, 'git' );
      my $repo_dir = File::Spec-&gt;catfile( $git_dir, "$repo.git" );

      unless (-d $repo_dir) {
        File::Path::mkpath($git_dir);
        system qq{git clone --bare gitosis\@$HOST:$repo.git $repo_dir};
      }
    } else {
      system "ssh $HOST git hubclone --bare-only $repo";
    }

    unless ($opt-&gt;{bare_only}) {
      my $clone_cmd = qq{git clone $user\@$HOST:git/$repo.git};
      system $clone_cmd;
    }
  }
}

Git::Hubclone-&gt;import;
Git::Hubclone-&gt;run;

I should really fix up App::Cmd::Simple to not require that import for
package-in-program applications. Still, I'm pretty happy with how easy
this was! Special thanks go out to Paul Fenwick for autodie, which saved
me having to write loads of error checking.</summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml"><p>...not really. I still really like using GitHub, and (obviously) they do much more than I could churn out in a weekend, let alone an hour. Also, I used Perl.</p>
<p>That said, we've recently stopped using them for work code. Things just didn't work out. I hope we can migrate back to them someday, but for now we needed to make a change.</p>
<p>We're using <a href="http://scie.nti.st/2007/11/14/hosting-git-repositories-the-easy-and-secure-way">gitosis</a>, now. I've used it before, and it's a really fantastic little tool. As with most good tools, it does one job and does it very well. That means that it doesn't get in the way of the workflow you want to use.</p>
<p>That also means it doesn't go out of its way to make any particular workflow easy. That's fine!</p>
<p>I had originally thought we'd be fine having users share their repos from their home directories, as everyone has read access to every other user's homedir. This ended up being tedious and stupid, for a number of reasons, including that each user puts his code in a different subdirectory under home. (Each choice other than my own just seems so unnatural!)</p>
<p>When we were using GitHub, we had a program that did something like this:</p>
<ul>
<li>ensure that master-user/repository existed</li>
<li>fork it to you/repository if needed</li>
<li>clone you/repository to cwd</li>
</ul>
<p>I updated this program to work on our gitosis setup with uniform per-user repository URLs. After all, a GitHub fork is just a clone with a tiny smidge of added metadata, near as I can tell.</p>
<p>The master user in our scenario is <code>gitosis@git.example.com</code>, and every user also has a login on that box. Here's the program:</p>
<pre>
<code>#!/usr/bin/perl
use strict;
use warnings;

{
  package Git::Hubclone;
  use base 'App::Cmd::Simple';

  use autodie qw(:default :system);
  use Getopt::Long::Descriptive;
  use Sys::Hostname::Long;

  my $HOST = q{git.example.com};

  sub usage_desc { '%c %o &lt;repo&gt;' }
  sub opt_spec {
    return (
      [ 'bare-only', "do not create a local clone, only hub copy" ],
    );
  }

  sub validate_args {
    my ($self, $opt, $args) = @_;

    my $user = $ENV{USER};
    my $repo = $args-&gt;[0];

    $self-&gt;usage_error("no repo name given") unless $repo;
    $self-&gt;usage_error("do not run as root") if $user eq 'root';
    $self-&gt;usage_error("illegal repo name")  if $repo !~ /\A[-_a-z0-9]+\z/;

    if (! $opt-&gt;{bare_only}) {
      $self-&gt;usage_error("already in a git repository!")       if -d '.git';
      $self-&gt;usage_error("directory './$repo' already exists") if -d $repo;
    }
  }

  sub run {
    my ($self, $opt, $args) = @_;

    my $user = $ENV{USER};
    my $repo = $args-&gt;[0];

    if (hostname_long eq $HOST) {
      require File::HomeDir;
      require File::Path;
      require File::Spec;

      my $git_dir  = File::Spec-&gt;catfile( File::HomeDir-&gt;my_home, 'git' );
      my $repo_dir = File::Spec-&gt;catfile( $git_dir, "$repo.git" );

      unless (-d $repo_dir) {
        File::Path::mkpath($git_dir);
        system qq{git clone --bare gitosis\@$HOST:$repo.git $repo_dir};
      }
    } else {
      system "ssh $HOST git hubclone --bare-only $repo";
    }

    unless ($opt-&gt;{bare_only}) {
      my $clone_cmd = qq{git clone $user\@$HOST:git/$repo.git};
      system $clone_cmd;
    }
  }
}

Git::Hubclone-&gt;import;
Git::Hubclone-&gt;run;
</code>
</pre>
<p>I should really fix up App::Cmd::Simple to not require that import for package-in-program applications. Still, I'm pretty happy with how easy this was! Special thanks go out to Paul Fenwick for <code>autodie</code>, which saved me having to write <em>loads</em> of error checking.</p></div>
    </content>
    <published>2009-06-27T15:08:39-05:00</published>
    <updated>2009-06-27T15:08:39-05:00</updated>
    <author>
      <name>rjbs</name>
    </author>
    <id>tag:perlsphere.net,2006:http://rjbs.manxome.org/rubric/entry/1776</id>
  </entry>
  <entry>
    <title>a quick overview of yapc (and my slides)</title>
    <link rel="alternate" href="http://rjbs.manxome.org/rubric/entry/1775" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">First off, my slides. Whenever I give a presentation, someone will ask me
whether the slides will go online. Sometimes they do, and sometimes they
don't. This year, I gave three presentations: one on Git, one on some new
email libraries, and one on Rx. The email slides will probably go online
soon. I'm not sure the other two will.

It's great to get feedback on my slides, and of course praise is nice
too, and I'd like everyone who can to be able to benefit from whatever
explanation I can provide, but sometimes slides just don't make sense as
a PDF online. Very often, the slides are merely visual aids for the
spoken content. Without narration, the slides are often less than useful,
or even counter-productive.

I would like to get my Git slides online, but it will require that I
first record the audio and sync it with presentation. That will require a
good bit of work, and I'm not sure when I'll make the time to do it.
(After all, presenting for YAPC earns me free admission and interesting
questions. Presenting for SlideShare mostly just gets me notices that
someone else has posted spam to the comments.)

So, on to the YAPC recap.

I arrived Saturday with plans to get some beer at the Hofbrauhaus, but it
fell through. Instead, we went to Claddagh. I was irritated that I had to
order four beers before they actually had any left, and that it was
Smithwick's instead of something local. Still, the service was great and
the food was really good. The price was right, too!

Sunday I mostly holed up in my room and worked on slides. In the evening,
Dieter and I headed out to the arrival dinner. As usual, it was
underwhelming, but it was still nice to see people and have a beer.
(Strangely enough, the only local beer I saw at the beer-o-centric Sharp
Edge was Hop Devil, which is all I drink at home.)

During the conference proper, I kept busy polishing slides until just
before each presentation. I also managed to see a good number of talks,
many of which were very good. Josh ben Jore had a good talk on debugging,
Jim Brandt spoke about Workflow.pm, Jonathan Swartz spoke about CHI, and
there were lots of others. It was also fun to see Dieter's talk on
Dist::Zilla, as it was the first time anyone else gave a talk on
something I wrote. (The next day, Chris N. included a lot of App::Cmd in
a talk, too.)

The conference dinner at Heinz Field was really good, and speakers got a
VIP tour of the stadium, including the locker rooms, control rooms, and
so on. I got lots of photos and called my brother to make him jealous.
He's a big Steelers fan.

It was also great to see so many people I hadn't seen in years. Sungo,
especially, had been MIA since Toronto. Lots of people have changed jobs,
which was fun to hear about, or lost jobs, which was not.

It was great to see Dieter again and rehash long-dormant in-jokes. (At
some point someone asked, "So... I guess you guys know each other?")
Sadly, we did not produce our discussed Perl Filk Concert lightning talk.

Finally, on Wednesday evening, David Golden was in town and stopped by
CMU. We had some pizza and beer, and we worked on the Metabase a bit.
Only a few code changes were made, but the whole thing was documented
some more and is now on the CPAN. Hopefully this will help get momentum
back up.

That might be all I have to say about YAPC. It was loads of fun, and I'm
looking forward to next year -- but I'm definitely going to enjoy having
a few months with no slides to think about, too.</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml"><p>First off, my slides. Whenever I give a presentation, someone will ask me whether the slides will go online. Sometimes they do, and sometimes they don't. This year, I gave three presentations: one on Git, one on some new email libraries, and one on Rx. The email slides will probably go online soon. I'm not sure the other two will.</p>
<p>It's great to get feedback on my slides, and of course praise is nice too, and I'd like everyone who can to be able to benefit from whatever explanation I can provide, but sometimes slides just don't make sense as a PDF online. Very often, the slides are merely visual aids for the spoken content. Without narration, the slides are often less than useful, or even counter-productive.</p>
<p>I would like to get my Git slides online, but it will require that I first record the audio and sync it with presentation. That will require a good bit of work, and I'm not sure when I'll make the time to do it. (After all, presenting for YAPC earns me free admission and interesting questions. Presenting for SlideShare mostly just gets me notices that someone else has posted spam to the comments.)</p>
<p>So, on to the YAPC recap.</p>
<p>I arrived Saturday with plans to get some beer at the Hofbrauhaus, but it fell through. Instead, we went to Claddagh. I was irritated that I had to order four beers before they actually had any left, and that it was Smithwick's instead of something local. Still, the service was great and the food was really good. The price was right, too!</p>
<p>Sunday I mostly holed up in my room and worked on slides. In the evening, Dieter and I headed out to the arrival dinner. As usual, it was underwhelming, but it was still nice to see people and have a beer. (Strangely enough, the only local beer I saw at the beer-o-centric Sharp Edge was Hop Devil, which is all I drink at home.)</p>
<p>During the conference proper, I kept busy polishing slides until just before each presentation. I also managed to see a good number of talks, many of which were very good. Josh ben Jore had a good talk on debugging, Jim Brandt spoke about Workflow.pm, Jonathan Swartz spoke about CHI, and there were lots of others. It was also fun to see Dieter's talk on Dist::Zilla, as it was the first time anyone else gave a talk on something I wrote. (The next day, Chris N. included a lot of App::Cmd in a talk, too.)</p>
<p>The conference dinner at Heinz Field was really good, and speakers got a VIP tour of the stadium, including the locker rooms, control rooms, and so on. I got lots of photos and called my brother to make him jealous. He's a big Steelers fan.</p>
<p>It was also great to see so many people I hadn't seen in years. Sungo, especially, had been MIA since Toronto. Lots of people have changed jobs, which was fun to hear about, or lost jobs, which was not.</p>
<p>It was great to see Dieter again and rehash long-dormant in-jokes. (At some point someone asked, "So... I guess you guys know each other?") Sadly, we did not produce our discussed Perl Filk Concert lightning talk.</p>
<p>Finally, on Wednesday evening, David Golden was in town and stopped by CMU. We had some pizza and beer, and we worked on the Metabase a bit. Only a few code changes were made, but the whole thing was documented some more and is now on the CPAN. Hopefully this will help get momentum back up.</p>
<p>That might be all I have to say about YAPC. It was loads of fun, and I'm looking forward to next year -- but I'm definitely going to enjoy having a few months with no slides to think about, too.</p></div>
    </content>
    <published>2009-06-27T13:41:55-05:00</published>
    <updated>2009-06-27T13:41:55-05:00</updated>
    <author>
      <name>rjbs</name>
    </author>
    <id>tag:perlsphere.net,2006:http://rjbs.manxome.org/rubric/entry/1775</id>
  </entry>
  <entry>
    <title>UK Train Running Times</title>
    <link rel="alternate" href="http://perlisalive.com/users/ajt/weblog/9" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">A while ago Greg McCarroll gave an interesting talk at the London Perl
Workshop on the topic of "JFDI". His example lead to the creation of
WWW::LiveDepartureBoards.

I later used this as an example topic for a Perl talk to my LUG:
Achieving the Impossible with Perl. At the same time I also supplied Greg
with a patch.

Since then Network Rail have started to provide a SOAP interface to their
running time data, and there is now a new interface
Net::NationalRail::LiveDepartureBoards. This has the advantage that it's
not a screen scrape, instead it's a SOAP monster...

What I want is a trivial interface, a LiveDepartureBoards::Simple... I
suppose now is the time to have a look at them both in detail and see if
I can abstract over them to create a drop-dead simple interface that uses
either as a back end.</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml"><p>A while ago Greg McCarroll gave an interesting talk at the London Perl Workshop on the topic of "JFDI". His example lead to the creation of <a href="http://search.cpan.org/dist/WWW-LiveDepartureBoards/">WWW::LiveDepartureBoards</a>.</p>
<p>I later used this as an example topic for a Perl talk to my LUG: <a href="http://www.iredale.net/p/by-permalink/1AB11BD2-EACD-11DC-AA41-82EC6225452B/">Achieving the Impossible with Perl</a>. At the same time I also supplied Greg with a patch.</p>
<p>Since then Network Rail have started to provide a SOAP interface to their running time data, and there is now a new interface <a href="http://search.cpan.org/dist/Net-NationalRail-LiveDepartureBoards/">Net::NationalRail::LiveDepartureBoards</a>. This has the advantage that it's not a screen scrape, instead it's a SOAP monster...</p>
<p>What I want is a trivial interface, a LiveDepartureBoards::Simple... I suppose now is the time to have a look at them both in detail and see if I can abstract over them to create a drop-dead simple interface that uses either as a back end.</p></div>
    </content>
    <published>2009-06-27T11:59:00+01:00</published>
    <updated>2009-06-27T11:59:00+01:00</updated>
    <author>
      <name>Adam Trickett (ajt)</name>
    </author>
    <id>tag:perlsphere.net,2006:http://perlisalive.com/users/ajt/weblog/9</id>
  </entry>
  <entry>
    <title>Promote Perl 6 by saying "Perl 5"</title>
    <link rel="alternate" href="http://feedproxy.google.com/~r/PerlBuzz/~3/OqfJM2YWG8U/promote-perl-6-by-saying-perl-5.html" type="text/html"/>
    <summary type="text">Perl 6 is hurtling toward completion. The specification is nearly
complete, and Rakudo now passes 68% of the specification tests.
Applications like November are being written in Perl 6. Perl 6 is no
vaporware, and the day when Perl 6 is ready for widespread use is coming
quickly.

Perl 6 has been in development since 2000, and in that time many people
may have forgotten about the plans we've had for Perl 6. There may be
those who have never even heard about the plans for Perl 6. Those of us
who live in the Perl world are aware of the great changes afoot, but
there are plenty of people who are not.

I think that the time is right to help make those people aware of Perl 6,
and to remind them constantly of what's coming. My proposed technique is
simple and it takes advantage of the key elements of time and repetition
to help remind everyone about Perl 6.

  We need to stop referring to Perl 5 as "Perl" and start calling it
  "Perl 5."

Specifying the "5" in "Perl 5" calls attention to the fact that there is
more than one Perl. It makes the listener or reader who is unaware of
Perl 6 wonder why the 5 is specified. For the reader who knows about Perl
6, hearing "Perl 5" reminds her that Perl 6 also exists.

I don't think it will be too tough. All I ask is that, at the very least,
when writing about Perl 5 in your blogs or mailing lists that you specify
the version you're talking about. It doesn't even need to be every
instance. I'm guessing we'll find that repeatedly saying "Perl 5" in a
long message will get tedious both for writer and reader.

I think the way to look at it is that "Perl 5" is the formal name for the
language, and later references can refer to it as "Perl," almost like a
nickname. Just that first reminder of "Perl 5" will be enough to help
lodge in the reader's brain.

With enough time &amp; repetition, it will get to be habit in our minds. With
enough time &amp; repetition, the computing world will be reminded of Perl 6
coming soon.

[IMAGE] [IMAGE] [IMAGE] [IMAGE][IMAGE]</summary>
    <content type="html">&lt;p&gt;Perl 6 is hurtling toward completion. The specification is nearly complete, and Rakudo now passes 68% of the specification tests. Applications like November are being written in Perl 6. Perl 6 is no vaporware, and the day when Perl 6 is ready for widespread use is coming quickly.&lt;/p&gt;
&lt;p&gt;Perl 6 has been in development since 2000, and in that time many people may have forgotten about the plans we've had for Perl 6. There may be those who have never even heard about the plans for Perl 6. Those of us who live in the Perl world are aware of the great changes afoot, but there are plenty of people who are not.&lt;/p&gt;
&lt;p&gt;I think that the time is right to help make those people aware of Perl 6, and to remind them constantly of what's coming. My proposed technique is simple and it takes advantage of the key elements of time and repetition to help remind everyone about Perl 6.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;We need to stop referring to Perl 5 as "Perl" and start calling it "Perl 5."&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Specifying the "5" in "Perl 5" calls attention to the fact that there is more than one Perl. It makes the listener or reader who is unaware of Perl 6 wonder why the 5 is specified. For the reader who knows about Perl 6, hearing "Perl 5" reminds her that Perl 6 also exists.&lt;/p&gt;
&lt;p&gt;I don't think it will be too tough. All I ask is that, at the very least, when writing about Perl 5 in your blogs or mailing lists that you specify the version you're talking about. It doesn't even need to be every instance. I'm guessing we'll find that repeatedly saying "Perl 5" in a long message will get tedious both for writer and reader.&lt;/p&gt;
&lt;p&gt;I think the way to look at it is that "Perl 5" is the formal name for the language, and later references can refer to it as "Perl," almost like a nickname. Just that first reminder of "Perl 5" will be enough to help lodge in the reader's brain.&lt;/p&gt;
&lt;p&gt;With enough time &amp;amp; repetition, it will get to be habit in our minds. With enough time &amp;amp; repetition, the computing world will be reminded of Perl 6 coming soon.&lt;/p&gt;
&lt;div class="feedflare"&gt;&lt;a href="http://feeds.feedburner.com/~ff/PerlBuzz?a=OqfJM2YWG8U:GAWZxXVes4M:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PerlBuzz?d=yIl2AUoC8zA"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PerlBuzz?a=OqfJM2YWG8U:GAWZxXVes4M:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PerlBuzz?i=OqfJM2YWG8U:GAWZxXVes4M:F7zBnMyn0Lo"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PerlBuzz?a=OqfJM2YWG8U:GAWZxXVes4M:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PerlBuzz?i=OqfJM2YWG8U:GAWZxXVes4M:V_sGLiPBpWU"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PerlBuzz?a=OqfJM2YWG8U:GAWZxXVes4M:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PerlBuzz?d=qj6IDK7rITs"&gt;&lt;/a&gt;&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/PerlBuzz/~4/OqfJM2YWG8U"&gt;</content>
    <category term="Perl 5 Perl 6"/>
    <published>2009-06-26T21:09:00Z</published>
    <updated>2009-06-26T21:09:00Z</updated>
    <author>
      <name>Andy Lester</name>
    </author>
    <id>tag:perlsphere.net,2006:tag:perlbuzz.com,2009://1.691</id>
  </entry>
  <entry>
    <title>App::Prove::State rocks</title>
    <link rel="alternate" href="http://feedproxy.google.com/~r/yuvalkogman/~3/GdrEkr-kH6o/appprovestate-rocks.html" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">Running a standard Perl module's test suite is very easy using prove. If
the module needs compilation, just run make before hand and pass the -b
flag to prove, otherwise use -l to add lib to @INC.

If you pass --state=save then information about the last run will be
saved in a .prove file in the current directory. This data can be used
later to run only failed tests, or to reorder tests.

My testing workflow was greatly improved using this feature. I use two
shell aliases to run prove:

alias ts="prove --state=slow,save -j3 -r"
alias tf="prove --state=failed,save -v -r"

I start by running ts -l t (or ts -b t if this module requires make to
run before testing). The -r flag tells it search for .t files recursively
in t. The -j option enables 3 concurrent jobs, and the --state flag
orders tests from slowest to fastest, and causes the .prove file to be
updated at the end of the run.

When I get failing tests I switch to using tf -l or tf -b. Since this has
--state=failed it only runs tests that failed in the previous run. The -v
causes the TAP output to be printed (with coloring).

I fix my tests or code one by one, and keep running tf. When tf has
nothing left to run everything is passing, so I switch back to ts to run
the full test suite again.

These two simple aliases let me run the test suite much more easily and
effectively than make test, so a great many thanks to Ovid and Andy
Armstrong [Update: and Andy Lester] for writing and maintaining these
tools.

[IMAGE][IMAGE]</div>
    </summary>
    <content type="html">&lt;p&gt;Running a standard Perl module's test suite is very easy using &lt;a href="http://search.cpan.org/perldoc?App::Prove"&gt;&lt;tt&gt;prove&lt;/tt&gt;&lt;/a&gt;. If the module needs compilation, just run &lt;tt&gt;make&lt;/tt&gt; before hand and pass the &lt;tt&gt;-b&lt;/tt&gt; flag to &lt;tt&gt;prove&lt;/tt&gt;, otherwise use &lt;tt&gt;-l&lt;/tt&gt; to add &lt;tt&gt;lib&lt;/tt&gt; to &lt;tt&gt;@INC&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;If you pass &lt;tt&gt;--state=save&lt;/tt&gt; then information about the last run will be saved in a &lt;tt&gt;.prove&lt;/tt&gt; file in the current directory. This data can be used later to run only failed tests, or to reorder tests.&lt;/p&gt;
&lt;p&gt;My testing workflow was greatly improved using this feature. I use two shell aliases to run &lt;tt&gt;prove&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="fake-gist" id="fake-gist-136836"&gt;
alias ts="prove --state=slow,save -j3 -r"
alias tf="prove --state=failed,save -v -r"
&lt;/pre&gt;
&lt;p&gt;I start by running &lt;tt&gt;ts -l t&lt;/tt&gt; (or &lt;tt&gt;ts -b t&lt;/tt&gt; if this module requires &lt;tt&gt;make&lt;/tt&gt; to run before testing). The &lt;tt&gt;-r&lt;/tt&gt; flag tells it search for &lt;tt&gt;.t&lt;/tt&gt; files recursively in &lt;tt&gt;t&lt;/tt&gt;. The &lt;tt&gt;-j&lt;/tt&gt; option enables 3 concurrent jobs, and the &lt;tt&gt;--state&lt;/tt&gt; flag orders tests from slowest to fastest, and causes the &lt;tt&gt;.prove&lt;/tt&gt; file to be updated at the end of the run.&lt;/p&gt;
&lt;p&gt;When I get failing tests I switch to using &lt;tt&gt;tf -l&lt;/tt&gt; or &lt;tt&gt;tf -b&lt;/tt&gt;. Since this has &lt;tt&gt;--state=failed&lt;/tt&gt; it only runs tests that failed in the previous run. The &lt;tt&gt;-v&lt;/tt&gt; causes the TAP output to be printed (with coloring).&lt;/p&gt;
&lt;p&gt;I fix my tests or code one by one, and keep running &lt;tt&gt;tf&lt;/tt&gt;. When &lt;tt&gt;tf&lt;/tt&gt; has nothing left to run everything is passing, so I switch back to &lt;tt&gt;ts&lt;/tt&gt; to run the full test suite again.&lt;/p&gt;
&lt;p&gt;These two simple aliases let me run the test suite much more easily and effectively than &lt;tt&gt;make test&lt;/tt&gt;, so a great many thanks to &lt;a href="http://use.perl.org/~Ovid/journal/"&gt;Ovid&lt;/a&gt; and &lt;a href="http://www.hexten.net/"&gt;Andy Armstrong&lt;/a&gt; [&lt;b&gt;Update:&lt;/b&gt; and &lt;a href="http://theworkinggeek.com/"&gt;Andy Lester&lt;/a&gt;] for writing and maintaining these tools.&lt;/p&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img&gt;&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/yuvalkogman/~4/GdrEkr-kH6o"&gt;</content>
    <category term="testing perl"/>
    <published>2009-06-26T18:35:00Z</published>
    <updated>2009-06-26T18:35:00Z</updated>
    <author>
      <name>nothingmuch</name>
    </author>
    <id>tag:perlsphere.net,2006:tag:blogger.com,1999:blog-876358347971598886.post-796200162498885466</id>
  </entry>
  <entry>
    <title>The 81% Solution</title>
    <link rel="alternate" href="http://use.perl.org/~Ovid/journal/39179?from=rss" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">Whether you're talking about git, Mercurial, SVK or some other
distributed version control system, it's very important to realize that
one of its strongest benefits is "distributed". Many people don't care
about this, but it can tremendously boost productivity when combined as a
part of overall development strategy.

Recently I got so fed up with our dev box that I install Ubuntu on my
work computer so I could work locally. This was because our dev box was
routinely running with loads around 20, and on one occasion hit a load of
57. Seems the admins thought it would be a good idea to let a bunch of
other teams develop on that server but not tell us about it. I just
couldn't work like that. Instead of using my computer as a dumb
workstation with Windows, I now develop locally and am (usually) not
dependent on our dev box being available.

That's also the reason why I have MySQL server installed locally, rather
than using our test database. Sometimes that test database goes down, so
I don't want to depend on that, either. And the admins thought it would
be a good idea to let a bunch of other teams develop on that server but
not tell us about it.

In fact, sometimes I break down. With a recent back injury, I was working
from home for a week. It was slow, frustrating and painful because I
wasn't really set up to work from home and this caused me to lose even
more productivity. Had I been able to work from my laptop, there would
have been no performance hit. Of course, even without a back injury, we
had thousands of employees unable to work full hours because of a Tube
strike.

Which brings me back to version control. More than once I've been unable
to check in code because the subversion server has been down (never mind
when the repository simply freaks out and tells me I can't commit). With
something like git, I could do all of my work locally and if I can't push
to the central repository, oh well.

So yeah, you know all this, but seriously, do the math. Let's be really
generous and assume that our dev box, subversion server, mysql server and
ability to be physically present at work all run at 99% availability.
This means that your chance being "available" to work is .99^4, or about
96%. If the average availability of all of those things seems around 95%,
then your "availability" drops to about 81%. Before I started working so
hard to "disconnect" from the network at work, my availability was often
lower than 81%. It was awful.

Now imagine sitting in a job interview and telling them that you're only
going to work 81% of the time. You're not going to get the job. But the
reality is, many corporate environments enforce 81% availability. This is
insane, but common. And of course, we also know that those four items
aren't the only things which can disrupt your productivity, but those are
the four which most impact mine, so that's why I chose them.

When you're setting up a dev environment for programmers and you want it
to be as productive as possible, don't force them to depend on things
they can't control, such as network availability. Of course, as an
employee, it's always fun when the network goes down and you see everyone
wandering around with a coffee cup in hand, having been electronically
muzzled. What on earth could convince people that this is a sane
development environment?</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml"><p>Whether you're talking about git, Mercurial, SVK or some other distributed version control system, it's very important to realize that one of its strongest benefits is "distributed". Many people don't care about this, but it can tremendously boost productivity when combined as a part of overall development strategy.</p>
<p>Recently I got so fed up with our dev box that I install Ubuntu on my work computer so I could work locally. This was because our dev box was routinely running with loads around 20, and on one occasion hit a load of 57. Seems the admins thought it would be a good idea to let a bunch of other teams develop on that server but not tell us about it. I just couldn't work like that. Instead of using my computer as a dumb workstation with Windows, I now develop locally and am (usually) not dependent on our dev box being available.</p>
<p>That's also the reason why I have MySQL server installed locally, rather than using our test database. Sometimes that test database goes down, so I don't want to depend on that, either. And the admins thought it would be a good idea to let a bunch of other teams develop on that server but not tell us about it.</p>
<p>In fact, sometimes <em>I</em> break down. With a recent back injury, I was working from home for a week. It was slow, frustrating and painful because I wasn't really set up to work from home and this caused me to lose even more productivity. Had I been able to work from my laptop, there would have been no performance hit. Of course, even without a back injury, we had thousands of employees unable to work full hours because of a Tube strike.</p>
<p>Which brings me back to version control. More than once I've been unable to check in code because the subversion server has been down (never mind when the repository simply freaks out and tells me I can't commit). With something like git, I could do all of my work locally and if I can't push to the central repository, oh well.</p>
<p>So yeah, you know all this, but seriously, do the math. Let's be really generous and assume that our dev box, subversion server, mysql server and ability to be physically present at work all run at 99% availability. This means that your chance being "available" to work is <nobr><wbr/></nobr>.99^4, or about 96%. If the average availability of all of those things seems around 95%, then your "availability" drops to about 81%. Before I started working so hard to "disconnect" from the network at work, my availability was often lower than 81%. It was awful.</p>
<p>Now imagine sitting in a job interview and telling them that you're only going to work 81% of the time. You're not going to get the job. But the reality is, many corporate environments <em>enforce</em> 81% availability. This is insane, but common. And of course, we also know that those four items aren't the only things which can disrupt your productivity, but those are the four which most impact mine, so that's why I chose them.</p>
<p>When you're setting up a dev environment for programmers and you want it to be as productive as possible, don't force them to depend on things they can't control, such as network availability. Of course, as an employee, it's always fun when the network goes down and you see everyone wandering around with a coffee cup in hand, having been electronically muzzled. What on <em>earth</em> could convince people that this is a sane development environment?</p></div>
    </content>
    <category term="journal"/>
    <published>2009-06-26T15:27:37Z</published>
    <updated>2009-06-26T15:27:37Z</updated>
    <author>
      <name>Ovid</name>
    </author>
    <id>tag:perlsphere.net,2006:http://use.perl.org/~Ovid/journal/39179?from=rss</id>
  </entry>
  <entry>
    <title>Database Design Woes ( or "Something Wicked This Way Comes")</title>
    <link rel="alternate" href="http://jjnapiorkowski.vox.com/library/post/database-design-woes-or-something-wicked-this-way-comes.html?_c=feed-atom-full" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">I wanted to drop in and explain my lengthy absence, especially given some
interesting "part two" articles in my queue that several of you have
emailed me hoping for an update.  In particular there's a pending summary
of all the feedback regarding "Why All the Hate", the long overdue "Blue
Child" installment (regarding end to end development of a Perl Catalyst
application) and on a lighter note, my decision regarding "Is it time to
rotate the Profile Pic?"  There's a few other items in my PENDING IRONMAN
BLOGS directory as well.

Earlier this summer I was diagnosed with an early form or tendonitis, and
I've been struggling to avoid surgery to repair it.  That has limited my
typing time substantially and although I've been using voice recognition
to help pick up the slack, I can't use it on my train rides to and from
work (it annoys the other passengers too much, similarly to what a loud
mobile phone conversation might provoke).  So I guess I'm out of the
Ironman running, although I am cool with that since so many of you are
stepping up to the job.  I also recruited a new blogger, a Perl newbie,
who is trying to record his learning Catalyst adventures.

Anyway, I'm not here to bitch about all that.  I am really annoyed by the
following issue regarding database design and that's what I am going to
bitch about.  My monumental annoyance is as follows:

Lookup tables.

I'm not talked about generic lookup tables (see this article for what's
bad about those.)  I'm talking about the kind most of us use all the
time.  For example, you have the logic "Each Address must have a State". 
As part of normalizing, you create Address and State tables, with a
foreign key constraint between Address and State.

This seems natural but always gives me a queasy feeling.  To me, they
seem to be blending the boundary between schema definition and
constraints with actual row data.  This makes it hard without using
triggers to have special constraints on certain types of rows in the look
up.  For example, California has a lot of special rules regarding pretty
much everything, which results in tons of evil code like:

if($row-&gt;name eq 'CA') { ## do something special }

Careful design in your ORM can mitigate the issue.  But I still don't
like what seems to be a very hard solution to a problem we all must have
several times a day.

I also don't like how in look up tables, the row data has to be part of
the database design.  DBIC makes it easy to deploy a DDL of a database
based on the classes you define, but then you still need to go in and
manually add a bunch of "insert into gender(name) values('female')" to
the generated DDL file.  This basically takes a nice and neat automated
system and makes it manual again.

Plus right now we can't use DBIC Versioning to manage the differences in
this row data.  DBIC Versioning only handles DDL differences, which is as
expected since you would imagine your actual data to be data, not logic
or constraints.  That means if you have changes in the lookups, you will
need to add more inserts or updates to the DDL diff that DBIC makes for
you.  Also, if you need to do updates, this introduces possible pain
regarding you primary key fields if you are using some sort of auto
increment or uuid system to create these, since you might not know in
advance the values in these fields.

It's been recommended to me that you can use an 'enum' type in the
database instead of table look ups.  That way you do indeed get to manage
the data as part of the DDL, but you still end up having to use
conditionals a lot for all the special rules.

At least with DBIC, you can mitigate this a bit by making classes and
resultset constricted to a particular query (so you can make a
Schema::Result(Set)::State::California that actually can hold the rules
for California).  This still feels a bit ugly to me since you still have
to do all the manual table inserts.

Anyway, that's my Friday rant.  Thoughts and suggests very welcomed.  For
such a common issue a commonly shared solution we can put into code would
be fantastic. 

Read and post comments | Send to a friend</div>
    </summary>
    <content type="html">&lt;div xmlns="http://www.w3.org/1999/xhtml" xmlns:at="http://www.sixapart.com/ns/at"&gt;
&lt;p&gt;I wanted to drop in and explain my lengthy absence, especially given some interesting "part two" articles in my queue that several of you have emailed me hoping for an update.&amp;nbsp; In particular there's a pending summary of all the feedback regarding "&lt;a href="http://jjnapiorkowski.vox.com/library/post/why-all-the-hate.html"&gt;Why All the Hate&lt;/a&gt;", the long overdue "&lt;a href="http://jjnapiorkowski.vox.com/library/post/bluechild-end-to-end-development-of-a-perl-catalyst-website.html"&gt;Blue Child&lt;/a&gt;" installment (regarding end to end development of a Perl Catalyst application) and on a lighter note, my decision regarding "&lt;a href="http://jjnapiorkowski.vox.com/library/post/time-to-rotate-the-profile-pic.html"&gt;Is it time to rotate the Profile Pic&lt;/a&gt;?"&amp;nbsp; There's a few other items in my PENDING IRONMAN BLOGS directory as well.&lt;/p&gt;
&lt;p&gt;Earlier this summer I was diagnosed with an early form or &lt;a href="http://www.itendonitis.com/wrist-tendonitis.html"&gt;tendonitis&lt;/a&gt;, and I've been struggling to avoid surgery to repair it.&amp;nbsp; That has limited my typing time substantially and although I've been using voice recognition to help pick up the slack, I can't use it on my train rides to and from work (it annoys the other passengers too much, similarly to what a loud mobile phone conversation might provoke).&amp;nbsp; So I guess I'm out of the &lt;a href="http://ironman.enlightenedperl.org/"&gt;Ironman&lt;/a&gt; running, although I am cool with that since so many of you are stepping up to the job.&amp;nbsp; I also recruited a new blogger, a Perl newbie, who is trying to record his learning Catalyst adventures.&lt;/p&gt;
&lt;p&gt;Anyway, I'm not here to bitch about all that.&amp;nbsp; I am really annoyed by the following issue regarding database design and that's what I am going to bitch about.&amp;nbsp; My monumental annoyance is as follows:&lt;/p&gt;
&lt;p&gt;Lookup tables.&lt;/p&gt;
&lt;p&gt;I'm not talked about generic lookup tables (see &lt;a href="http://www.projectdmx.com/dbdesign/lookup.aspx"&gt;this article&lt;/a&gt; for what's bad about those.)&amp;nbsp; I'm talking about the kind most of us use all the time.&amp;nbsp; For example, you have the logic "Each Address must have a State".&amp;nbsp; As part of normalizing, you create Address and State tables, with a foreign key constraint between Address and State.&lt;/p&gt;
&lt;p&gt;This seems natural but always gives me a queasy feeling.&amp;nbsp; To me, they seem to be blending the boundary between schema definition and constraints with actual row data.&amp;nbsp; This makes it hard without using triggers to have special constraints on certain types of rows in the look up.&amp;nbsp; For example, California has a lot of special rules regarding pretty much everything, which results in tons of evil code like:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if($row-&amp;gt;name eq 'CA') { ## do something special }&lt;/p&gt;
&lt;p&gt;Careful design in your ORM can mitigate the issue.&amp;nbsp; But I still don't like what seems to be a very hard solution to a problem we all must have several times a day. &amp;nbsp;&lt;/p&gt;
&lt;p&gt;I also don't like how in look up tables, the row data has to be part of the database design.&amp;nbsp; DBIC makes it easy to deploy a DDL of a database based on the classes you define, but then you still need to go in and manually add a bunch of "insert into gender(name) values('female')" to the generated DDL file.&amp;nbsp; This basically takes a nice and neat automated system and makes it manual again.&lt;/p&gt;
&lt;p&gt;Plus right now we can't use DBIC Versioning to manage the differences in this row data.&amp;nbsp; DBIC Versioning only handles DDL differences, which is as expected since you would imagine your actual data to be data, not logic or constraints.&amp;nbsp; That means if you have changes in the lookups, you will need to add more inserts or updates to the DDL diff that DBIC makes for you.&amp;nbsp; Also, if you need to do updates, this introduces possible pain regarding you primary key fields if you are using some sort of auto increment or uuid system to create these, since you might not know in advance the values in these fields.&lt;/p&gt;
&lt;p&gt;It's been recommended to me that you can use an 'enum' type in the database instead of table look ups.&amp;nbsp; That way you do indeed get to manage the data as part of the DDL, but you still end up having to use conditionals a lot for all the special rules.&lt;/p&gt;
&lt;p&gt;At least with DBIC, you can mitigate this a bit by making classes and resultset constricted to a particular query (so you can make a Schema::Result(Set)::State::California that actually can hold the rules for California).&amp;nbsp; This still feels a bit ugly to me since you still have to do all the manual table inserts.&lt;/p&gt;
&lt;p&gt;Anyway, that's my Friday rant.&amp;nbsp; Thoughts and suggests very welcomed.&amp;nbsp; For such a common issue a commonly shared solution we can put into code would be fantastic.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://jjnapiorkowski.vox.com/library/post/database-design-woes-or-something-wicked-this-way-comes.html?_c=feed-atom-full#comments"&gt;Read and post comments&lt;/a&gt; | &lt;a href="http://www.vox.com/share/6a00fa9675c31f000201101667fa11860c?_c=feed-atom-full"&gt;Send to a friend&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;</content>
    <category term="perl dbix-class dbic"/>
    <published>2009-06-26T13:19:10Z</published>
    <updated>2009-06-26T13:19:10Z</updated>
    <author>
      <name>John Napiorkowski</name>
    </author>
    <id>tag:perlsphere.net,2006:tag:vox.com,2009-06-26:asset-6a00fa9675c31f000201101667fa11860c</id>
  </entry>
  <entry>
    <title>grok update</title>
    <link rel="alternate" href="http://blog.nix.is/grok-update" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">Some things have kept me very busy lately and I’m a bit behind on my GSoC
schedule. I’m starting to catch up now, though.

First of all, as of version 0.05, you can now easily install grok from
the command line on most operating systems like so:

$ cpanp -i App::Grok.

It can handle Pod 5 files now (via Pod::Text) as well (which most of the
Perl 6 Synopses are written in). The ANSI-colored output looks a bit
different than the Pod 6 output because Pod::Text is very conservative in
its use of colors. I’ll probably make them more similar later to keep it
consistent.

When called interactively, grok now uses your system’s pager to view the
output by default.

It will now treat an argument as a Pod 6 file to read if said argument
doesn’t match a known documentation target. As for the targets, the only
known ones so far are the synopses (which are bundled with grok for now),
so you can do things like:

$ grok s02
$ grok s32-rules</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml"><p>Some things have kept me very busy lately and I’m a bit behind on my GSoC schedule. I’m starting to catch up now, though.<br/>
<span id="more-183"/><br/>
First of all, as of version 0.05, you can now easily install <code>grok</code> from the command line on most operating systems like so:</p>
<p><code>$ cpanp -i App::Grok</code>.</p>
<p>It can handle Pod 5 files now (via <code>Pod::Text</code>) as well (which most of the Perl 6 Synopses are written in). The ANSI-colored output looks a bit different than the Pod 6 output because <code>Pod::Text</code> is very conservative in its use of colors. I’ll probably make them more similar later to keep it consistent.</p>
<p>When called interactively, <code>grok</code> now uses your system’s pager to view the output by default.</p>
<p>It will now treat an argument as a Pod 6 file to read if said argument doesn’t match a known documentation target. As for the targets, the only known ones so far are the synopses (which are bundled with <code>grok</code> for now), so you can do things like:</p>
<p><code>$ grok s02</code><br/>
<code>$ grok s32-rules</code></p></div>
    </content>
    <category term="english gsoc perl perl6"/>
    <published>0</published>
    <updated>0</updated>
    <author>
      <name>Hinrik Örn Sigurðsson</name>
    </author>
    <id>tag:perlsphere.net,2006:http://blog.nix.is/?p=183</id>
  </entry>
  <entry>
    <title>Metabase: Opinions from anyone about anything</title>
    <link rel="alternate" href="http://www.dagolden.com/index.php/261/metabase-opinions-from-anyone-about-anything/" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">Explaining Metabase
-------------------

At YAPC::NA, Ricardo and I finally released some early alpha Metabase
modules to CPAN. Metabase is a project we started in 2008 at the Oslo QA
Hackathon to provide a new transport and storage infrastructure for CPAN
Testers and other CPAN distribution metadata. We’ve been working out of
github until now, but think it’s time to encourage others in the Perl
programming community to take a look.

One of the challenges we’ve had is just explaining Metabase to people.
Here’s what I’ve come up with: Metabase is a database framework and web
API to store and search opinions from anyone about anything. In the
terminology of Metabase, Users store Facts about Resources. Facts are
really opinions or claims; there is no inherent truth in them. Resources
are logical identifiers, generally in the form of a URI, since the things
we’re most interested in describing are online.

Since CPAN Testers is our first use case, I’ll use that to illustrate the
concept. Currently, CPAN Testers email test reports about distributions
on CPAN. In the Metabase world, each CPAN tester is a User. The Resource
is a CPAN distribution file – a ‘distfile’ URI that describes a
distribution tarball on CPAN such as
cpan://distfile/DAGOLDEN/Capture-Tiny-0.06.tar.gz. The Fact is the test
report. Today that’s just the text of the email message, but in the
future it will be structured data. 1

It’s easy to see how this can be generalized to an entire ecosystem of
facts and opinions about CPAN distributions, such as CPANTS, ratings,
annotations, tags, etc. Today, every CPAN website has its own database
and its own API so mashups and remixes require building an interface to
each. Metabase offers the possibility of a unified way for all these
tools to store, share and cross-reference information about CPAN.


Design considerations
---------------------

Metabase has some similarities to other, general ontology frameworks, but
we decided to focus our efforts around some pragmatic tradeoffs using
CPAN Testers to guide the design. We think these decisions generalize
well to other uses, but we’re trying to follow a YAGNI strategy and only
implement what CPAN Testers will need before worrying about more general
cases.


(1) High fact volume

There are currently about 18,000 “latest” distributions on CPAN, and the
entire history of CPAN is a bit over 100,000 distributions. By contrast,
there are over 4 million CPAN Testers reports already and the total is
growing by about 250,000 per month. Reports are usually consumed as a
batch process to create summary statistics on the CPAN Testers website
and relatively few reports are ever reviewed in detail. Therefore, the
Metabase design to date prioritizes Fact submission over search and
retrieval.


(2) Minimalist Perl for client libraries

Many CPAN Testers want to run smoke tests using a Perl installation that
has as few extra modules installed as possible. Therefore, any Metabase
components used by clients such as Metabase::Fact or
Metabase::Client::Simple need minimal non-core dependencies. On the other
hand, anything that will run on the server side can take full advantage
of Modern Perl tools like Moose, DBIC and Catalyst.


(3) No barriers to contribution

Today, new CPAN Testers don’t have to register or get authorized to start
contributing, they just start sending emails to a mailing list that
collects reports. For Metabase, users generate a user profile fact and
submit it as a credential with their facts. Metabase manages user
identities within the Metabase itself – adding new users automatically –
allowing new contributors to join without any external pre-authorization
hurdles that might discourage participation.2


(4) Open to extension and evolution

We want to make CPAN Testers tools available for corporations or
perl5-porters or anyone with customized testing needs. We want people to
come up with new facts and new resources. That means defining interfaces
well and leaving implementation details open to change. Metabase allows
lots of choices about things like underlying data storage technologies or
permissible fact types.

Metabase specifies data storage capabilities, but the actual database
storage is pluggable, from flat files to relational databases to cloud
services. Metabase defines how Fact classes can provide validation and
custom index data on top of a very simple data model. Moreover, Metabase
is a fairly dumb repository; any intelligent analysis must be done by
third parties extracting and transforming data.


Where do we go from here?
-------------------------

I’ve successfully submitted test reports to a local Metabase, but for
Metabase to become what we need for CPAN Testers (and more), there are
still quite a number of things to do:

  * Improve documentation

  * Test and refine Metabase components

  * Design and implement search capabilities

  * Establish one or more ‘development server’ Metabases for testing
    robustness and throughput

  * Migrate the 4 million CPAN Testers reports from NNTP to Metabase

  * Migrate CPAN Testers downstream analytics to use Metabase as a source

  * Have some CPAN Testers pilot submitting reports to Metabase

  * Develop and release new CPAN Testers clients that can submit
    structured Metabase reports

If you are interested in following or participating in Metabase, there is
a (still low-volume) mailing list you can subscribe to and several of the
key developers can be found on #toolchain on irc.perl.org.

  1. Technically, a CPAN Testers report will be a collection of more
    granular facts like prerequisites, test output, environment and so
    on.

  2. Verification or authorization is optional</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml"><h2>Explaining Metabase</h2>
<p>At <a href="http://yapc10.org/">YAPC::NA</a>, Ricardo and I finally released some early alpha <a href="http://search.cpan.org/search?query=metabase&amp;mode=dist">Metabase</a> modules to CPAN. Metabase is a project we started in 2008 at the Oslo QA Hackathon to provide a new transport and storage infrastructure for <a href="http://www.cpantesters.org/">CPAN Testers</a> and other CPAN distribution metadata. We’ve been working out of <a href="http://github.com/dagolden/">github</a> until now, but think it’s time to encourage others in the Perl programming community to take a look.</p>
<p>One of the challenges we’ve had is just explaining Metabase to people. Here’s what I’ve come up with: <strong>Metabase is a database framework and web API to store and search opinions from anyone about anything</strong>. In the terminology of Metabase, <em>Users</em> store <em>Facts</em> about <em>Resources</em>. Facts are really opinions or claims; there is no inherent truth in them. Resources are logical identifiers, generally in the form of a URI, since the things we’re most interested in describing are online.</p>
<p>Since CPAN Testers is our first use case, I’ll use that to illustrate the concept. Currently, CPAN Testers email test reports about distributions on CPAN. In the Metabase world, each CPAN tester is a User. The Resource is a CPAN distribution file – a ‘distfile’ URI that describes a distribution tarball on CPAN such as cpan://distfile/DAGOLDEN/Capture-Tiny-0.06.tar.gz. The Fact is the test report. Today that’s just the text of the email message, but in the future it will be structured data. <sup>1</sup></p>
<p>It’s easy to see how this can be generalized to an entire ecosystem of facts and opinions about CPAN distributions, such as CPANTS, ratings, annotations, tags, etc. Today, every CPAN website has its own database and its own API so mashups and remixes require building an interface to each. Metabase offers the possibility of a unified way for all these tools to store, share and cross-reference information about CPAN.</p>
<h2>Design considerations</h2>
<p>Metabase has some similarities to other, general ontology frameworks, but we decided to focus our efforts around some pragmatic tradeoffs using CPAN Testers to guide the design. We think these decisions generalize well to other uses, but we’re trying to follow a YAGNI strategy and only implement what CPAN Testers will need before worrying about more general cases.</p>
<h3>(1) High fact volume</h3>
<p>There are currently about 18,000 “latest” distributions on CPAN, and the entire history of CPAN is a bit over 100,000 distributions. By contrast, there are over 4 million CPAN Testers reports already and the total is growing by about 250,000 per month. Reports are usually consumed as a batch process to create summary statistics on the CPAN Testers website and relatively few reports are ever reviewed in detail. Therefore, the Metabase design to date prioritizes Fact submission over search and retrieval.</p>
<h3>(2) Minimalist Perl for client libraries</h3>
<p>Many CPAN Testers want to run smoke tests using a Perl installation that has as few extra modules installed as possible. Therefore, any Metabase components used by clients such as <a href="http://search.cpan.org/perldoc?Metabase::Fact">Metabase::Fact</a> or <a href="http://search.cpan.org/perldoc?Metabase::Client::Simple">Metabase::Client::Simple</a> need minimal non-core dependencies. On the other hand, anything that will run on the server side can take full advantage of Modern Perl tools like <a href="http://search.cpan.org/perldoc?Moose">Moose</a>, <a href="http://search.cpan.org/perldoc?DBIx::Class">DBIC</a> and <a href="http://www.catalystframework.org/">Catalyst</a>.</p>
<h3>(3) No barriers to contribution</h3>
<p>Today, new CPAN Testers don’t have to register or get authorized to start contributing, they just start sending emails to a mailing list that collects reports. For Metabase, users generate a user profile fact and submit it as a credential with their facts. Metabase manages user identities within the Metabase itself – adding new users automatically – allowing new contributors to join without any external pre-authorization hurdles that might discourage participation.<sup>2</sup></p>
<h3>(4) Open to extension and evolution</h3>
<p>We want to make CPAN Testers tools available for corporations or perl5-porters or anyone with customized testing needs. We want people to come up with new facts and new resources. That means defining interfaces well and leaving implementation details open to change. Metabase allows lots of choices about things like underlying data storage technologies or permissible fact types.</p>
<p>Metabase specifies data storage capabilities, but the actual database storage is pluggable, from flat files to relational databases to cloud services. Metabase defines how Fact classes can provide validation and custom index data on top of a very simple data model. Moreover, Metabase is a fairly dumb repository; any intelligent analysis must be done by third parties extracting and transforming data.</p>
<h2>Where do we go from here?</h2>
<p>I’ve successfully submitted test reports to a local Metabase, but for Metabase to become what we need for CPAN Testers (and more), there are still quite a number of things to do:</p>
<ul>
<li>Improve documentation</li>
<li>Test and refine Metabase components</li>
<li>Design and implement search capabilities</li>
<li>Establish one or more ‘development server’ Metabases for testing robustness and throughput</li>
<li>Migrate the 4 million CPAN Testers reports from NNTP to Metabase</li>
<li>Migrate CPAN Testers downstream analytics to use Metabase as a source</li>
<li>Have some CPAN Testers pilot submitting reports to Metabase</li>
<li>Develop and release new CPAN Testers clients that can submit structured Metabase reports</li>
</ul>
<p>If you are interested in following or participating in Metabase, there is a (still low-volume) mailing list you can <a href="http://www.listbox.com/subscribe/?list_id=137267">subscribe to</a> and several of the key developers can be found on #toolchain on irc.perl.org.</p>
<ol class="footnotes">
<li id="footnote_0_261" class="footnote">Technically, a CPAN Testers report will be a collection of more granular facts like prerequisites, test output, environment and so on.</li>
<li id="footnote_1_261" class="footnote">Verification or authorization is optional</li>
</ol></div>
    </content>
    <category term="cpan cpan-testers metabase perl"/>
    <published>2009-06-26T01:05:05Z</published>
    <updated>2009-06-26T01:05:05Z</updated>
    <author>
      <name>david</name>
    </author>
    <id>tag:perlsphere.net,2006:http://www.dagolden.com/?p=261</id>
  </entry>
  <entry>
    <title>The Value of a Pumpking</title>
    <link rel="alternate" href="http://www.modernperlbooks.com/mt/2009/06/the-value-of-a-pumpking.html" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">I like creating software.

In truth, I like solving problems. I like making annoying problems
disappear, especially before people encounter them. I enjoy the
realization that a little bit of work on on my part will make the world a
little bit cleaner, a little bit simpler, and a little bit nicer.

Sometimes I have to write code to do that.

I have no desire to be a pumpking, however.


What Your Pumpking Does
-----------------------

People like Nicholas Clark and Rafael Garcia-Suarez also love to write
code. They love to clean up ugly problems and replace it with elegant
solutions. They love efficient code, and tidy code, and bug-free, stable
code.

They're a special class of person called a pumpking. In the Perl world,
the pumpking has ultimate responsibility for leading and releasing stable
versions of Perl. Think of them as Larry's lieutenants.

If you love writing code and solving problems, that sounds great. You
won't catch me volunteering, however, because a pumpking must also:

  * Manage bugs, including triaging them and fixing the ugly ones no one
    else wants to fix.

  * Manage patches, rejecting them when appropriate, revising them when
    necessary, and applying them and watching for black smoke when
    unfortunate. They must also do this in a timely fashion so as not to
    drive away volunteers.

  * Manage volunteers, helping direct their energy and enthusiasm in
    productive ways while responding quickly enough to take advantage of
    their available time but not blocking the project on promises they
    can't quite fulfill.

  * Write documentation.

  * Manage test reports, identifying when and where a commit caused
    problems and which commit might fix them.

  * Understand various portability concerns, not just of Perl code but of
    core code, across operating systems of expanding lineages and
    hardware platforms but compiler and library support.

  * Uphold the implicit support and deprecation policy, even in the face
    of often competing goals for features and bugfixes.

  * Communicate the direction of the project through development to
    stabilization and release and support even to handoff to another
    pumpking.

  * Understand the long term maintainability concerns of proposed
    features, existing code, and development policies.

  * Liase with the maintainers of core modules, especially when a release
    is imminent and full release stability and behavior is important.

  * Keep Perl perlish.

Sometimes they get to write code.


Nothing but Praise
------------------

I've written critically about the existing Perl 5 development process
here, and I expect to do so in the future. I want to be very clear about
one fact, however.

I have nothing but respect for anyone who voluntarily does the job of a
pumpking. It is a difficult, thankless position. It requires someone with
an amazing attention to detail and a superhuman ability to manage a lot
of fiddly, underappreciated work.

Past, present, and future pumpkings deserve our praise and support and
thanks.

I'm critical of the process by which we develop Perl. I have no intention
to criticize the people who develop Perl, and I offer my most sincere
apologies and appreciation to everyone who's felt criticized or attacked
or slighted.

Now how do we make the job of a pumpking easier?</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml"><p>I like creating software.</p>
<p>In truth, I like solving problems. I like making annoying problems disappear, especially before people encounter them. I enjoy the realization that a little bit of work on on my part will make the world a little bit cleaner, a little bit simpler, and a little bit nicer.</p>
<p>Sometimes I have to write code to do that.</p>
<p>I have no desire to be a pumpking, however.</p>
<h2><strong>What Your Pumpking Does</strong></h2>
<p>People like Nicholas Clark and Rafael Garcia-Suarez also love to write code. They love to clean up ugly problems and replace it with elegant solutions. They love efficient code, and tidy code, and bug-free, stable code.</p>
<p>They're a special class of person called a <em>pumpking</em>. In the Perl world, the pumpking has ultimate responsibility for leading and releasing stable versions of Perl. Think of them as Larry's lieutenants.</p>
<p>If you love writing code and solving problems, that sounds great. You won't catch me volunteering, however, because a pumpking must also:</p>
<ul>
<li>Manage bugs, including triaging them and fixing the ugly ones no one else wants to fix.</li>
<li>Manage patches, rejecting them when appropriate, revising them when necessary, and applying them and watching for black smoke when unfortunate. They must also do this in a timely fashion so as not to drive away volunteers.</li>
<li>Manage volunteers, helping direct their energy and enthusiasm in productive ways while responding quickly enough to take advantage of their available time but not blocking the project on promises they can't quite fulfill.</li>
<li>Write documentation.</li>
<li>Manage test reports, identifying when and where a commit caused problems and which commit might fix them.</li>
<li>Understand various portability concerns, not just of Perl code but of core code, across operating systems of expanding lineages and hardware platforms but compiler and library support.</li>
<li>Uphold the implicit support and deprecation policy, even in the face of often competing goals for features and bugfixes.</li>
<li>Communicate the direction of the project through development to stabilization and release and support even to handoff to another pumpking.</li>
<li>Understand the long term maintainability concerns of proposed features, existing code, and development policies.</li>
<li>Liase with the maintainers of core modules, especially when a release is imminent and full release stability and behavior is important.</li>
<li>Keep Perl perlish.</li>
</ul>
<p>Sometimes they get to write code.</p>
<h2><strong>Nothing but Praise</strong></h2>
<p>I've written critically about the existing Perl 5 development process here, and I expect to do so in the future. I want to be very clear about one fact, however.</p>
<p>I have nothing but respect for anyone who voluntarily does the job of a pumpking. It is a difficult, thankless position. It requires someone with an amazing attention to detail and a superhuman ability to manage a lot of fiddly, underappreciated work.</p>
<p>Past, present, and future pumpkings deserve our praise and support and thanks.</p>
<p>I'm critical of the process by which we develop Perl. I have no intention to criticize the people who develop Perl, and I offer my most sincere apologies and appreciation to everyone who's felt criticized or attacked or slighted.</p>
<p>Now how do we make the job of a pumpking easier?</p></div>
    </content>
    <category term="modern perl perl 5 perl programming software development support"/>
    <published>2009-06-25T18:33:34Z</published>
    <updated>2009-06-25T18:33:34Z</updated>
    <author>
      <name>chromatic</name>
    </author>
    <id>tag:perlsphere.net,2006:tag:www.modernperlbooks.com,2009:/mt//1.64</id>
  </entry>
  <entry>
    <title>beginning of moose support in padre</title>
    <link rel="alternate" href="http://jquelin.blogspot.com/2009/06/beginning-of-moose-support-in-padre.html" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">so i started using moose like all the cool kids today. it turns out to be
quite nice to use. declaring an attribute is as easy as:

  has foo =&gt;   (   is=&gt;  'ro'  , ...   )  ;

and since i'm also using poe, i was glad to find the illicit love child
of moose and poe - aka moosex::poe. declaring an event without any fuss:

  event frobnize =&gt; sub   {   say   $_  [  0  ]  -&gt;foo   }  ;

but when your module grows to have lots of attributes and poe events,
it's difficult to go directly to a given definition in the file.

readers of this blog know that i'm using padre (the perl ide), but
neither the sub nor the outline views can help. indeed, if you look the
code snippets above, there is no traditional sub definition... syntaxic
sugar is nice, but it means the tools need to be aware of them.

this was clearly an itch to scratch... i had a look at padre's outline
code, and after some help from alias, here's the result:

the patch is surprisingly small: around 20 lines for attribute detection,
and the same for event detection... that's the beauty of having cpan
modules at hand - the great ppi in this case.

(note: the feature is in trunk currently. you'll have to wait 0.38
release)

so, try padre. tell us which feature it lacks. or how can we make it the
modern perl editor, the one that would be recommended alongside moose and
others. [IMAGE]</div>
    </summary>
    <content type="text">so i started using &lt;a href="http://search.cpan.org/dist/Moose/"&gt;moose&lt;/a&gt; like all the cool kids today. it turns out to be quite nice to use. declaring an attribute is as easy as:&lt;br /&gt;
&lt;blockquote&gt;
&lt;pre&gt;
has foo =&amp;gt; &lt;span&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/span&gt; is=&amp;gt;&lt;span&gt;'ro'&lt;/span&gt;, ... &lt;span&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/span&gt;;
&lt;/pre&gt;&lt;/blockquote&gt;
and since i'm also using &lt;a href="http://search.cpan.org/dist/POE/"&gt;poe&lt;/a&gt;, i was glad to find the illicit love child of moose and poe - aka &lt;a href="http://search.cpan.org/dist/MooseX-POE/"&gt;moosex::poe&lt;/a&gt;. declaring an event without any fuss:&lt;br /&gt;
&lt;blockquote&gt;
&lt;pre&gt;
event frobnize =&amp;gt; sub &lt;span&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/span&gt; say &lt;span&gt;$_&lt;/span&gt;&lt;span&gt;&lt;strong&gt;[&lt;/strong&gt;&lt;/span&gt;0&lt;span&gt;&lt;strong&gt;]&lt;/strong&gt;&lt;/span&gt;-&amp;gt;foo &lt;span&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/span&gt;;
&lt;/pre&gt;&lt;/blockquote&gt;
but when your module grows to have lots of attributes and poe events, it's difficult to go directly to a given definition in the file.&lt;br /&gt;
&lt;br /&gt;
readers of this blog know that i'm using &lt;a href="http://padre.perlide.org/"&gt;padre&lt;/a&gt; (the perl ide), but neither the sub nor the outline views can help. indeed, if you look the code snippets above, there is no traditional sub definition... syntaxic sugar is nice, but it means the tools need to be aware of them.&lt;br /&gt;
&lt;br /&gt;
this was clearly an itch to scratch... i had a look at padre's outline code, and after some help from &lt;a href="http://use.perl.org/%7EAlias/journal/"&gt;alias&lt;/a&gt;, here's the result:&lt;br /&gt;
&lt;a href="http://2.bp.blogspot.com/_qZIpP8ZamQY/SkOr4_B5v1I/AAAAAAAAAZI/_9CilwV4bEY/s1600-h/blog.jpg"&gt;&lt;img src="http://2.bp.blogspot.com/_qZIpP8ZamQY/SkOr4_B5v1I/AAAAAAAAAZI/_9CilwV4bEY/s320/blog.jpg" alt=""&gt;&lt;/a&gt;&lt;br /&gt;
the patch is surprisingly small: around 20 lines for &lt;a href="http://padre.perlide.org/trac/changeset/5577"&gt;attribute detection&lt;/a&gt;, and the same for event detection... that's the beauty of having cpan modules at hand - the great &lt;a href="http://search.cpan.org/dist/PPI/"&gt;ppi&lt;/a&gt; in this case.&lt;br /&gt;
&lt;br /&gt;
(note: the feature is in trunk currently. you'll have to wait 0.38 release)&lt;br /&gt;
&lt;br /&gt;
so, try padre. tell us which feature it lacks. or how can we make it &lt;span&gt;the&lt;/span&gt; modern perl editor, the one that would be recommended alongside moose and others.
&lt;div class="blogger-post-footer"&gt;&lt;img&gt;&lt;/div&gt;</content>
    <category term="moose padre perl poe"/>
    <published>2009-06-25T16:54:00Z</published>
    <updated>2009-06-25T16:54:00Z</updated>
    <author>
      <name>jquelin@gmail.com (Jérôme Quelin)</name>
    </author>
    <id>tag:perlsphere.net,2006:tag:blogger.com,1999:blog-6162910877268067002.post-3650571752764719448</id>
  </entry>
  <entry>
    <title>Movable Type fork Melody is an opportunity to harness CPAN</title>
    <link rel="alternate" href="http://feedproxy.google.com/~r/PerlBuzz/~3/wXlKW2S3utQ/movable-type-fork-melody-is-an-opportunity-to-harness-cpan.html" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">Reposted from a blog entry by Mark Stosberg

Today Melody was announced as a fork of the Perl-based Movable Type
platform. I helped the Melody project as it prepared to launch, in part
advising on how to best to relate to the Perl community.  One of the
stated interests of Melody is to refactor the project to use
CGI::Application, which I maintain. Tim Appnel has already spelled out a
vision of what a "CPANization" of Movable Type might look like, and I've
looked in depth at what the initial steps towards using CGI::Application
could be.

My own vision for Melody is a code base that's very focused on publishing
and content management, with all the infrastructure outsourced to CPAN
modules that are well-written, well-documented, and well-tested.  The
collaboration between Melody and CPAN would be a two-way code flow. While
there are more CPAN modules that Melody could make use of, there are
number of pieces of Melody which should be packaged as independent
modules on their own and released to CPAN.

One example is the great "dirification" that already exists in Movable
Type. This is the functionality that turns any given string of words into
a reasonable representation in URLs. It seems like an easy problem on the
surface, but Movable Type has a sophisticated solution that takes into
account what it means to do this well across many different languages. I
also couldn't find any existing CPAN module which already takes on this
problem space, so I started to extract this out of Movable Type myself
and published a draft of String::Dirify. For that initial release, I
ripped out all the fancy multi-language support, and there is still more
significant work to be done to untangle this layer from from Movable
Type. (If you want to pick up that project and work on it, there's also
some discussion of testing String::Dirify).

While Movable Type already had an open source release, I expect Melody to
have  a more adventurous evolution, and I look forward to it becoming a
shining star in the Perl community, not just for the exterior
functionality, but also because internals have an opportunity to become
an example of best practices.

Mark Stosberg has been using programming Perl for the web for over a
decade. He is the Principal Developer at Summersault and maintains
several CPAN modules including Titanium and Data::FormValidator.

[IMAGE] [IMAGE] [IMAGE] [IMAGE][IMAGE]</div>
    </summary>
    <content type="html">&lt;p&gt;&lt;i&gt;Reposted from &lt;a href="http://mark.stosberg.com/blog/2009/06/movable-type-fork-is-an-opportunity-to-harness-cpan.html"&gt;a blog entry&lt;/a&gt; by &lt;a href="http://mark.stosberg.com/blog"&gt;Mark Stosberg&lt;/a&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;Today &lt;a href="http://www.openmelody.org/"&gt;Melody&lt;/a&gt; was announced as a fork of the Perl-based &lt;a href="http://www.movabletype.org/"&gt;Movable Type platform&lt;/a&gt;. I helped the Melody project as it prepared to launch, in part advising on how to best to relate to the Perl community.&amp;nbsp; One of the stated interests of Melody is to refactor the project to use &lt;a href="http://www.cgi-app.org/"&gt;CGI::Application&lt;/a&gt;, which I maintain. Tim Appnel has already spelled out &lt;a href="http://wiki.movabletype.org/Proposal:Foundry"&gt;a vision of what a "CPANization" of Movable Type might look like&lt;/a&gt;, and I've looked in depth at what the &lt;a href="http://wiki.movabletype.org/Proposal:QueryObjectRefactor"&gt;initial steps towards using CGI::Application&lt;/a&gt; could be.&lt;/p&gt;
&lt;p&gt;My own vision for Melody is a code base that's very focused on publishing and content management, with all the infrastructure outsourced to &lt;a href="http://search.cpan.org/"&gt;CPAN&lt;/a&gt; modules that are well-written, well-documented, and well-tested.&amp;nbsp; The collaboration between Melody and CPAN would be a two-way code flow. While there are more CPAN modules that Melody could make use of, there are number of pieces of Melody which should be packaged as independent modules on their own and released to CPAN.&lt;/p&gt;
&lt;p&gt;One example is the great "dirification" that already exists in Movable Type. This is the functionality that turns any given string of words into a reasonable representation in URLs. It seems like an easy problem on the surface, but Movable Type has a sophisticated solution that takes into account what it means to do this well across many different languages. I also couldn't find any existing CPAN module which already takes on this problem space, so I started to extract this out of Movable Type myself and &lt;a href="http://www.sixapart.com/pipermail/mtos-dev/2008-December/002249.html"&gt;published a draft of String::Dirify&lt;/a&gt;. For that initial release, I ripped out all the fancy multi-language support, and there is still more significant work to be done to untangle this layer from from Movable Type. (If you want to pick up that project and work on it, there's also &lt;a href="http://www.sixapart.com/pipermail/mtos-dev/2008-September/001982.html"&gt;some discussion of testing String::Dirify&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;While Movable Type already had an open source release, I expect Melody to have&amp;nbsp; a more adventurous evolution, and I look forward to it becoming a shining star in the Perl community, not just for the exterior functionality, but also because internals have an opportunity to become an example of best practices.&lt;/p&gt;
&lt;p&gt;&lt;i&gt;&lt;a href="http://mark.stosberg.com/blog"&gt;Mark Stosberg&lt;/a&gt; has been using programming Perl for the web for over a decade. He is the Principal Developer at &lt;a href="http://www.summersault.com"&gt;Summersault&lt;/a&gt; and maintains several CPAN modules including &lt;a href="http://search.cpan.org/perldoc?Titanium"&gt;Titanium&lt;/a&gt; and &lt;a href="http://search.cpan.org/perldoc?DataFormValidator"&gt;Data::FormValidator&lt;/a&gt;.&lt;/i&gt;&lt;/p&gt;
&lt;div class="feedflare"&gt;&lt;a href="http://feeds.feedburner.com/~ff/PerlBuzz?a=wXlKW2S3utQ:5_J5XlO-O-0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PerlBuzz?d=yIl2AUoC8zA"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PerlBuzz?a=wXlKW2S3utQ:5_J5XlO-O-0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PerlBuzz?i=wXlKW2S3utQ:5_J5XlO-O-0:F7zBnMyn0Lo"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PerlBuzz?a=wXlKW2S3utQ:5_J5XlO-O-0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PerlBuzz?i=wXlKW2S3utQ:5_J5XlO-O-0:V_sGLiPBpWU"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PerlBuzz?a=wXlKW2S3utQ:5_J5XlO-O-0:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PerlBuzz?d=qj6IDK7rITs"&gt;&lt;/a&gt;&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/PerlBuzz/~4/wXlKW2S3utQ"&gt;</content>
    <category term="CPAN Community Perl 5"/>
    <published>2009-06-25T14:54:33Z</published>
    <updated>2009-06-25T14:54:33Z</updated>
    <author>
      <name>Andy Lester</name>
    </author>
    <id>tag:perlsphere.net,2006:tag:perlbuzz.com,2009://1.689</id>
  </entry>
  <entry>
    <title>Padre 0.37 released</title>
    <link rel="alternate" href="http://szabgab.com/blog/2009/06/1245915077.html" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">Without fanfare, v0.37 of Padre has been released.

The list of changes based on the Changes file:

  * "Introduce Temporary Variable" refactoring tool (SMUELLER)

  * Added a friendly icon on the toolbar to toggle comments (GARU)

  * Crazy Win32::API AllowSetForegroundWindow hack to allow the Single
    Instance Server to correctly foreground itself (ADAMK)

  * Added Padre::Search search and replace API (ADAMK)

  * Switching to last edited file is now Ctrl-Shift-p (SZABGAB)

  * Be compatible with older version of File::Path (RYAN52)

  * Links to Mibbit were replaced by links to our irc.html (SZABGAB)

  * Merged the code of Padre::Plugin::Encode into Padre (SZABGAB)

  * Update directory only when switching to new editor (SZABGAB)

Soon it should arrive to a CPAN mirror near you.

Enjoy and thanks to all the people who put effort in Padre!</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml"><p>Without fanfare, v0.37 of <a rel="nofollow" target="_blank" href="http://padre.perlide.org/">Padre</a> has been released.</p>
<p>The list of changes based on the Changes file:</p>
<ul>
<li>"Introduce Temporary Variable" refactoring tool (SMUELLER)</li>
<li>Added a friendly icon on the toolbar to toggle comments (GARU)</li>
<li>Crazy Win32::API AllowSetForegroundWindow hack to allow the Single Instance Server to correctly foreground itself (ADAMK)</li>
<li>Added Padre::Search search and replace API (ADAMK)</li>
<li>Switching to last edited file is now Ctrl-Shift-p (SZABGAB)</li>
<li>Be compatible with older version of File::Path (RYAN52)</li>
<li>Links to Mibbit were replaced by links to our irc.html (SZABGAB)</li>
<li>Merged the code of Padre::Plugin::Encode into Padre (SZABGAB)</li>
<li>Update directory only when switching to new editor (SZABGAB)</li>
</ul>
<p>Soon it should arrive to a <a rel="nofollow" target="_blank" href="http://search.cpan.org/dist/Padre/">CPAN mirror</a> near you.</p>
<p>Enjoy and thanks to all the people who put effort in Padre!</p></div>
    </content>
    <published>2009-06-25T03:31:17-07:00</published>
    <updated>2009-06-25T03:31:17-07:00</updated>
    <author>
      <name>nobody</name>
    </author>
    <id>tag:perlsphere.net,2006:ylxaLesS3hGLuL_IPm7D0g_ee7716024e5f4d4085b413dce1b8397a</id>
  </entry>
  <entry>
    <title>The Top 100 website identifies its first OMGIBROKECPAN event</title>
    <link rel="alternate" href="http://use.perl.org/~Alias/journal/39173?from=rss" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">Because I've been distracted writing my new CPAN dependency graph
generator (to repair the main flaw in the CPAN Top 100 website) I haven't
been paying the website a whole lot of attention in the last week or so.

I just run the website data generator once or twice a week, and other
than that, I'm focusing on creating the next iteration of the support
software.

After updating the data file today, imagine my surprise when a new module
absolutely roared ahead of the previous #1 highest score, posting a new
record of over 500,000 FAILure points.

It would appear that the June 18th release of DBD::mysql was something of
a disaster, and the high number of modules that depend on MySQL means
that the impact on end users is very high.

It's good to see that when something like this happens, it is highlighted
on the list very quickly and very obviously.

However, in retrospect I'm somewhat disappointed that it took this long
to highlight it (because I don't run the updater often enough). What if
it just took a while because it took a few weeks to gradually climb up to
the top of the list, fighting against high-dependency modules with one or
two rare failures, that aren't growing so fast.

I'm wonder what might be done to spot these dramatic failures faster,
within a few days of their release, rather than having to wait a week or
so.

Even starting to do something like that will probably require a serious
improvement to the update date of the data that feeds the website, and
changes to teach the analyser about the concept of time.

Food for thought, certainly.

The question now of course, is how high a really big OMGIBROKECPAN event
might score. Something in the vicinity of several million failure points
certainly seems possible, especially if the number of CPAN Testers
installs grows.</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml"><p>Because I've been distracted writing my new CPAN dependency graph generator (to repair the main flaw in the <a href="http://ali.as/top100/">CPAN Top 100</a> website) I haven't been paying the website a whole lot of attention in the last week or so.</p>
<p>I just run the website data generator once or twice a week, and other than that, I'm focusing on creating the next iteration of the support software.</p>
<p>After updating the data file today, imagine my surprise when a new module absolutely roared ahead of the previous #1 highest score, posting a new record of over 500,000 FAILure points.</p>
<p>It would appear that the June 18th release of <a href="http://search.cpan.org/perldoc?DBD::mysql">DBD::mysql</a> was something of a disaster, and the high number of modules that depend on MySQL means that the impact on end users is very high.</p>
<p>It's good to see that when something like this happens, it is highlighted on the list very quickly and very obviously.</p>
<p>However, in retrospect I'm somewhat disappointed that it took this long to highlight it (because I don't run the updater often enough). What if it just took a while because it took a few weeks to gradually climb up to the top of the list, fighting against high-dependency modules with one or two rare failures, that aren't growing so fast.</p>
<p>I'm wonder what might be done to spot these dramatic failures faster, within a few days of their release, rather than having to wait a week or so.</p>
<p>Even starting to do something like that will probably require a serious improvement to the update date of the data that feeds the website, and changes to teach the analyser about the concept of time.</p>
<p>Food for thought, certainly.</p>
<p>The question now of course, is how high a really big OMGIBROKECPAN event might score. Something in the vicinity of several million failure points certainly seems possible, especially if the number of CPAN Testers installs grows.</p></div>
    </content>
    <category term="journal"/>
    <published>2009-06-25T05:19:46Z</published>
    <updated>2009-06-25T05:19:46Z</updated>
    <author>
      <name>Alias</name>
    </author>
    <id>tag:perlsphere.net,2006:http://use.perl.org/~Alias/journal/39173?from=rss</id>
  </entry>
  <entry>
    <title>The Swarm - Adding collaborative editing support to Padre</title>
    <link rel="alternate" href="http://use.perl.org/~Alias/journal/39172?from=rss" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">On #padre the other night, a discussion broke out on the subject of
collaborative editing (ala MoonEdit, SubEthaEdit, etc). A number of
people had never even heard of it before.

Collaborative Editing, as it is typically implemented, involves
"connecting" your editor to someone else's editor. Instead of opening the
files for local editing, your typing events and such are transmitted to
the original host in real-time.

The effect is that two or more people can edit the same document in
real-time, everyone with their own individual syntax highlighting, key
bindings, preferences and plugins active.

After establishing that all the standalone libraries for doing collab
(like libgobby) weren't going to be appropriate, we started pondering how
we might implement it ourself, and what features OTHER than pure
collaborative editing might be handy.

Some of the sorts of things you could probably do quite easily is to
"steal" a copy of an open unsaved file from someone else's Padre, open a
file for remote viewing only (think live remote code reviews), or allow
remote users to take actions for code that can only be run on one
physical system (due to exotic hardware etc).

Then there's the whole social aspect to explore. Putting your Padre into
"Conference Mode" might enable all sorts of curious effects (like
automatically notifying you if someone else on the local is editing a
CPAN distribution that you have a checkout of as well) and let you do
different things compared to collaboration with someone that is truly
physically remote. Perhaps it might allow other conference attendees to
hijack your editor so they can run module test suites on platforms they
don't have... the possibilities for sharing development effort in a more
intimate environment are quite extensive.

There's all sorts of different things that you might do, and all sorts of
different methodologies you could apply to make them happen. Multicast,
broadcast, UDP, things like Bonjour.

And just as useful for Padre is that doing collaborative editing would
require significant improvements in the cleanliness of Padre's internals.
Before we could make half this stuff work, Padre would need to have a
much more robust and sophisticated understanding of the ways in which
concepts align and mix together across the Main Window, Editor Panels,
Documents and Projects.

Having permanently running clients and servers would drive improvements
in Padre's Task API and background processing capabilities, and will
require improvements in threading and IPC.

Until this notional day in the future when we actually know how to
implement all of this in Padre safely and sanely, I've created a new
Padre::Plugin::Swarm plugin to serve as a vessel for all the insane test
cases.

"Padre Swarm" is intended to be a container for experimental work and
shiny demonstrations. It will intentionally ignore stuff like robustness,
scalability and security.

Swarm gives people a chance for people to show off the kinds of shiny
toys that might be possible when you don't have to care that implementing
it means allowing arbitrary remote code execution by the entire world,
and that it only works on multicast-capable networks, and that in the
process the Single Instance server doesn't work any more and Padre
crashes if you try to refresh the Outline panel.

As usual, if you find this interesting or exciting, I strongly encourage
you to drop in at #padre and have a chat. If you like what is happening,
we can get you commit and everything else from there.

(As an aside, Padre is now sitting at around 20 active contributors. We
now only need another 50% increase in contributors to catch and exceed
the number of active contributors on Emacs) :)</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml"><p>On <a href="http://padre.perlide.org/irc.html">#padre</a> the other night, a discussion broke out on the subject of collaborative editing (ala MoonEdit, SubEthaEdit, etc). A number of people had never even heard of it before.</p>
<p>Collaborative Editing, as it is typically implemented, involves "connecting" your editor to someone else's editor. Instead of opening the files for local editing, your typing events and such are transmitted to the original host in real-time.</p>
<p>The effect is that two or more people can edit the same document in real-time, everyone with their own individual syntax highlighting, key bindings, preferences and plugins active.</p>
<p>After establishing that all the standalone libraries for doing collab (like libgobby) weren't going to be appropriate, we started pondering how we might implement it ourself, and what features OTHER than pure collaborative editing might be handy.</p>
<p>Some of the sorts of things you could probably do quite easily is to "steal" a copy of an open unsaved file from someone else's Padre, open a file for remote viewing only (think live remote code reviews), or allow remote users to take actions for code that can only be run on one physical system (due to exotic hardware etc).</p>
<p>Then there's the whole social aspect to explore. Putting your Padre into "Conference Mode" might enable all sorts of curious effects (like automatically notifying you if someone else on the local is editing a CPAN distribution that you have a checkout of as well) and let you do different things compared to collaboration with someone that is truly physically remote. Perhaps it might allow other conference attendees to hijack your editor so they can run module test suites on platforms they don't have... the possibilities for sharing development effort in a more intimate environment are quite extensive.</p>
<p>There's all sorts of different things that you might do, and all sorts of different methodologies you could apply to make them happen. Multicast, broadcast, UDP, things like Bonjour.</p>
<p>And just as useful for Padre is that doing collaborative editing would require significant improvements in the cleanliness of Padre's internals. Before we could make half this stuff work, Padre would need to have a much more robust and sophisticated understanding of the ways in which concepts align and mix together across the Main Window, Editor Panels, Documents and Projects.</p>
<p>Having permanently running clients and servers would drive improvements in Padre's Task API and background processing capabilities, and will require improvements in threading and IPC.</p>
<p>Until this notional day in the future when we actually know how to implement all of this in Padre safely and sanely, I've created a new Padre::Plugin::Swarm plugin to serve as a vessel for all the insane test cases.</p>
<p>"Padre Swarm" is intended to be a container for experimental work and shiny demonstrations. It will intentionally ignore stuff like robustness, scalability and security.</p>
<p>Swarm gives people a chance for people to show off the kinds of shiny toys that might be possible when you don't have to care that implementing it means allowing arbitrary remote code execution by the entire world, and that it only works on multicast-capable networks, and that in the process the Single Instance server doesn't work any more and Padre crashes if you try to refresh the Outline panel.</p>
<p>As usual, if you find this interesting or exciting, I strongly encourage you to drop in at <a href="http://padre.perlide.org/irc.html">#padre</a> and have a chat. If you like what is happening, we can get you commit and everything else from there.</p>
<p>(As an aside, Padre is now sitting at around 20 active contributors. We now only need another 50% increase in contributors to catch and exceed the number of active contributors on Emacs) <nobr><wbr/></nobr>:)</p></div>
    </content>
    <category term="journal"/>
    <published>2009-06-25T00:58:31Z</published>
    <updated>2009-06-25T00:58:31Z</updated>
    <author>
      <name>Alias</name>
    </author>
    <id>tag:perlsphere.net,2006:http://use.perl.org/~Alias/journal/39172?from=rss</id>
  </entry>
  <entry>
    <title>Saudi Arabian Adventures - Days 1-2</title>
    <link rel="alternate" href="http://pjf.id.au/blog/?position=576" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">Note: Pictures of my trip to the Middle East are now available.
The events in this entry happened on 12-13th June

Saudi Arabian Adventures - Day 1
My first true day in Saudi Arabia was one of rest. After 30+ hours of
travel, being able to sleep in a bed was truly lovely. I woke up fairly
late in the day, caught up on e-mail, and then decided to go exploring.
There was a food hall just around the corner from the hotel, and while I
gawked at the sign displaying opening times, (I was concerned I had
missed lunch), and worried about the wording that said the hall was for
Saudi Aramco staff only, one of the staff members waved me in with a
smile.

What I discovered is that the food hall has both very good and very
affordable food. Cans of drink, bottles of water, and cups of coffee were
almost universally 1 riyal (about $0.30 AUD). Some basic meals were
available for about 4-5 riyals (under $2.00 AUD), with the best value for
money undoubtedly being the "budget meal", which provided soup,
vegetables, rice/potatoes, a generous main meal serving, and a dessert,
all for 11.5 riyals (about $4 AUD).

I got myself a salad (which were excellent), some soup, and some coffee,
and felt very thankful that I had changed myself some 300 riyals (about
$100 AUD) while in Dubai, since I hadn't spotted any way of doing money
exchange at the Dammam airport.

The rest of my travels included a walk around the camp, the most
interesting part of which was a fenced area that seemed to include a
library and a bowling alley. Here also a large sign proclaimed the
facilities were for Aramco employees only, and passes will be checked on
entry. I was getting the feeling that having an employee pass would be a
good idea.

Saudi Arabian Adventures - Day 2
Today was my first day of teaching. Fuad, my contact at Aramco, had
arranged to meet me at 7am at the hotel, and I had noted from my trip to
the food hall yesterday that it opened for breakfast at 5am.
Collectively, these were hints that Saudis were morning people. I set my
alarm for 5am, which in my jet-lagged state would feel like waking up at
noon in Australia.

Going to the food hall for breakfast once again had me feel like I was in
America; the most popular food that people ordered were waffles! Of
course, I didn't fly half-way around the world just to have waffles for
breakfast, so I ordered a generous bowl of ful medames... and waffles.

Of the two breakfast foods, ful was the clear winner. It tasted good, and
unlike the waffles, it had actual nutritional content. I finished
breakfast with plenty of time to meet Fuad back at the hotel at 7am.

Fuad chuckled at my attempts at an Arabic greeting, and asked in perfect
English "where are you learning this stuff, a phrase book?". I think that
means my Arabic has some ways to go. ;)

Fuad asked about my flight here, explained that the Aramco camp was
generally divided into zones, the general business hours (7:30am-3:30pm),
and helped me get set up with my lab. I was also glad to hear he would be
attending my first course.

At this point, I should explain a little about what I was teaching. My
class consisted primarily of people with job titles that started with
"Geo-", and who regularly had to deal with data that was in formats
different to what they would prefer. Unsurprisingly, they'd like to use
Perl to help solve these problems. That's an increasingly common story
with the courses I teach.

What made this interesting is that rather than having a good four or five
days (which is what I'd prefer), I was teaching two classes, a dozen
students in each, with only 2.5 days per class. To top that off, I was in
a different country, and I had no idea how comprehensible my Australian
accent would be. I'd put together a plan that covered the basics (syntax,
variables, and control structures) a tour of the CPAN, and as much regexp
content as I could squeeze in.

When we were doing introductions, it became clear that my class had a
good sense of my humour. My favourite introduction was from one student
who said "my name is very hard to remember... it's Mohammed".

The first day of teaching went well, and from the bountiful, well-thought
out questions, it was clear that I was being understood.

Posted: 25th June 2009.

Tags: adventure aramco dhahran perl saudi travel

Bookmark:

Digg this Digg this</div>
    </summary>
    <content type="html">&lt;p&gt;&lt;i&gt;Note: Pictures of my trip to the &lt;a href="http://www.flickr.com/photos/pfenwick/sets/72157620291456375"&gt;Middle East&lt;/a&gt; are now available.&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;The events in this entry happened on 12-13th June&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Saudi Arabian Adventures - Day 1&lt;/b&gt;&lt;br /&gt;
My first true day in &lt;a href="http://en.wikipedia.org/wiki/Saudi_Arabia"&gt;Saudi Arabia&lt;/a&gt; was one of rest. After 30+ hours of travel, being able to sleep in a bed was truly lovely. I woke up fairly late in the day, caught up on e-mail, and then decided to go exploring. There was a food hall just around the corner from the hotel, and while I gawked at the sign displaying opening times, (I was concerned I had missed lunch), and worried about the wording that said the hall was for &lt;a href="http://en.wikipedia.org/wiki/Saudi_Aramco"&gt;Saudi Aramco&lt;/a&gt; staff only, one of the staff members waved me in with a smile.&lt;/p&gt;
&lt;p&gt;What I discovered is that the food hall has both very good and very affordable food. Cans of drink, bottles of water, and cups of coffee were almost universally 1 &lt;a href="http://en.wikipedia.org/wiki/Saudi_riyal"&gt;riyal&lt;/a&gt; (about $0.30 AUD). Some basic meals were available for about 4-5 riyals (under $2.00 AUD), with the best value for money undoubtedly being the "budget meal", which provided soup, vegetables, rice/potatoes, a generous main meal serving, and a dessert, all for 11.5 riyals (about $4 AUD).&lt;/p&gt;
&lt;p&gt;I got myself a salad (which were excellent), some soup, and some coffee, and felt very thankful that I had changed myself some 300 riyals (about $100 AUD) while in Dubai, since I hadn't spotted any way of doing money exchange at the &lt;a href="http://en.wikipedia.org/wiki/King_Fahd_International_Airport"&gt;Dammam airport&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The rest of my travels included a walk around the camp, the most interesting part of which was a fenced area that seemed to include a library and a bowling alley. Here also a large sign proclaimed the facilities were for Aramco employees only, and passes will be checked on entry. I was getting the feeling that having an employee pass would be a good idea.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Saudi Arabian Adventures - Day 2&lt;/b&gt;&lt;br /&gt;
Today was my first day of teaching. Fuad, my contact at Aramco, had arranged to meet me at 7am at the hotel, and I had noted from my trip to the food hall yesterday that it opened for breakfast at 5am. Collectively, these were hints that Saudis were morning people. I set my alarm for 5am, which in my jet-lagged state would feel like waking up at noon in Australia.&lt;/p&gt;
&lt;p&gt;Going to the food hall for breakfast once again had me feel like I was in America; the most popular food that people ordered were waffles! Of course, I didn't fly half-way around the world just to have waffles for breakfast, so I ordered a generous bowl of &lt;a href="http://en.wikipedia.org/wiki/Ful_medames"&gt;ful medames&lt;/a&gt;... and waffles.&lt;/p&gt;
&lt;p&gt;Of the two breakfast foods, ful was the clear winner. It tasted good, and unlike the waffles, it had actual nutritional content. I finished breakfast with plenty of time to meet Fuad back at the hotel at 7am.&lt;/p&gt;
&lt;p&gt;Fuad chuckled at my attempts at an Arabic greeting, and asked in perfect English "where are you learning this stuff, a phrase book?". I think that means my Arabic has some ways to go. ;)&lt;/p&gt;
&lt;p&gt;Fuad asked about my flight here, explained that the Aramco camp was generally divided into zones, the general business hours (7:30am-3:30pm), and helped me get set up with my lab. I was also glad to hear he would be attending my first course.&lt;/p&gt;
&lt;p&gt;At this point, I should explain a little about what I was teaching. My class consisted primarily of people with job titles that started with "Geo-", and who regularly had to deal with data that was in formats different to what they would prefer. Unsurprisingly, they'd like to use Perl to help solve these problems. That's an increasingly common story with the courses I teach.&lt;/p&gt;
&lt;p&gt;What made this interesting is that rather than having a good four or five days (which is what I'd prefer), I was teaching two classes, a dozen students in each, with only 2.5 days per class. To top that off, I was in a different country, and I had no idea how comprehensible my Australian accent would be. I'd put together a plan that covered the basics (syntax, variables, and control structures) a tour of the CPAN, and as much regexp content as I could squeeze in.&lt;/p&gt;
&lt;p&gt;When we were doing introductions, it became clear that my class had a good sense of my humour. My favourite introduction was from &lt;a href="http://twitter.com/zagzoog"&gt;one student&lt;/a&gt; who said "my name is very hard to remember... it's Mohammed".&lt;/p&gt;
&lt;p&gt;The first day of teaching went well, and from the bountiful, well-thought out questions, it was clear that I was being understood.&lt;/p&gt;
&lt;p&gt;Posted: 25th June 2009.&lt;/p&gt;
&lt;p&gt;Tags: &lt;a href="http://pjf.id.au/blog/toc.html?tag=adventure" rel="tag"&gt;adventure&lt;/a&gt; &lt;a href="http://pjf.id.au/blog/toc.html?tag=aramco" rel="tag"&gt;aramco&lt;/a&gt; &lt;a href="http://pjf.id.au/blog/toc.html?tag=dhahran" rel="tag"&gt;dhahran&lt;/a&gt; &lt;a href="http://pjf.id.au/blog/toc.html?tag=perl" rel="tag"&gt;perl&lt;/a&gt; &lt;a href="http://pjf.id.au/blog/toc.html?tag=saudi" rel="tag"&gt;saudi&lt;/a&gt; &lt;a href="http://pjf.id.au/blog/toc.html?tag=travel" rel="tag"&gt;travel&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Bookmark:&lt;/p&gt;
&lt;a href="http://digg.com/submit?phase=2&amp;amp;url=http%3A%2F%2Fpjf.id.au%2Fblog%2F%3Fposition%3D576&amp;amp;title=Saudi%20Arabian%20Adventures%20-%20Days%201-2"&gt;&lt;img src="http://pjf.id.au/images/icons/digg.png" alt="Digg this"&gt;&lt;/a&gt; &lt;a href="http://www.technorati.com/faves?add=http%3A%2F%2Fpjf.id.au%2Fblog%2F%3Fposition%3D576"&gt;&lt;img src="http://pjf.id.au/images/icons/technorati.png" alt="Digg this"&gt;&lt;/a&gt;</content>
    <published>2009-06-25T00:00:00Z</published>
    <updated>2009-06-25T00:00:00Z</updated>
    <author>
      <name>nobody</name>
    </author>
    <id>tag:perlsphere.net,2006:http://pjf.id.au/blog/?position=576</id>
  </entry>
  <entry>
    <title>YAPC::NA</title>
    <link rel="alternate" href="http://feedproxy.google.com/~r/yuvalkogman/~3/NJnpeGDlNe8/yapcna.html" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">So YAPC::NA is over, or at least the conference proper is (there are
still a few days of hacking to look forward to). It was a pretty bad YAPC
for me, I was sick the whole time and didn't really see any talks and
barely socialized. I do feel better now so hopefully I can still salvage
some fun.

I am also a little disappointed in my own talk as well. I was hoping to
be a bit more practical, but every time I tried to write slides with that
in mind I got lost in endless digressions. In the end I think it was a
little too shallow and ranty, not exactly what I had hoped for. It did
seem to be rather well received so at least I'm happy about that.

I also don't think I presented well, but given that I feeling very bad I
guess I can't complain. By the end I was having tunnel vision and my ears
felt really pressurized. Someone said I sounded like I was bored with my
talk, so I guess it didn't go as bad as I felt ;-)

Anyway, here's hoping for a productive hackathon, and a quick recovery.

[IMAGE][IMAGE]</div>
    </summary>
    <content type="html">&lt;p&gt;So YAPC::NA is over, or at least the conference proper is (there are still a few days of hacking to look forward to). It was a pretty bad YAPC for me, I was sick the whole time and didn't really see any talks and barely socialized. I do feel better now so hopefully I can still salvage some fun.&lt;/p&gt;
&lt;p&gt;I am also a little disappointed in my own talk as well. I was hoping to be a bit more practical, but every time I tried to write slides with that in mind I got lost in endless digressions. In the end I think it was a little too shallow and ranty, not exactly what I had hoped for. It did seem to be rather well received so at least I'm happy about that.&lt;/p&gt;
&lt;p&gt;I also don't think I presented well, but given that I feeling very bad I guess I can't complain. By the end I was having tunnel vision and my ears felt really pressurized. Someone said I sounded like I was bored with my talk, so I guess it didn't go as bad as I felt ;-)&lt;/p&gt;
&lt;p&gt;Anyway, here's hoping for a productive hackathon, and a quick recovery.&lt;/p&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img&gt;&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/yuvalkogman/~4/NJnpeGDlNe8"&gt;</content>
    <category term="yapc perl"/>
    <published>2009-06-24T20:17:00Z</published>
    <updated>2009-06-24T20:17:00Z</updated>
    <author>
      <name>nothingmuch</name>
    </author>
    <id>tag:perlsphere.net,2006:tag:blogger.com,1999:blog-876358347971598886.post-7223233603435107245</id>
  </entry>
  <entry>
    <title>Perlbuzz news roundup for 2009-06-24</title>
    <link rel="alternate" href="http://feedproxy.google.com/~r/PerlBuzz/~3/3nJWZnPizCE/perlbuzz-news-roundup-for-2009-06-24.html" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">These links are collected from the Perlbuzz Twitter feed. If you have
suggestions for news bits, please mail me at andy@perlbuzz.com.

  * How Perl 6 just sells itself

  * Converting an A4 PDF to Letter with Margins

  * Read-optimize your source code

  * Optimizing life for reduced frustration

  * Request for assistance: The most important toolchain bug

  * Stealing from Padre for Vim

  * Allison Randal in Linux Magazine: "Why Parrot is Important"

  * Anyone want to adopt Getopt::Auto?

  * Rakudo Perl 6 dev release #18: Pittsburgh

  * DBIx::Class vs Class::DBI vs Rose::DB::Object vs Fey::ORM

  * 3D graphics with Perl 6

  * A gentle introduction to Moose

  * "Radical Career Success in a Down Economy": A free webcast on July
    1st

  * Gray coding at the pediatrician's office

  * What I got out of the Parrot Workshop

  * Rakudo gets mainstream press attention in SD Times

  * Movable Type fork is an opportunity to harness CPAN

  * YAPC::NA 2010 will be in Columbus, Ohio

  * Scaling out is frictionless when you use open source software

[IMAGE] [IMAGE] [IMAGE] [IMAGE][IMAGE]</div>
    </summary>
    <content type="html">&lt;p&gt;These links are collected from the &lt;a href="http://twitter.com/perlbuzz"&gt;Perlbuzz Twitter feed&lt;/a&gt;. If you have suggestions for news bits, please mail me at &lt;a href="mailto:andy@perlbuzz.com"&gt;andy@perlbuzz.com&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://use.perl.org/~masak/journal/39025"&gt;How Perl 6 just sells itself&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://dague.net/2009/06/12/the-power-of-perl-converting-an-a4-pdf-to-letter-with-margins/"&gt;Converting an A4 PDF to Letter with Margins&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.brendel.com/consulting/blog/2009/06/read-optimized-source-code.html"&gt;Read-optimize your source code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://broadcast.oreilly.com/2009/06/spending-10-minutes-to-save-1.html"&gt;Optimizing life for reduced frustration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://use.perl.org/~Alias/journal/39134"&gt;Request for assistance: The most important toolchain bug&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://code-and-hacks.blogspot.com/2009/06/stealing-from-padre-for-vim.html"&gt;Stealing from Padre for Vim&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.linux-mag.com/id/7373"&gt;Allison Randal in Linux Magazine: "Why Parrot is Important"&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://use.perl.org/~Aristotle/journal/39143"&gt;Anyone want to adopt Getopt::Auto?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://rakudo.org/node/46"&gt;Rakudo Perl 6 dev release #18: Pittsburgh&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.afoolishmanifesto.com/archives/822"&gt;DBIx::Class vs Class::DBI vs Rose::DB::Object vs Fey::ORM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://use.perl.org/~masak/journal/39152"&gt;3D graphics with Perl 6&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.catalyzed.org/2009/06/a-gentle-introduction-to-moose.html"&gt;A gentle introduction to Moose&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://theworkinggeek.com/2009/06/free-webcast-radical-career-success-in-a-down-econ.html"&gt;"Radical Career Success in a Down Economy": A free webcast on July 1st&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.plover.com/2009/06/21/"&gt;Gray coding at the pediatrician's office&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://elliotlovesperl.com/2009/06/22/what-i-got-out-of-the-parrot-workshop/"&gt;What I got out of the Parrot Workshop&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.sdtimes.com/link/33566"&gt;Rakudo gets mainstream press attention in SD Times&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://mark.stosberg.com/blog/2009/06/movable-type-fork-is-an-opportunity-to-harness-cpan.html"&gt;Movable Type fork is an opportunity to harness CPAN&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://news.perlfoundation.org/2009/06/yapcna_2010_in_columbus.html"&gt;YAPC::NA 2010 will be in Columbus, Ohio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.codinghorror.com/blog/archives/001279.html"&gt;Scaling out is frictionless when you use open source software&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="feedflare"&gt;&lt;a href="http://feeds.feedburner.com/~ff/PerlBuzz?a=3nJWZnPizCE:s9MBZGU9odE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PerlBuzz?d=yIl2AUoC8zA"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PerlBuzz?a=3nJWZnPizCE:s9MBZGU9odE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PerlBuzz?i=3nJWZnPizCE:s9MBZGU9odE:F7zBnMyn0Lo"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PerlBuzz?a=3nJWZnPizCE:s9MBZGU9odE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PerlBuzz?i=3nJWZnPizCE:s9MBZGU9odE:V_sGLiPBpWU"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PerlBuzz?a=3nJWZnPizCE:s9MBZGU9odE:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PerlBuzz?d=qj6IDK7rITs"&gt;&lt;/a&gt;&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/PerlBuzz/~4/3nJWZnPizCE"&gt;</content>
    <published>2009-06-24T17:11:51Z</published>
    <updated>2009-06-24T17:11:51Z</updated>
    <author>
      <name>Andy Lester</name>
    </author>
    <id>tag:perlsphere.net,2006:tag:perlbuzz.com,2009://1.687</id>
  </entry>
  <entry>
    <title>Nested TAP Now Available In Developer Release</title>
    <link rel="alternate" href="http://use.perl.org/~Ovid/journal/39167?from=rss" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">Schwern has released Test::Simple 0.89_01. Nested TAP is now available.
In case you don't recall (or haven't heard about this), you might write a
subtest like this:

  use Test::More tests =&gt; 3;

  pass("First test");

  subtest 'An example subtest' =&gt; sub {
  plan tests =&gt; 2;

  pass("This is a subtest");
  pass("So is this");
  };

  pass("Third test");

And get the following nested TAP:

  1..3
  ok 1 - First test
  1..2
  ok 1 - This is a subtest
  ok 2 - So is this
  ok 2 - An example subtest
  ok 3 - Third test

(Adrian, I believe you have a branch of Test::Class which uses this? :)</div>
    </summary>
    <content type="html">&lt;p&gt;Schwern has released &lt;a href="http://search.cpan.org/~mschwern/Test-Simple-0.89_01/"&gt;Test::Simple 0.89_01&lt;/a&gt;. Nested TAP is now available. In case you don't recall (or haven't heard about this), you might write a subtest like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;
&lt;p&gt;&lt;tt&gt;&amp;nbsp; use Test::More tests =&amp;gt; 3;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; pass("First test");&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; subtest 'An example subtest' =&amp;gt; sub {&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; plan tests =&amp;gt; 2;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; pass("This is a subtest");&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; pass("So is this");&lt;br /&gt;
&amp;nbsp; };&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; pass("Third test");&lt;/tt&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;p&gt;And get the following nested TAP:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;
&lt;p&gt;&lt;tt&gt;&amp;nbsp; 1..3&lt;br /&gt;
&amp;nbsp; ok 1 - First test&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; 1..2&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; ok 1 - This is a subtest&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; ok 2 - So is this&lt;br /&gt;
&amp;nbsp; ok 2 - An example subtest&lt;br /&gt;
&amp;nbsp; ok 3 - Third test&lt;/tt&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;p&gt;(Adrian, I believe you have a branch of &lt;a href="http://search.cpan.org/dist/Test-Class/"&gt;Test::Class&lt;/a&gt; which uses this? &lt;nobr&gt;&lt;wbr /&gt;&lt;/nobr&gt;:)&lt;/p&gt;</content>
    <category term="journal"/>
    <published>2009-06-24T07:50:18Z</published>
    <updated>2009-06-24T07:50:18Z</updated>
    <author>
      <name>Ovid</name>
    </author>
    <id>tag:perlsphere.net,2006:http://use.perl.org/~Ovid/journal/39167?from=rss</id>
  </entry>
  <entry>
    <title>Another stupid geek argument</title>
    <link rel="alternate" href="http://use.perl.org/~xsawyerx/journal/39166?from=rss" type="text/html"/>
    <summary type="text">While I contemplate on this new pale white design of use.perl.org, hoping
it's either temporary or half of what it's meant to be, I wanted to share
an argument I had yesterday at $work.

A co-worker presented me a problem:

  34 sub scan_array {
  35   my ( $item, $arrayref ) = @_;
  36
  37   # does the $item and $_ equal
  38   if ( any { lc($item) eq lc($_) } @{$arrayref} )   ||
  39   # or does $item is part of $_ but not equal to it
  40  ( any { $_ =~ /$item/i } @{$arrayref} )   {
  41   return 1;
  42   }
  43   elsif  {
  44   return 1;
  45   }
  46
  47   return 0;
  48 }
  syntax error at tests_include.pl line 38, near ")   ||"
  Global symbol "$arrayref" requires explicit package name at
  tests_include.pl line 40.
  syntax error at tests_include.pl line 40, near "} )

"why can't it find the arrayref ?!"

Can you spot the error? I have. The if() is missing the encompassing
brackets. What actually happened is that perl is thinking that the if()
statement ended with the first closing bracket, and then could not
interpret the || after. Instead of running if (CONDITION || CONDITION),
it ran IF (CONDITION) || CONDITION and according to the syntax of Perl,
this shouldn't work, and it didn't.

After explaining to my co-worker (who is indeed a talented programmer)
the simple error, he claimed that Perl is stupid because this is the way
it works. Now, I should note that I don't really care when people rag on
Perl since they're plainly missing something very awesome. I merely
explain and move on, albeit often I ignore when I sense a large
concentration of ignorance or "showoffness". However, this annoyed me.
Since I have a deep interest in optimal writing, programming patterns and
coherent coding styles, I found this particularly annoying, as it is
simply a matter of incorrect syntax usage, clearly not a language
problem.

I stated simply that in almost every language, you have brackets around
the if(), and when he proclaimed that in Pascal (of all languages,
Pascal? Really?) it is not like that, I simply reaffirmed that Pascal
decided not to have that, good for Pascal. However, Pascal just uses the
next then to understand when the if ends. That's all. Perl decided to be
more pro-active about this and allow more readable code (readable? Perl?
YES!). That's also why Perl has mandatory code brackets even on a single
if(). Perl however, does allow you to remove both the code brackets and
if condition brackets on postfix if()s.

This argument (as many other stupid geek arguments) ensued and enrolled
two other developers who both suggested that what I say makes the most
sense but that even if you could write it without the condition brackets,
it wouldn't be as understandable, and that's an additional minus on its
own.

If you want to complain about a language, try to pick better things to
complain about. I could give you half a dozen things I don't like about
Perl (I think...) which are waaaaay better to complain about besides the
fact that "it makes me write an additional pair of brackets around the if,
what the fuck?!" &lt;-- exact quote OMG.</summary>
    <content type="html">&lt;p&gt;While I contemplate on this new pale white design of use.perl.org, hoping it's either temporary or half of what it's meant to be, I wanted to share an argument I had yesterday at $work.&lt;/p&gt;
&lt;p&gt;A co-worker presented me a problem:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;
&lt;p&gt;&lt;tt&gt;34 sub scan_array {&lt;br /&gt;
35&amp;nbsp; &amp;nbsp; &amp;nbsp;my ( $item, $arrayref ) = @_;&lt;br /&gt;
36&lt;br /&gt;
37&amp;nbsp; &amp;nbsp; &amp;nbsp;# does the $item and $_ equal&lt;br /&gt;
38&amp;nbsp; &amp;nbsp; &amp;nbsp;if ( any { lc($item) eq lc($_) } @{$arrayref} )&amp;nbsp; &amp;nbsp;||&lt;br /&gt;
39&amp;nbsp; &amp;nbsp; &amp;nbsp;# or does $item is part of $_ but not equal to it&lt;br /&gt;
40&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ( any { $_ =~ &lt;nobr&gt;&lt;wbr /&gt;&lt;/nobr&gt;/$item/i } @{$arrayref} )&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{&lt;br /&gt;
41&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return 1;&lt;br /&gt;
42&amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;br /&gt;
43&amp;nbsp; &amp;nbsp; &amp;nbsp;elsif&amp;nbsp; {&lt;br /&gt;
44&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return 1;&lt;br /&gt;
45&amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;br /&gt;
46&lt;br /&gt;
47&amp;nbsp; &amp;nbsp; &amp;nbsp;return 0;&lt;br /&gt;
48 }&lt;br /&gt;
syntax error at tests_include.pl line 38, near ")&amp;nbsp; &amp;nbsp;||"&lt;br /&gt;
Global symbol "$arrayref" requires explicit package name at tests_include.pl line 40.&lt;br /&gt;
syntax error at tests_include.pl line 40, near "} )&lt;/tt&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;p&gt;"why can't it find the arrayref ?!"&lt;/p&gt;
&lt;p&gt;Can you spot the error? I have. The &lt;code&gt;if()&lt;/code&gt; is missing the encompassing brackets. What actually happened is that perl is thinking that the &lt;code&gt;if()&lt;/code&gt; statement ended with the first closing bracket, and then could not interpret the &lt;code&gt;||&lt;/code&gt; after. Instead of running &lt;code&gt;if (CONDITION || CONDITION)&lt;/code&gt;, it ran &lt;code&gt;IF (CONDITION) || CONDITION&lt;/code&gt; and according to the syntax of Perl, this shouldn't work, and it didn't.&lt;/p&gt;
&lt;p&gt;After explaining to my co-worker (who is indeed a talented programmer) the simple error, he claimed that Perl is stupid because this is the way it works. Now, I should note that I don't really care when people rag on Perl since they're plainly missing something &lt;b&gt;very&lt;/b&gt; awesome. I merely explain and move on, albeit often I ignore when I sense a large concentration of ignorance or "showoffness". However, this annoyed me. Since I have a deep interest in optimal writing, programming patterns and coherent coding styles, I found this particularly annoying, as it is simply a matter of incorrect syntax usage, clearly not a language problem.&lt;/p&gt;
&lt;p&gt;I stated simply that in almost every language, you have brackets around the &lt;code&gt;if()&lt;/code&gt;, and when he proclaimed that in Pascal (of all languages, Pascal? Really?) it is not like that, I simply reaffirmed that Pascal decided not to have that, good for Pascal. However, Pascal just uses the next &lt;code&gt;then&lt;/code&gt; to understand when the &lt;code&gt;if&lt;/code&gt; ends. That's all. Perl decided to be more pro-active about this and allow more readable code (readable? Perl? YES!). That's also why Perl has mandatory code brackets even on a single &lt;code&gt;if()&lt;/code&gt;. Perl however, does allow you to remove both the code brackets and &lt;code&gt;if&lt;/code&gt; condition brackets on postfix &lt;code&gt;if()&lt;/code&gt;s.&lt;/p&gt;
&lt;p&gt;This argument (as many other stupid geek arguments) ensued and enrolled two other developers who both suggested that what I say makes the most sense but that even if you could write it without the condition brackets, it wouldn't be as understandable, and that's an additional minus on its own.&lt;/p&gt;
&lt;p&gt;If you want to complain about a language, try to pick better things to complain about. I could give you half a dozen things I don't like about Perl (I think...) which are waaaaay better to complain about besides the fact that "it makes me write an additional pair of brackets around the &lt;code&gt;if&lt;/code&gt;, what the fuck?!" &amp;lt;-- exact quote OMG.&lt;/p&gt;</content>
    <category term="journal"/>
    <published>2009-06-24T07:44:26Z</published>
    <updated>2009-06-24T07:44:26Z</updated>
    <author>
      <name>xsawyerx</name>
    </author>
    <id>tag:perlsphere.net,2006:http://use.perl.org/~xsawyerx/journal/39166?from=rss</id>
  </entry>
  <entry>
    <title>Data driven programming</title>
    <link rel="alternate" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">The other days somebody asked on IRC for help with this question:

He was looking for all 9 digit numbers that didn't contain a zero digit
anywhere, and the first digit should be divisible by one, the number
formed from the first two digits should be divisible by 2, the number
formed from the first three digits should be divisible by 3 etc.

The first such number is 1232525616, because 1 can be divided by 1, 12
can be divided by 2, 123 can be divided by 3 etc.

Since finding one isn't really a challenge, let's focus on finding them
all. The easiest approach is, of course, brute force. There are 109
numbers with 9 digits, that's quite a manageable number for a modern
computer. On my laptop it takes perl about 45 seconds to loop over all 109
numbers, doing nothing else.

So all you've got to do is iterate over all numbers, test if they meet
the criterion stated above, and print them out if they do:

use strict;use warnings;sub test {
    my $z = shift;
    for (2..9) {
        return if (substr($z, 0, $_) % $_ != 0);
    }
    return 1;
}
for (my $i = 1 x 9; length($i) == 9; $i += 9) {
    next if $i =~ /0/;
    if (test($i)) {
        print $i, $/;
    }
}

This uses a small trick: the first number that doesn't contain any zero
is 111111111, or short 1 x 9.

It takes 4 minutes and 20 seconds, produces the right answer, and we're
happy.

But it wastes a lot of resources, and wouldn't scale for larger numbers.
So for the sake of fun I tried a few different optimizations.

The first one is quite simple: the second digit must always be even,
otherwise the number consisting of the first two digits could not be
even. Likewise the fifths digit must be 5 or 0 to ensure that it can be
divided by 5. Since 0 is forbidden anyway, it has to be 5. So let's skip
the expensive check if those conditions aren't fulfilled:

for (my $i = 1 x 9; length($i) == 9; $i += 9) {
    next if $i =~ /0/;
    next if $i =~ /^.[13579]/;
    next unless $i =~ /^....5/;
    if (test($i)) {
        print $i, $/;
    }
}

This speeds up the computation to roughly a minute. Since 40 seconds are
minimum for the iteration alone, it's nearly as good as it gets with this
approach.

But of course there's still room for improvement: when the second digit
is odd, the program iterates over a hundred million of numbers without
finding one. Instead of skipping them each time, it would be much more
efficient to generate the number digit by digit, checking divisibility at
each step of the way.

for my $a (1..9) {
    for my $b (2, 4, 6, 8) {
        for my $c (1..9) {
            next if ($a + $b + $c) % 3;
            for my $d (2, 4, 6, 8) {
                next if (10 * $c + $d) % 4;
                my $e = 5;
                for my $f (2, 4, 6, 8) {
                    next if ($a + $b + $c + $d + $e + $f) % 3;
                    for my $g (1..9) {
                        my $so_far = "$a$b$c$d$e$f$g";
                        next if $so_far % 7;
                        for my $h (2, 4, 6, 8) {
                            next if ($so_far . $h) % 8;
                            for my $i (1..9) {
                                my $so_far = $so_far . "$h$i";
                                next if $so_far % 9;
                                print "$so_far$h\n";
                            }
                        }
                    }
                }
            }
        }
    }
}

Wow, that's ugly code, but it works and it's fast. Very fast. 27
milliseconds, or more than 2000 times faster as the previous version.

Bug it contains lots of duplicated code, and again it wouldn't scale for
finding larger numbers, this time because for digit a loop needs to be
written.

Whenever I find myself repeating some piece of code a few times, but in
slightly different forms, I try to pack the code into a data structure
instead.

For each digit position there needs to a list of digit to try, and a test
that determines if the newly added digit violates its divisibility rule.

use strict;use warnings;
my @config = (
    [[1..9],        sub { 0 }],
    [[2, 4, 6, 8],  sub { 0 }],
    [[1..9],        sub { $_[0] % 3}],
    [[2, 4, 6, 8],  sub { $_[0] % 4 }],
    [[5],           sub { 0 }],
    [[2, 4, 6, 8],  sub { $_[0] % 6 }],
    [[1..9],        sub { $_[0] % 7 }],
    [[2, 4, 6, 8],  sub { $_[0] % 8 }],
    [[1..9],        sub { $_[0] % 9 }],
);

The nested loops from the previous script can be emulated by recursion,
passing the previous digits along (and the configuration for all digit
positions that still need to be tested).

sub f {
    my ($so_far, $config) = @_; 
    $config = [ @$config ];
    if (!@$config) {
        print "$so_far\n";
    } else {
        my $c = shift @$config;
        for my $current (@{$c-&gt;[0]}) {
            next if $c-&gt;[1]-&gt;($so_far . $current);
            f($so_far . $current, $config);
        }
    }
}

f('', \@config);

With 46ms runtime it's still acceptably fast, and much leaner than the
nested loops.

Actually a rough sketch of the configuration table can also be generated
automatically, and then optimized manually:

my @config;
for my $n (1..9) {
    push @config, [
        ($n % 2 ? [1..9] : [2, 4, 6, 8]),
        sub { $_[0] % $n },
    ]
}$config[4] = [[5], sub { 0 } ];

Now the script contains as little duplication as possible, is reasonably
fast, and I'm happy.

(Just one final note: there's no scalability problem in this particular
task, because it can't be extended to more than nine digits: if no zero
is allowed, there won't be any numbers divisible by 10.)</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml"><p>The other days somebody asked on IRC for help with this question:</p>
<p>He was looking for all 9 digit numbers that didn't contain a zero digit anywhere, and the first digit should be divisible by one, the number formed from the first two digits should be divisible by 2, the number formed from the first three digits should be divisible by 3 etc.</p>
<p>The first such number is 1232525616, because 1 can be divided by 1, 12 can be divided by 2, 123 can be divided by 3 etc.</p>
<p>Since finding one isn't really a challenge, let's focus on finding them all. The easiest approach is, of course, brute force. There are 10<sup>9</sup> numbers with 9 digits, that's quite a manageable number for a modern computer. On my laptop it takes perl about 45 seconds to loop over all 10<sup>9</sup> numbers, doing nothing else.</p>
<p>So all you've got to do is iterate over all numbers, test if they meet the criterion stated above, and print them out if they do:</p>
<pre>
<span class="synStatement">use strict</span>;
<span class="synStatement">use warnings</span>;
<span class="synStatement">sub </span><span class="synIdentifier">test </span>{
    <span class="synStatement">my</span> <span class="synIdentifier">$z</span> = <span class="synStatement">shift</span>;
    <span class="synStatement">for</span> (<span class="synConstant">2..9</span>) {
        <span class="synStatement">return</span> <span class="synStatement">if</span> (<span class="synStatement">substr</span>(<span class="synIdentifier">$z</span>, <span class="synConstant">0</span>, <span class="synIdentifier">$_</span>) % <span class="synIdentifier">$_</span> != <span class="synConstant">0</span>);
    }
    <span class="synStatement">return</span> <span class="synConstant">1</span>;
}

<span class="synStatement">for</span> (<span class="synStatement">my</span> <span class="synIdentifier">$i</span> = <span class="synConstant">1</span> x <span class="synConstant">9</span>; <span class="synStatement">length</span>(<span class="synIdentifier">$i</span>) == <span class="synConstant">9</span>; <span class="synIdentifier">$i</span> += <span class="synConstant">9</span>) {
    <span class="synStatement">next</span> <span class="synStatement">if</span> <span class="synIdentifier">$i</span> =~ <span class="synStatement">/</span><span class="synConstant">0</span><span class="synStatement">/</span>;
    <span class="synStatement">if</span> (test(<span class="synIdentifier">$i</span>)) {
        <span class="synStatement">print</span> <span class="synIdentifier">$i</span>, <span class="synIdentifier">$/</span>;
    }
}
</pre>
<p>This uses a small trick: the first number that doesn't contain any zero is <code>111111111</code>, or short <code>1 x 9</code>.</p>
<p>It takes 4 minutes and 20 seconds, produces the right answer, and we're happy.</p>
<p>But it wastes a lot of resources, and wouldn't scale for larger numbers. So for the sake of fun I tried a few different optimizations.</p>
<p>The first one is quite simple: the second digit must always be even, otherwise the number consisting of the first two digits could not be even. Likewise the fifths digit must be 5 or 0 to ensure that it can be divided by 5. Since 0 is forbidden anyway, it has to be 5. So let's skip the expensive check if those conditions aren't fulfilled:</p>
<pre>
<span class="synStatement">for</span> (<span class="synStatement">my</span> <span class="synIdentifier">$i</span> = <span class="synConstant">1</span> x <span class="synConstant">9</span>; <span class="synStatement">length</span>(<span class="synIdentifier">$i</span>) == <span class="synConstant">9</span>; <span class="synIdentifier">$i</span> += <span class="synConstant">9</span>) {
    <span class="synStatement">next</span> <span class="synStatement">if</span> <span class="synIdentifier">$i</span> =~ <span class="synStatement">/</span><span class="synConstant">0</span><span class="synStatement">/</span>;
    <span class="synStatement">next</span> <span class="synStatement">if</span> <span class="synIdentifier">$i</span> =~ <span class="synStatement">/</span><span class="synConstant">^</span><span class="synSpecial">.[13579]</span><span class="synStatement">/</span>;
    <span class="synStatement">next</span> <span class="synStatement">unless</span> <span class="synIdentifier">$i</span> =~ <span class="synStatement">/</span><span class="synConstant">^</span><span class="synSpecial">....</span><span class="synConstant">5</span><span class="synStatement">/</span>;
    <span class="synStatement">if</span> (test(<span class="synIdentifier">$i</span>)) {
        <span class="synStatement">print</span> <span class="synIdentifier">$i</span>, <span class="synIdentifier">$/</span>;
    }
}
</pre>
<p>This speeds up the computation to roughly a minute. Since 40 seconds are minimum for the iteration alone, it's nearly as good as it gets with this approach.</p>
<p>But of course there's still room for improvement: when the second digit is odd, the program iterates over a hundred million of numbers without finding one. Instead of skipping them each time, it would be much more efficient to generate the number digit by digit, checking divisibility at each step of the way.</p>
<pre>
<span class="synStatement">for</span> <span class="synStatement">my</span> <span class="synIdentifier">$a</span> (<span class="synConstant">1..9</span>) {
    <span class="synStatement">for</span> <span class="synStatement">my</span> <span class="synIdentifier">$b</span> (<span class="synConstant">2</span>, <span class="synConstant">4</span>, <span class="synConstant">6</span>, <span class="synConstant">8</span>) {
        <span class="synStatement">for</span> <span class="synStatement">my</span> <span class="synIdentifier">$c</span> (<span class="synConstant">1..9</span>) {
            <span class="synStatement">next</span> <span class="synStatement">if</span> (<span class="synIdentifier">$a</span> + <span class="synIdentifier">$b</span> + <span class="synIdentifier">$c</span>) % <span class="synConstant">3</span>;
            <span class="synStatement">for</span> <span class="synStatement">my</span> <span class="synIdentifier">$d</span> (<span class="synConstant">2</span>, <span class="synConstant">4</span>, <span class="synConstant">6</span>, <span class="synConstant">8</span>) {
                <span class="synStatement">next</span> <span class="synStatement">if</span> (<span class="synConstant">10</span> * <span class="synIdentifier">$c</span> + <span class="synIdentifier">$d</span>) % <span class="synConstant">4</span>;
                <span class="synStatement">my</span> <span class="synIdentifier">$e</span> = <span class="synConstant">5</span>;
                <span class="synStatement">for</span> <span class="synStatement">my</span> <span class="synIdentifier">$f</span> (<span class="synConstant">2</span>, <span class="synConstant">4</span>, <span class="synConstant">6</span>, <span class="synConstant">8</span>) {
                    <span class="synStatement">next</span> <span class="synStatement">if</span> (<span class="synIdentifier">$a</span> + <span class="synIdentifier">$b</span> + <span class="synIdentifier">$c</span> + <span class="synIdentifier">$d</span> + <span class="synIdentifier">$e</span> + <span class="synIdentifier">$f</span>) % <span class="synConstant">3</span>;
                    <span class="synStatement">for</span> <span class="synStatement">my</span> <span class="synIdentifier">$g</span> (<span class="synConstant">1..9</span>) {
                        <span class="synStatement">my</span> <span class="synIdentifier">$so_far</span> = <span class="synConstant">"</span><span class="synIdentifier">$a$b$c$d$e$f$g</span><span class="synConstant">"</span>;
                        <span class="synStatement">next</span> <span class="synStatement">if</span> <span class="synIdentifier">$so_far</span> % <span class="synConstant">7</span>;
                        <span class="synStatement">for</span> <span class="synStatement">my</span> <span class="synIdentifier">$h</span> (<span class="synConstant">2</span>, <span class="synConstant">4</span>, <span class="synConstant">6</span>, <span class="synConstant">8</span>) {
                            <span class="synStatement">next</span> <span class="synStatement">if</span> (<span class="synIdentifier">$so_far</span> . <span class="synIdentifier">$h</span>) % <span class="synConstant">8</span>;
                            <span class="synStatement">for</span> <span class="synStatement">my</span> <span class="synIdentifier">$i</span> (<span class="synConstant">1..9</span>) {
                                <span class="synStatement">my</span> <span class="synIdentifier">$so_far</span> = <span class="synIdentifier">$so_far</span> . <span class="synConstant">"</span><span class="synIdentifier">$h$i</span><span class="synConstant">"</span>;
                                <span class="synStatement">next</span> <span class="synStatement">if</span> <span class="synIdentifier">$so_far</span> % <span class="synConstant">9</span>;
                                <span class="synStatement">print</span> <span class="synConstant">"</span><span class="synIdentifier">$so_far$h</span><span class="synSpecial">\n</span><span class="synConstant">"</span>;
                            }
                        }
                    }
                }
            }
        }
    }
}
</pre>
<p>Wow, that's ugly code, but it works and it's fast. Very fast. 27 milliseconds, or more than 2000 times faster as the previous version.</p>
<p>Bug it contains lots of duplicated code, and again it wouldn't scale for finding larger numbers, this time because for digit a loop needs to be written.</p>
<p>Whenever I find myself repeating some piece of code a few times, but in slightly different forms, I try to pack the code into a data structure instead.</p>
<p>For each digit position there needs to a list of digit to try, and a test that determines if the newly added digit violates its divisibility rule.</p>
<pre>
<span class="synStatement">use strict</span>;
<span class="synStatement">use warnings</span>;

<span class="synStatement">my</span> <span class="synIdentifier">@config</span> = (
    [[<span class="synConstant">1..9</span>],        <span class="synStatement">sub </span>{ <span class="synConstant">0</span> }],
    [[<span class="synConstant">2</span>, <span class="synConstant">4</span>, <span class="synConstant">6</span>, <span class="synConstant">8</span>],  <span class="synStatement">sub </span>{ <span class="synConstant">0</span> }],
    [[<span class="synConstant">1..9</span>],        <span class="synStatement">sub </span>{ <span class="synIdentifier">$_[</span><span class="synConstant">0</span><span class="synIdentifier">]</span> % <span class="synConstant">3</span>}],
    [[<span class="synConstant">2</span>, <span class="synConstant">4</span>, <span class="synConstant">6</span>, <span class="synConstant">8</span>],  <span class="synStatement">sub </span>{ <span class="synIdentifier">$_[</span><span class="synConstant">0</span><span class="synIdentifier">]</span> % <span class="synConstant">4</span> }],
    [[<span class="synConstant">5</span>],           <span class="synStatement">sub </span>{ <span class="synConstant">0</span> }],
    [[<span class="synConstant">2</span>, <span class="synConstant">4</span>, <span class="synConstant">6</span>, <span class="synConstant">8</span>],  <span class="synStatement">sub </span>{ <span class="synIdentifier">$_[</span><span class="synConstant">0</span><span class="synIdentifier">]</span> % <span class="synConstant">6</span> }],
    [[<span class="synConstant">1..9</span>],        <span class="synStatement">sub </span>{ <span class="synIdentifier">$_[</span><span class="synConstant">0</span><span class="synIdentifier">]</span> % <span class="synConstant">7</span> }],
    [[<span class="synConstant">2</span>, <span class="synConstant">4</span>, <span class="synConstant">6</span>, <span class="synConstant">8</span>],  <span class="synStatement">sub </span>{ <span class="synIdentifier">$_[</span><span class="synConstant">0</span><span class="synIdentifier">]</span> % <span class="synConstant">8</span> }],
    [[<span class="synConstant">1..9</span>],        <span class="synStatement">sub </span>{ <span class="synIdentifier">$_[</span><span class="synConstant">0</span><span class="synIdentifier">]</span> % <span class="synConstant">9</span> }],
);
</pre>
<p>The nested loops from the previous script can be emulated by recursion, passing the previous digits along (and the configuration for all digit positions that still need to be tested).</p>
<pre>
<span class="synStatement">sub </span><span class="synIdentifier">f </span>{
    <span class="synStatement">my</span> (<span class="synIdentifier">$so_far</span>, <span class="synIdentifier">$config</span>) = <span class="synIdentifier">@_</span>; 
    <span class="synIdentifier">$config</span> = [ <span class="synIdentifier">@$config</span> ];
    <span class="synStatement">if</span> (!<span class="synIdentifier">@$config</span>) {
        <span class="synStatement">print</span> <span class="synConstant">"</span><span class="synIdentifier">$so_far</span><span class="synSpecial">\n</span><span class="synConstant">"</span>;
    } <span class="synStatement">else</span> {
        <span class="synStatement">my</span> <span class="synIdentifier">$c</span> = <span class="synStatement">shift</span> <span class="synIdentifier">@$config</span>;
        <span class="synStatement">for</span> <span class="synStatement">my</span> <span class="synIdentifier">$current</span> (<span class="synIdentifier">@{$c-&gt;[</span><span class="synConstant">0</span><span class="synIdentifier">]}</span>) {
            <span class="synStatement">next</span> <span class="synStatement">if</span> <span class="synIdentifier">$c-&gt;[</span><span class="synConstant">1</span><span class="synIdentifier">]</span>-&gt;(<span class="synIdentifier">$so_far</span> . <span class="synIdentifier">$current</span>);
            f(<span class="synIdentifier">$so_far</span> . <span class="synIdentifier">$current</span>, <span class="synIdentifier">$config</span>);
        }
    }
}

f(<span class="synConstant">''</span>, \<span class="synIdentifier">@config</span>);
</pre>
<p>With 46ms runtime it's still acceptably fast, and much leaner than the nested loops.</p>
<p>Actually a rough sketch of the configuration table can also be generated automatically, and then optimized manually:</p>
<pre>
<span class="synStatement">my</span> <span class="synIdentifier">@config</span>;

<span class="synStatement">for</span> <span class="synStatement">my</span> <span class="synIdentifier">$n</span> (<span class="synConstant">1..9</span>) {
    <span class="synStatement">push</span> <span class="synIdentifier">@config</span>, [
        (<span class="synIdentifier">$n</span> % <span class="synConstant">2</span> ? [<span class="synConstant">1..9</span>] : [<span class="synConstant">2</span>, <span class="synConstant">4</span>, <span class="synConstant">6</span>, <span class="synConstant">8</span>]),
        <span class="synStatement">sub </span>{ <span class="synIdentifier">$_[</span><span class="synConstant">0</span><span class="synIdentifier">]</span> % <span class="synIdentifier">$n</span> },
    ]
}
<span class="synIdentifier">$config[</span><span class="synConstant">4</span><span class="synIdentifier">]</span> = [[<span class="synConstant">5</span>], <span class="synStatement">sub </span>{ <span class="synConstant">0</span> } ];
</pre>
<p>Now the script contains as little duplication as possible, is reasonably fast, and I'm happy.</p>
<p>(Just one final note: there's no scalability problem in this particular task, because it can't be extended to more than nine digits: if no zero is allowed, there won't be any numbers divisible by 10.)</p></div>
    </content>
    <author>
      <name>nobody</name>
    </author>
    <id>tag:perlsphere.net,2006:http://perlgeek.de/blog-en/Data driven programming</id>
  </entry>
  <entry>
    <title> Bryar security hole </title>
    <link rel="alternate" href=" http://www.cantrell.org.uk/david/journal/index.pl/id_bryar-security-hole" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">Someone on IRC reported a bug in Bryar. Namely that a Naughty Person can
exploit the feature that notifies you of blog-spam by email to execute
arbitrary code on your machine, as the user you run Bryar under.

A patched release is on the way to the CPAN, and you are strongly urged
to upgrade.</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">Someone on IRC reported a bug in Bryar. Namely that a Naughty Person can exploit the feature that notifies you of blog-spam by email to execute arbitrary code on your machine, as the user you run Bryar under.
<p>A patched release is on the way to the CPAN, and you are strongly urged to upgrade.</p></div>
    </content>
    <author>
      <name> david </name>
    </author>
    <id>tag:perlsphere.net,2006: http://www.cantrell.org.uk/david/journal/index.pl/id_bryar-security-hole</id>
  </entry>
  <entry>
    <title> Thanks, Yahoo! </title>
    <link rel="alternate" href=" http://www.cantrell.org.uk/david/journal/index.pl/id_thanks-yahoo" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">[originally posted on Apr 3 2008]

I'd like to express my warm thanks to the lovely people at Yahoo and in
particular to their bot-herders. Until quite recently, their web-crawling
bots had most irritatingly obeyed robot exclusion rules in the robots.txt
file that I have on CPANdeps. But in the last couple of weeks they've got
rid of that niggling little exclusion so now they're indexing all of the
CPAN's dependencies through my site! And for the benefit of their
important customers, they're doing it nice and quickly - a request every
few seconds instead of the pedestrian once every few minutes that gentler
bots use.

Unfortunately, because generating a dependency tree takes more time than
they were allowing between requests, they were filling up my process
table, and all my memory, and eating all the CPU, and the only way to get
back into the machine was by power-cycling it. So it is with the deepest
of regrets that I have had to exclude them.

Cunts.

[update] For fuck's sake, they're doing it again from a different
netblock!</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">[originally posted on Apr 3 2008]
<p>I'd like to express my warm thanks to the lovely people at Yahoo and in particular to their bot-herders. Until quite recently, their web-crawling bots had most irritatingly obeyed robot exclusion rules in the robots.txt file that I have on <a href="http://cpandeps.cantrell.org.uk/">CPANdeps</a>. But in the last couple of weeks they've got rid of that niggling little exclusion so now they're indexing all of the CPAN's dependencies through my site! And for the benefit of their important customers, they're doing it nice and quickly - a request every few seconds instead of the pedestrian once every few minutes that gentler bots use.</p>
<p>Unfortunately, because generating a dependency tree takes more time than they were allowing between requests, they were filling up my process table, and all my memory, and eating all the CPU, and the only way to get back into the machine was by power-cycling it. So it is with the deepest of regrets that I have had to exclude them.</p>
<p><a href="http://www.yahoo.com/">Cunts</a>.</p>
<p>[update] For fuck's sake, they're doing it again from a different netblock!</p></div>
    </content>
    <author>
      <name> david </name>
    </author>
    <id>tag:perlsphere.net,2006: http://www.cantrell.org.uk/david/journal/index.pl/id_thanks-yahoo</id>
  </entry>
  <entry>
    <title> Module pre-requisites analyser </title>
    <link rel="alternate" href=" http://www.cantrell.org.uk/david/journal/index.pl/id_cpandeps-release" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">As a service to module authors, here is a tool to show a module's
pre-requisites and the test results from the CPAN testers. So before you
rely on something working as a pre-requisite for your code, have a look
to see how reliable it and its dependencies are.</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">As a service to module authors, <a href="http://cpandeps.cantrell.org.uk/">here</a> is a tool to show a module's pre-requisites and the test results from the CPAN testers. So before you rely on something working as a pre-requisite for your code, have a look to see how reliable it and <em>its</em> dependencies are.</div>
    </content>
    <author>
      <name> david </name>
    </author>
    <id>tag:perlsphere.net,2006: http://www.cantrell.org.uk/david/journal/index.pl/id_cpandeps-release</id>
  </entry>
  <entry>
    <title> Ill </title>
    <link rel="alternate" href=" http://www.cantrell.org.uk/david/journal/index.pl/id_ill" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">I am ill. I've been ill since Thursday, with a cold. You're meant to be
able to cure a cold with [insert old wives tale remedy here] in 5 days,
or if you don't, it'll clear itself up in just under a week. So hopefully
today is the last day.

So what have I done while ill?

On Friday I became old (see previous post), and went to the Byzantium
exhibition at the Royal Academy. It was good. You should go.

Saturday was the London Perl Workshop. My talk on closures went down
well, and people seemed to understand what I was talking about. Hurrah! I
decided that rather than hang around nattering and going to a few talks,
I'd rather hide under my duvet for the rest of the day.

I mostly hid on Sunday too, and spent most of the day asleep. In a brief
moment of productivity, I got my laptop and my phone to talk to each
other using magic interwebnet bluetooth stuff. I'd tried previously
without success, but that was with the previous release of OS X. With
version X.5 it seems to Just Work, so no Evil Hacks were necessary.

The cold means that I can't taste a damned thing, not even bacon. So now
I know what it's like to be Jewish. Being Jewish sucks.

And today, I am still coughing up occasional lumps of lung and making odd
bubbling noises in my chest, although my nasal demons seem to be Snotting
less than they were, so hopefully I'll be back to normal tomorrow.</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">I am ill. I've been ill since Thursday, with a cold. You're meant to be able to cure a cold with [insert old wives tale remedy here] in 5 days, or if you don't, it'll clear itself up in just under a week. So hopefully today is the last day.
<p>So what have I done while ill?</p>
<p>On Friday I became old (see previous post), and went to the <a href="http://www.royalacademy.org.uk/exhibitions/byzantium/">Byzantium</a> exhibition at the Royal Academy. It was good. You should go.</p>
<p>Saturday was the <a href="http://conferences.yapceurope.org/lpw2008/">London Perl Workshop</a>. My talk on closures went down well, and people seemed to understand what I was talking about. Hurrah! I decided that rather than hang around nattering and going to a few talks, I'd rather hide under my duvet for the rest of the day.</p>
<p>I mostly hid on Sunday too, and spent most of the day asleep. In a brief moment of productivity, I got my laptop and my phone to talk to each other using magic interwebnet bluetooth stuff. I'd tried previously without success, but that was with the previous release of OS X. With version X.5 it seems to Just Work, so no Evil Hacks were necessary.</p>
<p>The cold means that I can't taste a damned thing, not even bacon. So now I know what it's like to be Jewish. Being Jewish <em>sucks</em>.</p>
<p>And today, I am still coughing up occasional lumps of lung and making odd bubbling noises in my chest, although my nasal demons seem to be Snotting less than they were, so hopefully I'll be back to normal tomorrow.</p></div>
    </content>
    <author>
      <name> david </name>
    </author>
    <id>tag:perlsphere.net,2006: http://www.cantrell.org.uk/david/journal/index.pl/id_ill</id>
  </entry>
  <entry>
    <title> POD includes </title>
    <link rel="alternate" href=" http://www.cantrell.org.uk/david/journal/index.pl/id_pod-includes" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">One of my CPAN distributions is CPAN-FindDependencies. It contains a
module CPAN::FindDependencies, and a simple script that wraps around it
so you can view dependencies easily from the command line. That script,
naturally, has a man page. However, that manpage basically says "if you
want to know what arguments this program takes, see the
CPAN::FindDependencies docs". This is Bad from a usability point of view,
good from a not-duplicating-stuff point of view, and good from a laziness
point of view. Which means that it's Bad.

So, the solution.

  =over

  #include shared/parameters

  =back

and some Magic that does the cpp-stylee substitution at make dist time.
Note the 'dist' section in my call to WriteMakefile.

This is, of course, crying out to be made less horribly hacky, but it
works for now, so I'm happy.

My original idea was to write some crazy shit that would do the #include
at install-time, when the user was installing my code. But that has the
disadvantage that tools like search.cpan wouldn't show it properly, as
they simply look at the files in the distribution. So this does the
#includes at the last moment just before I package up the code and upload
to the PAUSE. You lovely people get the right documentation in all the
right places, I only have to maintain it in one place so it stays in
sync, and (in the interests of Laziness) I don't have to remember to run
any extra scripts before releasing, make dist just Does The Right Thing.</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">One of my CPAN distributions is <a href="http://search.cpan.org/search?query=CPAN-FindDependencies">CPAN-FindDependencies</a>. It contains a module CPAN::FindDependencies, and a simple script that wraps around it so you can view dependencies easily from the command line. That script, naturally, has a man page. However, that manpage basically says "if you want to know what arguments this program takes, see the CPAN::FindDependencies docs". This is Bad from a usability point of view, good from a not-duplicating-stuff point of view, and good from a laziness point of view. Which means that it's Bad.
<p>So, the solution.</p>
<blockquote><tt>=over</tt>
<p><tt>#include shared/parameters</tt></p>
<p><tt>=back</tt></p>
</blockquote>
<p>and some <a href="http://www.cantrell.org.uk/cgit/cgit.cgi/perlmodules/tree/CPAN-FindDependencies/Makefile.PL?id=b643a4d95f300552b9af9e7edd1fef9ae96543b3">Magic</a> that does the <a href="http://gcc.gnu.org/onlinedocs/gcc-4.3.3/cpp/">cpp-stylee</a> substitution at <code>make dist</code> time. Note the 'dist' section in my call to <code>WriteMakefile</code>.</p>
<p>This is, of course, crying out to be made less horribly hacky, but it works for now, so I'm happy.</p>
<p>My original idea was to write some crazy shit that would do the #include at install-time, when the user was installing my code. But that has the disadvantage that tools like <a href="http://search.cpan.org/">search.cpan</a> wouldn't show it properly, as they simply look at the files in the distribution. So this does the #includes at the last moment just before I package up the code and upload to the PAUSE. You lovely people get the right documentation in all the right places, I only have to maintain it in one place so it stays in sync, and (in the interests of Laziness) I don't have to remember to run any extra scripts before releasing, <code>make dist</code> just Does The Right Thing.</p></div>
    </content>
    <author>
      <name> david </name>
    </author>
    <id>tag:perlsphere.net,2006: http://www.cantrell.org.uk/david/journal/index.pl/id_pod-includes</id>
  </entry>
  <entry>
    <title> YAPC::Europe 2007 report: day 1 </title>
    <link rel="alternate" href=" http://www.cantrell.org.uk/david/journal/index.pl/id_yapc-europe-2007-day-1" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">As is becoming normal, I used the times between talks to bugfix some of
my modules - this time Tie::STDOUT and Data::Transactional. The former
was failing on perl 5.6, the latter on 5.9.5. The former was a bug in
perl (you can't localise tied filehandles and expect the tieing to go
away in 5.6, so it now declares a dependency on 5.8), the latter was a
bug in my code.

Philippe Bruhat's talk on Net::Proxy was great - you can tell it's great
because I came away with ideas for at least four things that I need to
write. First up will be a plugin for it to allow the user to specify
minimum and maximum permitted data rates for proxied connections. This
will permit bandwidth limits for maximum permitted rates, but will also
help to defeat IDSes doing traffic analysis if you specify a minimum
permitted data rate.

This will protect (eg) ssh sessions from being identified based on their
very bursty traffic pattern, by "filling in the blanks" with junk data.

In the evening, the CPAN-testers BOF was productive.</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">As is becoming normal, I used the times between talks to bugfix some of my modules - this time <a href="http://search.cpan.org/~dcantrell/Tie-STDOUT-1.03/">Tie::STDOUT</a> and <a href="http://search.cpan.org/~dcantrell/Data-Transactional-1.0/">Data::Transactional</a>. The former was failing on perl 5.6, the latter on 5.9.5. The former was a bug in perl (you can't localise tied filehandles and expect the tieing to go away in 5.6, so it now declares a dependency on 5.8), the latter was a bug in my code.
<p>Philippe Bruhat's talk on <a href="http://search.cpan.org/~book/Net-Proxy-0.08/">Net::Proxy</a> was great - you can tell it's great because I came away with ideas for at least four things that I <em>need</em> to write. First up will be a plugin for it to allow the user to specify minimum and maximum permitted data rates for proxied connections. This will permit bandwidth limits for maximum permitted rates, but will also help to defeat IDSes doing traffic analysis if you specify a minimum permitted data rate.</p>
<p>This will protect (eg) ssh sessions from being identified based on their very bursty traffic pattern, by "filling in the blanks" with junk data.</p>
<p>In the evening, the CPAN-testers BOF was productive.</p></div>
    </content>
    <author>
      <name> david </name>
    </author>
    <id>tag:perlsphere.net,2006: http://www.cantrell.org.uk/david/journal/index.pl/id_yapc-europe-2007-day-1</id>
  </entry>
  <entry>
    <title> XML::Tiny released </title>
    <link rel="alternate" href=" http://www.cantrell.org.uk/david/journal/index.pl/id_xml-tiny" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">I have released my XML::Tiny module. The parser at its core is less than
twenty lines of code. Pretty easy to follow code too, I think, and that
also includes error handling. One of my aims in writing it was to keep
memory usage and code to the absolute minimum, so it doesn't handle all
of XML. The documentation says that it supports "a useful subset of XML".
Personally, I think it supports the useful subset. It's certainly enough
to parse the data I get back from Amazon when I use their web services,
and to parse an RSS feed.</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">I have released my <a href="http://www.cantrell.org.uk/david/tech/perl-modules/XML-Tiny-1.0.tar.gz">XML::Tiny</a> module. The parser at its core is less than twenty lines of code. Pretty easy to follow code too, I think, and that also includes error handling. One of my aims in writing it was to keep memory usage and code to the absolute minimum, so it doesn't handle all of XML. The documentation says that it supports "a useful subset of XML". Personally, I think it supports <em>the</em> useful subset. It's certainly enough to parse the data I get back from Amazon when I use their web services, and to parse an RSS feed.</div>
    </content>
    <author>
      <name> david </name>
    </author>
    <id>tag:perlsphere.net,2006: http://www.cantrell.org.uk/david/journal/index.pl/id_xml-tiny</id>
  </entry>
  <entry>
    <title> Palm Treo call db module </title>
    <link rel="alternate" href=" http://www.cantrell.org.uk/david/journal/index.pl/id_palm-treophonecalldb-first-release" type="text/html"/>
    <summary type="text">To make up for a disappointing gap in Palm's software for the Treo smartphone, I wrote a &lt;a href=http://www.cantrell.org.uk/david/tech/treo/call-dumper/&gt;small perl script&lt;/a&gt; to parse the database that stores my call history.  I then re-wrote it as &lt;a href=http://search.cpan.org/search?query=Palm%3A%3ATreoPhoneCallDB&gt;a re-useable module&lt;/a&gt; which also figgers out whether the call was incoming or outgoing.
</summary>
    <content type="text">To make up for a disappointing gap in Palm's software for the Treo smartphone, I wrote a &lt;a href=http://www.cantrell.org.uk/david/tech/treo/call-dumper/&gt;small perl script&lt;/a&gt; to parse the database that stores my call history.  I then re-wrote it as &lt;a href=http://search.cpan.org/search?query=Palm%3A%3ATreoPhoneCallDB&gt;a re-useable module&lt;/a&gt; which also figgers out whether the call was incoming or outgoing.
</content>
    <author>
      <name> david </name>
    </author>
    <id>tag:perlsphere.net,2006: http://www.cantrell.org.uk/david/journal/index.pl/id_palm-treophonecalldb-first-release</id>
  </entry>
  <entry>
    <title> Number::Phone release </title>
    <link rel="alternate" href=" http://www.cantrell.org.uk/david/journal/index.pl/id_number-phone-release" type="text/html"/>
    <summary type="text">There's a new release, &lt;a href=http://www.cantrell.org.uk/david/tech/perl-modules/Number-Phone-1.58.tar.gz&gt;version 1.58&lt;/a&gt;, of Number::Phone, my set of perl modules for picking information out of phone numbers.  Changes from the previous release are that Mayotte, Reunion and Comoros can't decide which country is which, and there's the usual updates to the database of UK numbers, mostly to support the &lt;a href=http://www.ofcom.org.uk/media/news/2007/02/nr_20070213b&gt;new 03 numbers&lt;/a&gt;.
</summary>
    <content type="text">There's a new release, &lt;a href=http://www.cantrell.org.uk/david/tech/perl-modules/Number-Phone-1.58.tar.gz&gt;version 1.58&lt;/a&gt;, of Number::Phone, my set of perl modules for picking information out of phone numbers.  Changes from the previous release are that Mayotte, Reunion and Comoros can't decide which country is which, and there's the usual updates to the database of UK numbers, mostly to support the &lt;a href=http://www.ofcom.org.uk/media/news/2007/02/nr_20070213b&gt;new 03 numbers&lt;/a&gt;.
</content>
    <author>
      <name> david </name>
    </author>
    <id>tag:perlsphere.net,2006: http://www.cantrell.org.uk/david/journal/index.pl/id_number-phone-release</id>
  </entry>
  <entry>
    <title> CPANdeps </title>
    <link rel="alternate" href=" http://www.cantrell.org.uk/david/journal/index.pl/id_cpandeps" type="text/html"/>
    <summary type="html">&lt;a href=http://cpandeps.cantrell.org.uk/&gt;CPANdeps&lt;/a&gt; now lets you filter test results by perl version number, and also knows what modules were in core in which versions of perl.  Hurrah!
</summary>
    <content type="html">&lt;a href=http://cpandeps.cantrell.org.uk/&gt;CPANdeps&lt;/a&gt; now lets you filter test results by perl version number, and also knows what modules were in core in which versions of perl.  Hurrah!
</content>
    <author>
      <name> david </name>
    </author>
    <id>tag:perlsphere.net,2006: http://www.cantrell.org.uk/david/journal/index.pl/id_cpandeps</id>
  </entry>
  <entry>
    <title> YAPC::Europe 2007 report: day 2 </title>
    <link rel="alternate" href=" http://www.cantrell.org.uk/david/journal/index.pl/id_yapc-europe-2007-day-2" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">A day of not many talks, but lots of cool stuff. Damian was his usual
crazy self, and MJD's talk on building parsers was really good. Although
I probably won't use those techniques at work as functional programming
seems to scare people.

The conference dinner at a Heuriger on the outskirts of Vienna was great.
The orga-punks had hired a small fleet of buses to get us there and back,
and one of the sponsors laid on a great buffet. The local wine was pretty
damned fine too, and then the evening de-generated into Schnapps, with
toasts to Her Majesty, to her splendid navy, and to The Village People.

It wasn't all debauchery in the evening though - on the bus, I had a very
useful chat with Philippe about Net::Proxy, and re-designing it to make
it easier to create new connectors for it.</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">A day of not many talks, but lots of cool stuff. Damian was his usual crazy self, and MJD's talk on building parsers was really good. Although I probably won't use those techniques at work as functional programming seems to scare people.
<p>The conference dinner at a <a href="http://wikiproxy.cantrell.org.uk/Heuriger">Heuriger</a> on the outskirts of Vienna was great. The orga-punks had hired a small fleet of buses to get us there and back, and one of the sponsors laid on a great buffet. The local wine was pretty damned fine too, and then the evening de-generated into Schnapps, with toasts to Her Majesty, to her splendid navy, and to The Village People.</p>
<p>It wasn't all debauchery in the evening though - on the bus, I had a very useful chat with <a href="http://www.bruhat.net/">Philippe</a> about <a href="http://search.cpan.org/~book/Net-Proxy-0.08/">Net::Proxy</a>, and re-designing it to make it easier to create new connectors for it.</p></div>
    </content>
    <author>
      <name> david </name>
    </author>
    <id>tag:perlsphere.net,2006: http://www.cantrell.org.uk/david/journal/index.pl/id_yapc-europe-2007-day-2</id>
  </entry>
  <entry>
    <title> YAPC::Europe 2006 report: day 3 </title>
    <link rel="alternate" href=" http://www.cantrell.org.uk/david/journal/index.pl/id_yapc-europe-2006-day-3" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">There were quite a few interesting talks in the morning, especially
Ivor's one on packaging perl applications. Oh, and mine about rsnapshot,
of course, in which people laughed at the right places and I judged the
length of it just right, finishing with a couple of minutes left for
questions.

At the traditional end-of-YAPC auction, I avoided spending my usual
stupid amounts of money on stupid things, which was nice. Obviously the
hundred quid I put in to buying the hair style of next year's organisers
wasn't stupid. Oh no. Definitely not.

An orange mohican will suit Domm beautifully.</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">There were quite a few interesting talks in the morning, especially Ivor's one on packaging perl applications. Oh, and mine about rsnapshot, of course, in which people laughed at the right places and I judged the length of it just right, finishing with a couple of minutes left for questions.
<p>At the traditional end-of-YAPC auction, I avoided spending my usual stupid amounts of money on stupid things, which was nice. Obviously the hundred quid I put in to buying the hair style of next year's organisers wasn't stupid. Oh no. Definitely not.</p>
<p>An orange mohican will suit <a href="http://static.flickr.com/9/11370395_031596292a_m.jpg">Domm</a> beautifully.</p></div>
    </content>
    <author>
      <name> david </name>
    </author>
    <id>tag:perlsphere.net,2006: http://www.cantrell.org.uk/david/journal/index.pl/id_yapc-europe-2006-day-3</id>
  </entry>
  <entry>
    <title> YAPC::Europe 2007 report: day 3 </title>
    <link rel="alternate" href=" http://www.cantrell.org.uk/david/journal/index.pl/id_yapc-europe-2007-day-3" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">My Lightning Talk on cpandeps went down really well, although as José
pointed out, I need to fix it to take account of File::Copy being broken.
I also need to talk to Domm after the conference is over to see if I can
get dependency information from CPANTS as well as from META.yml files.

There were lots of other good lightning talks. Dmitri Karasik's regexes
for doing OCR, Juerd Waalboer's Unicode::Semantics, and Renée Bäcker's
Win32::GuiTest were especially noteworthy.

Richard Foley's brief intro to the perl debugger was also useful.
Unfortunately Hakim Cassimally's talk was about debugging web
applications, which I'd not noticed on the schedule, so I didn't stay for
that.

And finally, Mark Fowler's grumble about why perl sucks (and what to do
about it) had a few interesting little things in it. I am having vaguely
sick ideas about mixing some of that up with an MJD-stylee parser.

At the auction I paid €250 to have the Danish organisers of next year's
YAPC::Europe wear the Swedish flag on their foreheads. This, I should
point out, was Greg's idea. I would never be so evil on my own.</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">My <a href="http://www.justanotherperlhacker.org/lightning/index.shtml">Lightning Talk</a> on <a href="http://cpandeps.cantrell.org.uk/">cpandeps</a> went down really well, although as José pointed out, I need to fix it to take account of <a href="http://cpandeps.cantrell.org.uk/?module=File%3A%3ACopy">File::Copy</a> being <a href="http://abigail1.hates-software.com/2005/09/21/0692681a.html">broken</a>. I also need to talk to Domm after the conference is over to see if I can get dependency information from CPANTS as well as from META.yml files.
<p>There were lots of other good lightning talks. Dmitri Karasik's regexes for doing OCR, Juerd Waalboer's <a href="http://search.cpan.org/~juerd/Unicode-Semantics-1.00/">Unicode::Semantics</a>, and Renée Bäcker's <a href="http://search.cpan.org/~ctrondlp/Win32-GuiTest-1_50.5/">Win32::GuiTest</a> were especially noteworthy.</p>
<p>Richard Foley's brief intro to the perl debugger was also useful. Unfortunately Hakim Cassimally's talk was about debugging <em>web</em> applications, which I'd not noticed on the schedule, so I didn't stay for that.</p>
<p>And finally, Mark Fowler's grumble about why perl sucks (and what to do about it) had a few interesting little things in it. I am having vaguely sick ideas about mixing some of that up with an MJD-stylee parser.</p>
<p>At the auction I paid €250 to have the Danish organisers of next year's YAPC::Europe wear the Swedish flag on their foreheads. This, I should point out, was <a href="http://drinkbroken.typepad.com/">Greg</a>'s idea. I would never be so evil on my own.</p></div>
    </content>
    <author>
      <name> david </name>
    </author>
    <id>tag:perlsphere.net,2006: http://www.cantrell.org.uk/david/journal/index.pl/id_yapc-europe-2007-day-3</id>
  </entry>
  <entry>
    <title> Perl isn't dieing </title>
    <link rel="alternate" href=" http://www.cantrell.org.uk/david/journal/index.pl/id_perl-isnt-dying" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">Perl isn't dieing, but it tells me that it wishes it was. Last night it
went out on the piss with Python and Ruby (PHP was the designated driver)
and it did rather too many cocktails. It isn't quite sure what happened,
but it woke up in the gutter in a puddle of its own fluids and its head
hurts a lot.

It asked me to ask you all to keep the volume down.</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">Perl isn't dieing, but it tells me that it wishes it was. Last night it went out on the piss with Python and Ruby (PHP was the designated driver) and it did rather too many cocktails. It isn't quite sure what happened, but it woke up in the gutter in a puddle of its own fluids and its head hurts a <em>lot</em>.
<p>It asked me to ask you all to keep the volume down.</p></div>
    </content>
    <author>
      <name> david </name>
    </author>
    <id>tag:perlsphere.net,2006: http://www.cantrell.org.uk/david/journal/index.pl/id_perl-isnt-dying</id>
  </entry>
  <entry>
    <title> YAPC::Europe 2007 travel plans </title>
    <link rel="alternate" href=" http://www.cantrell.org.uk/david/journal/index.pl/id_yapc-europe-2007--travel-plans" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">I'm going to Vienna by train for YAPC::Europe. If you want to join me
you'll need to book in advance, and probably quite some way in advance as
some of these trains apparently get fully booked.

arr

dep

date

Waterloo

1740

Fri 24 Aug

Paris Nord

2117

Paris Est

2245

Munich

0859

0928

Sat 25 Aug

Vienna

1335

The first two legs of that are second class, cos first wasn't available
on Eurostar (being a Friday evening it's one of the commuter Eurostars
and gets booked up months and months in advance) and was way too spendy
on the sleeper to Munich. Upgrading to first class from Munich to Vienna
is cheap, so I have.

Coming back it's first class all the way cos upgrading was nearly free
...

arr

dep

date

Vienna

0930

Fri 31 Aug

Zurich

1820

Zurich

1402

Sun 2 Sep

Paris Est

1834

Paris Nord

2013

Waterloo

2159

Don't even think about trying to book online or over the phone, or at the
Eurostar ticket office at Waterloo. Your best bet is to go to the Rail
Europe shop on Picadilly, opposite the Royal Academy and next to
Fortnums.</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">I'm going to Vienna by train for <a href="http://vienna.yapceurope.org/ye2007/index.html">YAPC::Europe</a>. If you want to join me you'll need to book in advance, and probably quite some way in advance as some of these trains apparently get fully booked.
<table border="1">
<tr>
<td/>
<th>arr</th>
<th>dep</th>
<th>date</th>
</tr>
<tr>
<th align="right">Waterloo</th>
<td/>
<td>1740</td>
<td>Fri 24 Aug</td>
</tr>
<tr>
<th align="right">Paris Nord</th>
<td>2117</td>
<td/>
<td/>
</tr>
<tr>
<th align="right">Paris Est</th>
<td/>
<td>2245</td>
<td/>
</tr>
<tr>
<th align="right">Munich</th>
<td>0859</td>
<td>0928</td>
<td>Sat 25 Aug</td>
</tr>
<tr>
<th align="right">Vienna</th>
<td>1335</td>
<td/>
<td/>
</tr>
</table>
<p>The first two legs of that are second class, cos first wasn't available on Eurostar (being a Friday evening it's one of the commuter Eurostars and gets booked up months and months in advance) and was way too spendy on the sleeper to Munich. Upgrading to first class from Munich to Vienna is cheap, so I have.</p>
<p>Coming back it's first class all the way cos upgrading was nearly free ...</p>
<table border="1">
<tr>
<td/>
<th>arr</th>
<th>dep</th>
<th>date</th>
</tr>
<tr>
<th align="right">Vienna</th>
<td/>
<td>0930</td>
<td>Fri 31 Aug</td>
</tr>
<tr>
<th align="right">Zurich</th>
<td>1820</td>
<td/>
<td/>
</tr>
<tr>
<th align="right">Zurich</th>
<td/>
<td>1402</td>
<td>Sun 2 Sep</td>
</tr>
<tr>
<th align="right">Paris Est</th>
<td>1834</td>
<td/>
<td/>
</tr>
<tr>
<th align="right">Paris Nord</th>
<td/>
<td>2013</td>
<td/>
</tr>
<tr>
<th align="right">Waterloo</th>
<td>2159</td>
<td/>
<td/>
</tr>
</table>
<p>Don't even think about trying to book online or over the phone, or at the Eurostar ticket office at Waterloo. Your best bet is to go to the Rail Europe shop on Picadilly, opposite the Royal Academy and next to Fortnums.</p></div>
    </content>
    <author>
      <name> david </name>
    </author>
    <id>tag:perlsphere.net,2006: http://www.cantrell.org.uk/david/journal/index.pl/id_yapc-europe-2007--travel-plans</id>
  </entry>
  <entry>
    <title> Wikipedia handheld proxy </title>
    <link rel="alternate" href=" http://www.cantrell.org.uk/david/journal/index.pl/id_wikipedia-proxy" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">I got irritated at how hard it was to use Wikipedia on my Treo. There's
so much rubbish splattered around their pages that it Just Doesn't Work
on such a small screen. Given that no alternatives seemed to be available
- at least, Google couldn't find any - I decided to write my own
Wikipedia handheld proxy.

It strips away all the useless rubbish that normally surrounds Wikipedia
pages, as well as things like the editing functions which are also hard
to use on portable devices. Internally, it's implemented using perl, LWP,
and mod_perl, and is hosted by Keyweb.de.</div>
    </summary>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">I got irritated at how hard it was to use <a href="http://en.wikipedia.org/">Wikipedia</a> on my Treo. There's so much rubbish splattered around their pages that it Just Doesn't Work on such a small screen. Given that no alternatives seemed to be available - at least, Google couldn't find any - I decided to write my own <a href="http://wikiproxy.cantrell.org.uk/">Wikipedia handheld proxy</a>.
<p>It strips away all the useless rubbish that normally surrounds Wikipedia pages, as well as things like the editing functions which are also hard to use on portable devices. Internally, it's implemented using <a href="http://www.perl.org/">perl</a>, <a href="http://search.cpan.org/~gaas/libwww-perl-5.806/">LWP</a>, and <a href="http://search.cpan.org/~pgollucci/mod_perl-2.0.3/">mod_perl</a>, and is hosted by <a href="http://www.keyweb.de/vrsrds/index.shtml">Keyweb.de</a>.</p></div>
    </content>
    <author>
      <name> david </name>
    </author>
    <id>tag:perlsphere.net,2006: http://www.cantrell.org.uk/david/journal/index.pl/id_wikipedia-proxy</id>
  </entry>
  <entry>
    <title>Meta: Script to Filter the Master use.perl.org Blogs' Feed</title>
    <link rel="alternate" href="http://use.perl.org/~Shlomi+Fish/journal/38969?from=rss" type="text/html"/>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">As expected from the latest trend in the Perl blogosphere this post will
be about Roles. And Moose! And Roles in Moose! And Moose in Roles! And
Roles outside Moose…

Seriously now, this is a post about a completely non-Moosey and non-Roley
script I wrote to filter the use.perl.org master journals' feed. What
this script does is fetch the Atom feed of all the use.perl.org journals'
posts, and filters out the entries of the use.perl.org authors that the
invoker specified.

Here is out to use it. First of all: svn checkout it (or otherwise fetch
it using HTTP). Then you can simply use:

  perl filter-use-perl-journals.pl -o everything.atom

Then you can serve everything.atom with a web-server to read it using
your web feeds' aggregator.

To simply create a non-filtered copy of the feed. Now let's say you want
to get rid of posts from my journal (because it sucks). In that case,
say:

  perl filter-use-perl-journals.pl -o non-shlomif.atom \
  --blacklist="Shlomi Fish"

Now, let's say you also want to get rid of Ovid's posts. I have no idea
why you'd want to do that, because his journal is great, but it's just
for the sake of the example. In that case, do:

  perl filter-use-perl-journals.pl -o non-shlomif-and-ovid.atom \
  --blacklist="Shlomi Fish" --blacklist="Ovid"

Finally, there's the --rand flag which is useful in case you're running
the script with cron. What it does is wait for a period of time of random
length, before fetching the feed, so the HTTP server would not be
overloaded at regular periods. This requires a working /dev/urandom for
the time being.

The script is made available under the MIT/X11 Licence so its use is
completely unencumbered. I wrote this script today, because I have a
personal use for it, but other people may find it useful too. It requires
a recent version of Perl (5.8.x should be enough I think) and XML-Feed.</div>
    </summary>
    <content type="html">&lt;p&gt;As expected from the latest trend in the Perl blogosphere this post will be about Roles. And Moose! And Roles in Moose! And Moose in Roles! And Roles outside Moose…&lt;/p&gt;
&lt;p&gt;Seriously now, this is a post about &lt;a href="http://svn.berlios.de/svnroot/repos/web-cpan/XML-Feed/trunk/filter-use.perl.org/"&gt;a completely non-Moosey and non-Roley script I wrote to filter the use.perl.org master journals' feed&lt;/a&gt;. What this script does is fetch the Atom feed of all the use.perl.org journals' posts, and filters out the entries of the use.perl.org authors that the invoker specified.&lt;/p&gt;
&lt;p&gt;Here is out to use it. First of all: &lt;tt&gt;svn checkout&lt;/tt&gt; it (or otherwise fetch it using HTTP). Then you can simply use:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;
&lt;p&gt;&lt;tt&gt;perl filter-use-perl-journals.pl -o everything.atom&lt;/tt&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;p&gt;Then you can serve &lt;tt&gt;everything.atom&lt;/tt&gt; with a web-server to read it using your web feeds' aggregator.&lt;/p&gt;
&lt;p&gt;To simply create a non-filtered copy of the feed. Now let's say you want to get rid of posts from my journal (because it sucks). In that case, say:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;
&lt;p&gt;&lt;tt&gt;perl filter-use-perl-journals.pl -o non-shlomif.atom \&lt;br /&gt;
&amp;nbsp; &amp;nbsp; --blacklist="Shlomi Fish"&lt;/tt&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now, let's say you also want to get rid of &lt;a href="http://use.perl.org/~Ovid/journal/"&gt;Ovid's&lt;/a&gt; posts. I have no idea why you'd want to do that, because his journal is great, but it's just for the sake of the example. In that case, do:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;
&lt;p&gt;&lt;tt&gt;perl filter-use-perl-journals.pl -o non-shlomif-and-ovid.atom \&lt;br /&gt;
&amp;nbsp; &amp;nbsp; --blacklist="Shlomi Fish" --blacklist="Ovid"&lt;/tt&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;p&gt;Finally, there's the &lt;tt&gt;--rand&lt;/tt&gt; flag which is useful in case you're running the script with cron. What it does is wait for a period of time of random length, before fetching the feed, so the HTTP server would not be overloaded at regular periods. This requires a working &lt;nobr&gt;&lt;wbr /&gt;&lt;/nobr&gt;&lt;tt&gt;/dev/urandom&lt;/tt&gt; for the time being.&lt;/p&gt;
&lt;p&gt;The script is made available under &lt;a href="http://en.wikipedia.org/wiki/MIT_License"&gt;the MIT/X11 Licence&lt;/a&gt; so its use is completely unencumbered. I wrote this script today, because I have a personal use for it, but other people may find it useful too. It requires a recent version of Perl (5.8.x should be enough I think) and &lt;a href="http://search.cpan.org/dist/XML-Feed/"&gt;XML-Feed&lt;/a&gt;.&lt;/p&gt;</content>
    <author>
      <name>shlomif@iglu.org.il (Shlomi Fish)</name>
    </author>
    <id>tag:perlsphere.net,2006:http://use.perl.org/~Shlomi+Fish/journal/38969?from=rss</id>
  </entry>
</feed>
