ferreira's Journal
http://use.perl.org/~ferreira/journal/
ferreira's use Perl Journalen-ususe Perl; is Copyright 1998-2006, Chris Nandor. Stories, comments, journals, and other submissions posted on use Perl; are Copyright their respective owners.2012-01-25T02:13:34+00:00pudgepudge@perl.orgTechnologyhourly11970-01-01T00:00+00:00ferreira's Journalhttp://use.perl.org/images/topics/useperl.gif
http://use.perl.org/~ferreira/journal/
YAPC Brasil 2008 hatching
http://use.perl.org/~ferreira/journal/37466?from=rss
<p>
We just started preparing a YAPC Brasil 2008. It will happen together with CONISLI 2008, at São Paulo (<a href="http://www.conisli.org/">http://www.conisli.org/</a>), October 18-19. Yes, that's very little time until the event, but we'll make the best we can with our distributed efforts. Brazilians are known for being good at improvising. (But we'll work hard to make that work in this limited piece of time.)
</p><p>
We know we will have a stand and a room where the talks will happen. Everything else is in flux yet. We are going to try to put down a preliminary scheduling very soon, and we would appreciate contributors as speakers and people with good ideas and suggestions.
</p><p>
At first sight, it is quite possible that we can gather together many Perl developers that never meet one another in person. That's mainly the people who keep busy the mailing lists Cascavel-pm, Rio-pm, and SaoPaulo-pm.
</p><p>
We are assembling a preliminary list of talks here:
<a href="http://www.perl.org.br/Main/Yapc2008Preliminares">http://www.perl.org.br/Main/Yapc2008Preliminares</a>.
</p><p>
I will try to post more information on the event as it is available.
</p>ferreira2008-09-16T22:36:46+00:00journalBye bye, old modules
http://use.perl.org/~ferreira/journal/36557?from=rss
<p>
I just scheduled for deletion (via <a href="http://pause.perl.org/">PAUSE</a>) the last CPAN files related to <a href="http://search.cpan.org/dist/Carp-Indeed/">Carp-Indeed</a> and <a href="http://search.cpan.org/dist/Class-Constructor-Factory/">Class-Constructor-Factory</a> distributions. Both were renamed: <a href="http://search.cpan.org/perldoc?Carp::Indeed">Carp::Indeed</a> became <a href="http://search.cpan.org/perldoc?Carp::Always">Carp::Always</a> and was deprecate since a long time ago. <a href="http://search.cpan.org/perldoc?Class::Constructor::Factory">Class::Constructor::Factory</a> was meant to be renamed since its inception and became <a href="http://search.cpan.org/perldoc?Class::Lego::Constructor">Class::Lego::Constructor</a>. I doubt anyone will miss them.
</p><p>
These files will no longer be found in CPAN, but only at BACKPAN. It got me thinking at how often that sort of cleanup happens. There were some occasions when I only found modules mentioned in the documentation of other code at BACKPAN. In general, these deletions look sensible (incomplete code that were never finished, superseded code, etc.). But many times it is hard to find the reasons they were removed and what was left in its place (if any). So it looks like BACKPAN really become an archeological research field, with all the difficulties to reconstruct the past when someone wants to.
</p>ferreira2008-05-31T22:20:31+00:00journalIs your file tidy? Really?
http://use.perl.org/~ferreira/journal/36295?from=rss
<p>
With respect to <a href="http://search.cpan.org/perldoc?Perl::Tidy">Perl::Tidy</a>, it is quite obvious that a tidy file is one that has gone through perltidy and which does not change if reformatted again.
</p><blockquote><div><p> <tt>$ perltidy tidy_file.pl<br>$ diff tidy_file.pl tidy_file.pl.tdy<br># zero, no difference</tt></p></div> </blockquote><p>
But <code>Perl::Tidy</code> is a work in progress which is constantly improving. And improving means changing. Those changes may include the fixes of some behaviors considered non-ideal or even flawed. So tidy files under a <code>Perl::Tidy</code> version may not be tidy under another version. So this concept is a little fragile (or needs a more precise wording).
</p><p>
Even <a href="http://search.cpan.org/perldoc?Test::PerlTidy">Test::PerlTidy</a> (which intends to capture that tidy-ness concept in the form of an automated test) was caught by this detail, since a new release of <code>Perl::Tidy</code> got out. Edmund von der Burg and me are working on a reasonable approach to this issue. Wait for a new release of <code>Test-PerlTidy</code> soon.
</p>ferreira2008-05-01T02:50:08+00:00journalClashes between functional and OO worlds
http://use.perl.org/~ferreira/journal/36294?from=rss
<p>
In refactoring some code, I opted for turning "warn/carp" calls into method calls "$self->carp". This way the objects could act by themselves (using CORE::warn/Carp::carp) or cooperate with others (via a closure).
</p><blockquote><div><p> <tt>sub carp {<br> my $self = shift;<br> my $on_warn = $self->on_warn;<br> if ( $on_warn ) {<br> $on_warn->(@_);<br> } else {<br> Carp::carp(@_);<br> }<br>}</tt></p></div> </blockquote><p>
It turned out that naming the method the same as a function was a bad idea (at least in the transition to the fully refactored code). The simple application used some simple hierarchies, and when I "fixed" the superclasses as in:
</p><blockquote><div><p> <tt>package Parent;<br> <br>sub carp {<br> <nobr> <wbr></nobr>...<br>}</tt></p></div> </blockquote><p>
I found after some perplexity that in the children, code like that:
</p><blockquote><div><p> <tt>package Child;<br> <br>use base qw( Parent );<br> <br>use Carp qw( carp );<br> <br>...<br> $self->carp("message");<br>...</tt></p></div> </blockquote><p>
emitted strange messages like:
</p><blockquote><div><p> <tt>Parent=HASH()message</tt></p></div> </blockquote><p>
because <code>$self->carp("message")</code> resolved to <code>Carp::carp( $self, "message" )</code> as <code>Carp::carp</code> had been exported to <code>Child</code> overriding the method I was expecting to inherit.
</p><p>
That's what we earn because methods are just subs.
</p>ferreira2008-05-01T02:37:56+00:00journalBeing clever by half may hurt
http://use.perl.org/~ferreira/journal/36244?from=rss
<p>
I know Perl may be quite irregular sometimes, and because it is irregular gotchas are easily glossed over and bite.
</p><p>
After some code refactoring, I ended up with a code like that:
</p><blockquote><div><p> <tt>for (@$x) {<br> push @array, $_;<br>}</tt></p></div> </blockquote><p>
which immediately suggested me an equivalent expression:
</p><blockquote><div><p> <tt>push @array, @$x;</tt></p></div> </blockquote><p>
Unfortunately, this is not quite equivalent when <code>$x</code> is <code>undef</code>. Under <code>strict</code>, <code>@$x</code> bails with <i>"Can't use an undefined value as an ARRAY reference "</i> while <code>for (@$x) {}</code> works flawlessly as a loop that is never entered. So the real equivalence I was looking for is:
</p><blockquote><div><p> <tt>if ( $x ) {<br> push @array, @$x;<br>}</tt></p></div> </blockquote><p>
whick is ok (as long as <code>$x</code> contains array refs or undefs).
</p>ferreira2008-04-25T12:10:40+00:00journal"perldoc -A @+" is out there
http://use.perl.org/~ferreira/journal/36229?from=rss
<p>
<a href="/~ovid">Ovid</a> proposed a patch to let <a href="http://search.cpan.org/perldoc?perldoc">perldoc</a> search for Perl predefined variables from <a href="http://search.cpan.org/perldoc?perlvar">perlvar</a> and mentioned it at use.perl <a href="http://use.perl.org/~Ovid/journal/35771">here</a> and <a href="http://use.perl.org/~Ovid/journal/35778">here</a>.
</p><p>
The development release <a href="http://search.cpan.org/~ferreira/Pod-Perldoc-3.14_05/">Pod-Perldoc 3.14_05</a> brings this goodness to your delight.
</p>ferreira2008-04-23T13:06:31+00:00journalNancy: from Lua to Perl
http://use.perl.org/~ferreira/journal/35871?from=rss
<p>
Some days before, Reuben Thomas (a known contributor to <a href="http://www.lua.org/">Lua</a> community) <a href="http://article.gmane.org/gmane.comp.lang.lua.general/46135">announced</a> the release of <a href="http://rrt.sc3d.org/Software/Nancy/">Nancy</a>, "a simple web site builder" at the <a href="http://www.lua.org/lua-l.html">Lua mailing list</a>.
</p><p>
For the dismay of Lua afficcionados, this release was not written in Lua.
</p><blockquote><div><p> <em>
Oh, and it's written in Perl. I thought it might be interesting to say why.
The problem was not libraries (I used my pure-Lua stdlib and LuaFileSystem),
but deployment on Windows (I use Linux). I had previously built an
all-in-one binary for Windows using a cross-compiler. That worked fine but
made it hard to debug on Windows as I couldn't just edit-run, and also broke
nastily when the cross-compiler was upgraded. So, I switched to LuaBinaries.
That enabled me in the end to deploy only pre-built binaries, but at the
cost of having to install 2 binary packages, and then do manual fiddling to
get<nobr> <wbr></nobr>.lua files run as commands by the Windows shell.
</em> </p><p> <em>
ActivePerl does all this for me, and I was already using some Perl scripts
in the same system, so by rewriting Nancy in Perl I got down to "run the
Perl installer" as being the prerequisites for running Nancy.
</em> </p></div>
</blockquote><p>
Nancy begun its life as Lua code (and that's the reason Reuben announced this at Lua mailing list for the last time unless it be written in Lua again in the future).
</p><p>
Perl still has an edge ahead before some of the popular dynamical languages out there, which (I hope) is not going away anytime soon in the future.
</p>ferreira2008-03-09T20:13:29+00:00journalAbusing "Memoize"
http://use.perl.org/~ferreira/journal/35842?from=rss
<p>
A few days ago, I was writing a code (namely the <a href="http://search.cpan.org/dist/Path-Classy">Path-Classy</a> dist) and stared at the code that produced the file size in raw bytes or "humanized" (28300 or 28K).
</p><blockquote><div><p> <tt>sub _format_size {<br> my ($sz, $opt) = @_;<br> <br> my $format = $opt->{format};<br> if ( $format eq 'h' ) {<br> require Numbers::Bytes::Human;<br> return Number::Bytes::Human->new->format( $sz );<br> }<br> else { # raw bytes<br> return $sz;<br> }<br>}</tt></p></div> </blockquote><p>
Of course, loading <code>Number::Bytes::Human</code> and creating a instance every time <code>$f->size({ format => 'h' })</code> was invoked seemed overkill. But saving the <code>N::B::H</code> into a class/instance variable seemed overkill too: it has nothing to do with <code>Path::Classy</code> (which are <code> <a href="http://search.cpan.org/perldoc?Path::Class">Path::Class</a> </code>) objects but for that instant relationship to format a file property, size.
</p><p>
Hey, that's a chance to use <a href="http://search.cpan.org/perldoc?Memoize">memoization</a>, splitting the formatter creation into a function and then memoizing it (so that we don't need to create a [reusable] object with the same capabilities over and over), we come to this code.
</p><blockquote><div><p> <tt>use Memoize;<br> <br>sub _size_formatter {<br> require Number::Bytes::Human;<br> return Number::Bytes::Human->new;<br>}<br>memoize('_size_formatter');<br> <br>sub _format_size {<br> my ($sz, $opt) = @_;<br> <br> my $format = $opt->{format};<br> if ( $format eq 'h' ) {<br> return _size_formatter->format( $sz );<br> <nobr> <wbr></nobr>...</tt></p></div> </blockquote><p>
That looked elegant to me. To make it even more tight (and to require yet another CPAN module<nobr> <wbr></nobr>;-) ), using <code> <a href="http://search.cpan.org/perldoc?Attribute::Memoize">Attribute::Memoize</a> </code> seemed right. It avoids the need to repeat the function name in the <code>memoize</code> call and it anticipated the wrapping up of the sub to BEGIN time (a free bonus of <code> <a href="http://search.cpan.org/perldoc?Attribute::Handlers">Attribute::Handlers</a> </code> in the backstage).
</p><blockquote><div><p> <tt>use Attribute::Memoize;<br> <br>sub _size_formatter<nobr> <wbr></nobr>:Memoize {<br> require Number::Bytes::Human;<br> return Number::Bytes::Human->new;<br>}</tt></p></div> </blockquote><p>
That's it! Efficient code, localized behavior, no need for extra variables. Will people understand that for maintenance? I hope so.
</p>ferreira2008-03-05T20:13:03+00:00journalWanna break some dists?
http://use.perl.org/~ferreira/journal/35653?from=rss
<p>
An easy recipe to do this is to include a dependency on a module version which only development releases reached that far.
</p><p>
That will provoke installations by the CPAN shell to fail complaining about a bad dependency. These actually will generate NA test reports because of dependencies which could not be satisfied.
</p><p>
I saw such an example the other day. The dist <a href="http://search.cpan.org/dist/KSx-Analysis-StripAccents/"> <code>KSx-Analysis-StripAccents </code> </a> declared a dependency on 0.2 version of <a href="http://search.cpan.org/dist/KinoSearch"> <code>KinoSearch</code> </a>. The latest stable release of KinoSearch is 0.162 and the current devel release is 0.20_05. That filled CPAN Testers with NA reports on SPROUT's module.
</p><p>
Note that this is not a major fault from author's part. It is just how the toolchain works nowadays. There is no automated way to have a dependency on development versions, which seems a good thing, but which cannot be circumvented (unless it is done manually).
</p><p>
Maybe, that has some resemblances with declaring dependencies on third-party modules which are not in CPAN (like <code>SVN::Core</code> and modules in the list kept by <a href="http://search.cpan.org/perldoc?Module::ThirdParty">Module::ThirdyParty</a>,
and company-specific code).</p>ferreira2008-02-14T16:07:10+00:00journalWhat's better? -Ilib or -Mblib?
http://use.perl.org/~ferreira/journal/35649?from=rss
<p>
When testing/playing with a distribution, one usually runs:
</p><blockquote><div><p> <tt>$ perl Makefile.PL; make<br>$ perl -Mblib demo.pl<br># or (with tests)<br>$ prove -b test.t</tt></p></div> </blockquote><p>
Sometime the <code>make</code> (or<nobr> <wbr></nobr><code>./Build</code>) gets annoying and a shortcut is nice:
</p><blockquote><div><p> <tt>$ perl -Ilib demo.pl<br># or<br>$ prove -l test.t</tt></p></div> </blockquote><p>
However, there are a bunch of reasons not do that. Among them:
</p><ul>
<li> <code>-Ilib</code> won't work for modules with XS parts (it will use installed XS components or fail to load)
</li><li>the current build settings may establish an environment different from the current <code>lib/</code> layout (with modules not in the MANIFEST and things like that)
</li></ul><p>
At the end, we conclude that working under <code>-Mblib</code> is safer (and closer to release conditions) than playing with <code>-Ilib</code>.
</p>ferreira2008-02-13T17:13:46+00:00journalAnother context feature
http://use.perl.org/~ferreira/journal/35623?from=rss
<blockquote><div><p> <em>
My original title was "Another context trap", but I changed my mind. Read on.
</em></p></div> </blockquote><p>
Easy things are supposed to be easy to write in Perl, right? Let's try this one: write an (efficient) identity subroutine one that returns the arguments given to it.
</p><p>
Ok. Now you write down your solution and come back to read the rest of it.
</p><p>
That was my first attempt:
</p><blockquote><div><p> <tt>my $id = sub { return @_; }</tt></p></div> </blockquote><p>
And it looked like a good idea at first, as the <code>@_</code> gets all the sub arguments (whether they be zero, one or many). And it seemingly worked.</p><blockquote><div><p> <tt>$id->() returns ()<br>$id->(42) returns (42)<br>$id->(42,42) returns (42,42)</tt></p></div> </blockquote><p>
Except that I was not totally honest, and these succeed only when the function is called at list context. If that's not the case, we have:
</p><blockquote><div><p> <tt>$c = $id->(42); # 1 gets assigned to $c (from scalar @_)<br>($a) = $id->(42); # good, 42 gets assigned to $c</tt></p></div> </blockquote><p>
The quick solution is to take into account the calling context and write down the code as:
</p><blockquote><div><p> <tt>$id = sub {<br> wantarray : @_ ? $_[0]<br>}</tt></p></div> </blockquote><p>
The fault of this is a Perl feature that most other programming languages don't have: sensitivity to calling context. Those others are happily relieved of this because they are poorer in semantics than Perl in that aspect.
</p><p>
The identity function needs to be defined from a domain into the same domain: <code>A -> A</code>. Then, if we consider the non-void contexts Perl 5 provides: list and scalar, we have not one but two identity functions to consider. Namely,
</p><blockquote><div><p> <tt>sub { @_ } # for list context, LIST -> LIST<br>sub ($) { $_[0] } # for scalar context, SCALAR -> SCALAR</tt></p></div> </blockquote><p>
<em>Note.</em> The sneaky prototype in the last sub definition entered the scene to guarantee the homomorphism between the domain and image, that was not tested in the previous definition. So to be 100% correct, that should do it:
</p><blockquote><div><p> <tt>sub {<br> if ( wantarray ) {<br> @_;<br> } else {<br> die "too many arguments" unless @_==1;<br> $_[0];<br> }<br>}</tt></p></div> </blockquote><p>
The trap in this case is more like a fault of all other programming languages that don't have call context sensitivity. Because if they did, like Perl, they would push you up to think harder about some concepts like identity itself.
</p><p>
What Perl 6 will have to do with this? You bet no one is going to draw back and "relieve" Perl 6 of that extra expressiveness her mother language has. On contrary, Perl 6 will have even more call context sensitivity. But IIRC you will be able to define nice multisubs which dispatch on return type and will avoid unintented uses.
</p><p>
Hm, how they would look like? I am not sure. Maybe
</p><blockquote><div><p> <tt>multi sub id(Any $x -> Any: ) { $x }</tt></p></div> </blockquote>ferreira2008-02-09T17:14:00+00:00journalA Subtlety of 'reverse'
http://use.perl.org/~ferreira/journal/35607?from=rss
<p>
A few days ago I was bitten by the dual nature of <code>reverse</code>.
</p><blockquote><div><p> <tt>$s = reverse 'xyz'; # 'zyx'<br>@a = reverse qw(a b c); # qw(c b a)</tt></p></div> </blockquote><blockquote><div><p> <em>
This is even worse because <code>reverse</code> in scalar
context may receive a LIST as argument and
concatenates the reverse string of each element.
</em> </p><blockquote><div><p> <tt>$s = reverse qw(abc mni xyz); # 'zyxinmcba'</tt></p></div> </blockquote></div> </blockquote><p>
There was a code where a method <code>history</code> was meant to return
an array and got used in a few places this way:
</p><blockquote><div><p> <tt>$history_size = $o->history();</tt></p></div> </blockquote><p>
which worked ok, until I found a subclass implementation
which had been coded like this:
</p><blockquote><div><p> <tt>sub history {<br> shift;<br> return ( reverse @history );<br>}</tt></p></div> </blockquote><p>
and the assumption that it should return
the (history) array size when called in
scalar context failed miserably.
The solution was to document what it was
supposed to return in list and scalar contexts
and to change the implementation to:
</p><blockquote><div><p> <tt>sub history {<br> shift;<br> return my @h = reverse @history;<br>}</tt></p></div> </blockquote><p>
That's the kind of thing I remember when someone
says: "What's so wrong with Perl 5 that we
might need Perl 6?"
</p><p>
That's the kind of subtlety that caught you
by surprise occasionally, beginner or not.
Idiosyncracies like that put a burden at
the programmer which has not a perfect memory
(and I am one of such programmers unfortunately,
I have to admit)
and makes some feel that a Perl guru is needed
to detect, solve and explain such bits.
This kind of weird behavior leads sometimes
to workarounds because there is no time
to think about what's wrong with that f...
piece of code. And then it distorts into ugly
things that contributes to the bad fame of
our favourite language.
</p><p>
Such ugly things go like a current joke
on Portuguese ortography.
A friend tells the other: "Write me a
check of 'sessenta' Brazilian Reais"
-- "How dow I spell 'sessenta'?" --
"Well, make two checks of thirty."
(Background: the word
"sessenta" (sixty) may raise doubts
to careless people about the right spelling:
"sesenta", "seçenta", "sessenta".)
</p><p>
If Perl 6 fails to get rid of such subtleties
(and this is one of its design principles),
it will have failed to be the improvement
of the Perl language it was supposed to
be.
</p>ferreira2008-02-07T18:08:47+00:00journalSMTP/SASL authentication for CPAN::Reporter
http://use.perl.org/~ferreira/journal/35488?from=rss
<p>
I wrote a monkeypatch (dirty, I have to confess) so that I could use CPAN::Reporter with my ISP mail server which requires authentication.
</p><p>
I had to do it by touching Test::Reporter as well. They will be available in CPAN at:
</p><ul>
<li> <a href="http://search.cpan.org/CPAN/authors/id/F/FE/FERREIRA/Test-Reporter-1.38-FERREIRA-01.patch.gz">http://search.cpan.org/CPAN/authors/id/F/FE/FERREIRA/Test-Reporter-1.38-FERREIR<nobr>A<wbr></nobr> -01.patch.gz</a> </li><li> <a href="http://search.cpan.org/CPAN/authors/id/F/FE/FERREIRA/CPAN-Reporter-1.07_05-FERREIRA-01.patch.gz">http://search.cpan.org/CPAN/authors/id/F/FE/FERREIRA/CPAN-Reporter-1.07_05-FERR<nobr>E<wbr></nobr> IRA-01.patch.gz</a> </li></ul><p>
In Test::Reporter, a new accessor <code>net_smtp_args</code> was created which should be filled with a hash ref. If it contains something like:</p><blockquote><div><p> <tt>{ auth => { user => 'me', pass => '***' } }</tt></p></div> </blockquote><p>
and Net::SMTP is the current transport, it will attempt to do SASL authentication after opening the connection.
</p><p>
In CPAN::Reporter, the changes allow the code to read from the config file <code>~/.cpanreporter/config.ini</code> two config values which get passed into Test::Reporter:</p><blockquote><div><p> <tt># to do SMTP/SASL authentication, add these to ~/.cpanreporter/config.ini<br>smtp_auth_user=me<br>smtp_auth_pass=***</tt></p></div> </blockquote><p>
This is not a permanent solution because <code>CPANT::Testers::Transport::*</code> is in the works to replace <code>Test::Reporter</code> which will allow more natural/elegant approaches to that.
</p>ferreira2008-01-25T18:41:07+00:00journalWWW::CPAN->query()
http://use.perl.org/~ferreira/journal/35388?from=rss
<p> <a href="http://search.cpan.org/perldoc?WWW::CPAN">WWW::CPAN</a> is a work in progress (slow progress, to be honest). At 0.004 release, its API got one more method, <tt>query()</tt>. The whole API is:
</p><ul>
<li> <tt>new</tt> - good old constructor</li><li> <tt>fetch_distmeta</tt> - grab META.yml (META.json) from CPAN distributions</li><li> <tt>query</tt> - do simple queries and get the result as Perl data</li>
</ul><p>
Ain't that promising? Everyone will use it when 0.999 release arrives. (Yes, updates are by +0.001 increments.)
</p>ferreira2008-01-14T22:51:06+00:00journalPerl 6 micro-articles just now
http://use.perl.org/~ferreira/journal/35233?from=rss
<p>
This week has seen a turmoil of emotions surrounding Perl 6. (Just take a look at the last articles here at use.perl and perlbuzz.) This entry is just to gladly announce that in this very moment (Dec 28 2007 18:30 GMT-0200) three microarticles of the series on Perl 6 operators are in The Hot 25 list of <a href="http://www.oreillynet.com/blogs/">O'Reilly Network Blogs</a>.
</p><p>
It may be due to other causes:
</p><ul>
<li>I faithfully provided one article from Monday to Friday for the last two weeks;</li><li>This is end-of-year time and reading habits may be different;</li>
<li>I am not quite sure of the criteria that make blog entries appear there in The Hot 25 and maybe it's just noise that took these articles to those positions (#5, #13, #23).
</li></ul><p>
But on the other hand, given that I am not that endowed for writing, I rather believe that
</p><ul>
<li>Perl 6 still captures curiosity and attention of people out there;
</li><li>
People do not want to lose the opportunity (to learn, use, criticize, think about, etc.) when Perl 6 is finally released.
</li></ul><p>
So I want to thank everyone that contributed to the current state of Perl 6-related development and to wish much fun in the future work that will bring us this long-awaited Christmas gift.
</p>ferreira2007-12-28T20:53:12+00:00journalThe need for SUPER
http://use.perl.org/~ferreira/journal/35228?from=rss
<blockquote><div><p> <em>
Also known as "The trap of SUPER::method"
</em></p></div> </blockquote><p>
I never have grokked <a href="http://search.cpan.org/perldoc?SUPER">SUPER</a> and what exactly it could do for me. Until I wrote <a href="http://search.cpan.org/perldoc?Class::Constructor::Factory">Class::Constructor::Factory</a>.
</p><p>
<code>Class::Constructor::Factory</code> is a helper module to prevent me to spend time writing constructors after using a module like <code>Class::Accessor</code> (and siblings) that gave me for free handy accessors/mutators for object fields. Those modules also gave me a constructor for free. But I am never happy with constructors without a way to specify defaults when initial field values are not given.</p><p>
So <code>C::C::F</code> is a step towards a more automated way to get better constructors for free and, in a near future, to write classes with less effort. Actually, using the 0.001 version of the module looks like this:
</p><blockquote><div><p> <tt>package Foo;<br> <br>use Class::Constructor::Factory;<br>use base qw( Class::Accessor Class::Constructor::Factory );<br> <br>__PACKAGE__->mk_constructor0({<br> foo => 42,<br> bar => 'fourty-two',<br>});<br>__PACKAGE__->mk_accessors(qw( foo bar ));</tt></p></div> </blockquote><p>
The thing is that <code>C::C::F</code> augments the actual constructor provided by the IS-A chain of the new package with handling of defaults. So a closure is built and then installed into <code>&Foo::new</code> to work out the wanted magic.
</p><blockquote><div><p> <tt>my $foo = Foo->new();<br>is( $foo->foo, 42 );<br>is( $foo->bar, 'fourty-two' );</tt></p></div> </blockquote><p>
That is rather straightforward and involved code which looked like this:
</p><blockquote><div><p> <tt>package Class::Constructor::Factory;<br> <br>...<br> <br>sub make_constructor0 {<br> my $self = shift;<br> <nobr> <wbr></nobr>...<br> <br> # return a closure<br> return sub {<br> my $self = shift;<br> <nobr> <wbr></nobr>...<br> return $self->SUPER::new->( $self, \%f ); # XXX the offender<br> };<br>}</tt></p></div> </blockquote><p>
I must say that this code is deceptively simple and wrong. Because <code>->SUPER::new</code> tried to invoke the <code>&new</code> of <code>Class::Constructor::Factory</code> superclasses (which does not exist). I understood why by reading the docs of <code>SUPER</code> and <a href="http://perldoc.perl.org/perlobj.html">perlobj</a>. The relevant quote is:</p><blockquote><div><p> <em>
"It is important to note that SUPER refers to the superclass(es) of the current package and not to the superclass(es) of the object."
</em></p></div> </blockquote><p>
So even after the closure was installed into the <code>Foo</code> namespace, <code>->SUPER::new</code> yet referred to the superclass of the package where the code was compiled, not doing what I wanted.
</p><p>
The solution is to use <code>SUPER</code> and then rewrite the offender code line as:
</p><blockquote><div><p> <tt> return $self->super('new')->( $self, \%f );</tt></p></div> </blockquote><p>
After this, the <code>&new</code> is searched correctly among the superclasses of the object and everything is just fine.
</p><p>
This entry is just to remind me that <code>->SUPER::method</code> and dynamic code generation (or equivalently dealing with closures in namespaces other than where they were compiled) is at least misleading. I don't claim to have understood all the issues <code>SUPER</code> may address, but I learned something. <em>Thanks, chromatic!</em> And maybe this trap may be turned off in the future by toogling a feature in a future Perl 5 version.
</p>ferreira2007-12-28T17:01:31+00:00journalMore Perl 6 micro-articles
http://use.perl.org/~ferreira/journal/35188?from=rss
For the next week, I have some drafts of micro-articles on Perl operators:
<ul>
<li> <a href="http://feather.perl6.nl/~ferreira/perl6-operators/iterate.html">Iterate operator</a> </li><li> <a href="http://feather.perl6.nl/~ferreira/perl6-operators/reduce1.html">Reduce operators</a> </li><li> <a href="http://feather.perl6.nl/~ferreira/perl6-operators/mutate.html">Mutating operators</a> </li><li> <a href="http://feather.perl6.nl/~ferreira/perl6-operators/fatarrow.html">The Pair constructor</a> </li></ul><p>
I would really appreciate feedback on these texts. Corrections, suggestions, etc.</p>ferreira2007-12-22T19:37:03+00:00journalFive Perl 6 micro-articles
http://use.perl.org/~ferreira/journal/35124?from=rss
<p>
So far I published more two articles at OnLAMP:
</p><ul> <li>
<a href="http://www.oreillynet.com/onlamp/blog/2007/12/yet_another_perl_6_operator_bo_1.html">Boolean operators</a>
</li><li>
<a href="http://www.oreillynet.com/onlamp/blog/2007/12/yap6_operator_the_default_oper.html">The<nobr> <wbr></nobr><tt>//</tt> operator</a>
</li></ul><p>
and got to complete three drafts for the next ones:
</p><ul> <li>
<a href="http://feather.perl6.nl/~ferreira/perl6-operators/negate.html">Negated operators</a>
</li><li>
<a href="http://feather.perl6.nl/~ferreira/perl6-operators/ternary.html">The conditional operator</a>
</li><li>
<a href="http://feather.perl6.nl/~ferreira/perl6-operators/ranges.html">Range operators</a>
</li></ul><p>
I would appreciate that interested people read them and point mistakes and improvements to be done.
</p><p> <small>
P.S. Yeah, sadly I know that some links at OnLAMP are wrong or missing. But I am afraid that MT changes URL again if I try to update the articles. I don't know what is worse.
</small> </p>ferreira2007-12-17T19:38:20+00:00journalMicro-articles again
http://use.perl.org/~ferreira/journal/35085?from=rss
<p>
After a long pause, I am back to the business of writing the micro-articles on Perl 6 operators.
</p><p>
The article I want to publish tomorrow is about boolean operators and it is <a href="http://feather.perl6.nl/~ferreira/perl6-operators/boolean.html">here</a>. I welcome corrections and suggestions.
</p>ferreira2007-12-11T20:15:16+00:00journalBEGIN { use_ok } keeps biting
http://use.perl.org/~ferreira/journal/35077?from=rss
<p>
The fearless Michael Schwern kept <a href="http://use.perl.org/~schwern/journal/34684">his word</a> and <a href="http://search.cpan.org/src/MSCHWERN/Test-Simple-0.74/Changes">brought back</a> the Test-Simple fix for <tt>BEGIN { use_ok }</tt> bug. (If you don't know what I am saying, read <a href="http://www.archivum.info/perl.qa/2007-09/msg00169.html">this</a>).
</p><p>
Some CPAN dists remain unfixed and those who upgraded the basic test modules will see an error while testing. Outstanding examples are:
</p><ul>
<li> <a href="http://search.cpan.org/dist/File-Temp">File-Temp</a></li>
<li> <a href="http://search.cpan.org/dist/Net-DNS">Net-DNS</a></li>
</ul><p>
Notice that the fix called for in this distributions is a real test bug. A contrived example is of the form:
</p><blockquote><div><p> <tt>use Test::More;<br> <br>if ( $exp_which_tells_test_should_be_skipped ) {<br> plan tests => 1; # this will happen at runtime<br>} else {<br> plan 'skip_all' => 1; # that too<br>}<br> <br>BEGIN { use_ok 'File::Temp' } # at compile-time<br> <br>ok(1);</tt></p></div> </blockquote><p>
When Test::Builder had the bug, it swallowed the exception during <tt>BEGIN { use_ok }</tt> which announced a test before planning. Also, the test count should not include the <tt>use_ok</tt> to get pass this point. Yes, for some time, we authors have introduced not one, but two bugs in this type of code to make it work. Now it is time to write it down correctly.
</p><blockquote><div><p> <tt>use Test::More;<br> <br>BEGIN {<br> if ( $exp_which_tells_test_should_be_skipped ) {<br> plan tests => 2;<br> } else {<br> plan 'skip_all' => 1;<br> }<br>}<br> <br>BEGIN { use_ok 'File::Temp' } # at compile-time<br> <br>ok(1);</tt></p></div> </blockquote><p>
Bonus point: The fixed version works ok with the old (buggy) and the new Test-Simple.
</p>ferreira2007-12-10T15:59:17+00:00journalNewer Exporter for Older Perls
http://use.perl.org/~ferreira/journal/35073?from=rss
<p>
Let's start by saying that Exporter is not an ideal module. It was conceived a long time ago, when some things (like programming practices) were different. But if you need a module with exporting capabilities and are not very demanding, Exporter is the module to use. As a bonus, it is there together with your installed perl.
</p><p>
Once we said this, this article is to announce that Exporter is now available at CPAN and now correctly indexed. This means that from within your CPAN shell, you may say:
</p><blockquote><div><p> <tt>cpan> install Exporter</tt></p></div> </blockquote><p>
and this omnipresent Perl module will be updated to the latest release.
</p><p>
Why is that important?
</p><p>
A lot of CPAN modules break unexpectedly because
its authors used the Exporter feature
</p><blockquote><div><p> <tt> use Exporter 'import';</tt></p></div> </blockquote><p>
which allows a module to get the Exporter's <tt>&import</tt> without needing to inherit from Exporter. However, this appeared only in Exporter 5.57 which was released with perl 5.8.3.
</p><p>
That means that every time a module, which did
the assumption that this feature were always there
with Exporter, was tested against a pre-5.8.3 perl, it choked.
</p><p>
Now these modules can correctly declare they need
at least version 5.57 of Exporter and <tt>cpan</tt> will try to update this very important piece of your standard libraries, to the dismay of many conservative people (including some sysadmins) out there. (Disclaimer: but it will only update if you say so: explicitly or by the configurations you have set up.)
</p><p>
That's evolution coming: time to use new tools even with rusty perls. Maybe, in the next step, people start using newer perls as well. (Hail, 5.10!)
</p>ferreira2007-12-10T11:49:38+00:00journalDON'T make disttest dist
http://use.perl.org/~ferreira/journal/35071?from=rss
One more thing I discovered I should not do: create a tarball in a hurry, right after testing it with a statement like:<blockquote><div><p> <tt>$ make disttest dist veryclean</tt></p></div> </blockquote><p>which I thought should test the distribution-packaged files, create a neat tarball and leave the current directory clean.
THE only mistake is that "make disttest" creates the "blib" directories and "make dist" packages it together in the tarball.
The pause indexer points your error:</p><blockquote><div><p> <em>
The distribution contains a blib/ directory and is therefore not being
indexed. Hint: try 'make dist'.
</em></p></div> </blockquote><p>
And I needed to use some weird file names (like Exporter-5.61b.tar.gz) to index correctly the files. I will be smarter some next time.</p>ferreira2007-12-10T00:56:40+00:00journalA Test::WWW::Mechanize trap: getting contents in a file
http://use.perl.org/~ferreira/journal/34604?from=rss
<p>
Sometimes I wonder at how good I am to
use code in the wrong way. This time I
did it with
<a href="http://search.cpan.org/dist/Test-WWW-Mechanize/">Test::WWW::Mechanize</a>.
I started a test script with:</p><blockquote><div><p> <tt> use Test::WWW::Mechanize;<br> <br> get_ok( $url );</tt></p></div> </blockquote><p>
and then I decided to take a look at the HTML
I was getting. Using the LWP options seemed natural:</p><blockquote><div><p> <tt> get_ok( $url, { ':content_file' => 'p.html' } );</tt></p></div> </blockquote><p>
But that gave me some binary content
rather than the HTML I was waiting for. The problem
was that <tt>WWW::Mechanize</tt> (the father
of most of the browser functionality of the testing
module) determines
that 'gzip' can be used as the content encoding
(if <tt>Compress::Zlib</tt> is available)
and transparently decodes the response.
</p><p>
Unfortunately, the LWP options in <tt>get_ok</tt> are the
same as in <tt>LWP::UserAgent::get</tt> and knows nothing
about this helpful trick. So I got the gzipped
content and not the HTML page. The content
is uncompressed later with other <tt>WWW::Mechanize</tt>
methods.
</p><p>
In turn,</p><blockquote><div><p> <tt> use File::Slurp qw( write_file );<br> write_file( 'p.html', $mech->content );</tt></p></div> </blockquote><p>worked as I needed it.</p>ferreira2007-10-03T22:27:29+00:00journalPerl 6 Micro-articles: grant status
http://use.perl.org/~ferreira/journal/34511?from=rss
<p>
This week has seen the publishing of the
three first micro-articles on Perl 6
operators, following the plan of
<a href="http://use.perl.org/~jesse/journal/34451">this grant proposal</a>.
</p><p>
The links are:
</p><ul>
<li> <a href="http://www.oreillynet.com/onlamp/blog/2007/09/yet_another_perl_6_operator_th_1.html">Introduction</a></li>
<li> <a href="http://www.oreillynet.com/onlamp/blog/2007/09/yet_another_perl_6_operator_zi.html">The zip operator</a></li>
<li> <a href="http://www.oreillynet.com/onlamp/blog/2007/09/yap6_operator_stitching.html">The ~ operator</a></li>
<li> <a href="http://www.oreillynet.com/onlamp/blog/2007/09/yap6_operator_repeat_operators_1.html">Repeat operators</a></li>
</ul><p>
These articles have been published
at Tuesday, Wednesday and Friday.
Probably next week we'll settle in a
more regular schedule like Monday, Wednesday,
and Friday. That means people can read their
<a href="http://xkcd.com/">xkcd strip</a>
and have a small dose of Perl 6
in the morning<nobr> <wbr></nobr>;-)
</p><p>
I gladly watched the article on the
string concatenation operator hit the
12th position in The Hot 25 of
O'Reilly blogs by yesterday. This list
appears to the right of
<a href="http://weblogs.oreilly.com/">the main weblog page</a>.
I am not so sure of how it ended there,
but that's ok, I think.
</p><p>
The project also had, in my opinion, a very
good reception from the Perl community.
And I found help in all channels I announced it:
the #perl6 IRC channel at freenode,
the perl6-language@perl.org mailing list,
use.perl itself and PerlMonks.
Special thanks to
<a href="http://use.perl.org/~autarch">autarch</a>
who generously offered to do grammar editing
improving the English of the texts
no need to say I hastily and gladly accepted it.
All remaining mistakes in these articles are
mine.
</p><p>
It is not all roses however, because I have been
strugling with MovableType, the blog
software of O'Reilly site, and I am losing
by now. Sometimes it raises some pretty database
errors after an update (hum, probable entry
point for SQL injection attacks), but it
gets better after some senseless tweaking.
And more to the point, I have proposed to
maintain an index of all articles in the
introduction, but I encountered the issue
that sometimes MT changes the URL after an
update. This gets very annoying as all articles
refer to the introduction and then need to be updated (while I pray they keep their URLs when I
do this). Also it defeats bookmarking
as a commenter already complained.
If you are well versed in MovableType and have
some clues, I am listening.
</p><p>
Juerd kindly granted me an account at
feather to work/experiment with pugs.
I am also maintaning the article sources
there at a SVK repository which should be
moved into Perl 6 docs later.
I am writing the articles in POD6
and it looks like it is going to be fun.
I squashed a tiny bug on the conversion
to XHTML and I am playing to get nice
looking customizations of the generated HTML.
The articles would be available (POD6 and HTML)
in the URL:</p><blockquote><div><p> <a href="http://feather.perl6.nl/~ferreira/perl6-operators/">http://feather.perl6.nl/~ferreira/perl6-operators/</a></p></div>
</blockquote><p>
The patch and patched Perl6::Perldoc is also
available at <a href="http://feather.perl6.nl/~ferreira/patches/">http://feather.perl6.nl/~ferreira/patches/</a>
but I filed an RT ticket as well, so it has a chance to be permanently fixed.</p>ferreira2007-09-21T14:51:24+00:00journalRubyForge vs CPAN?
http://use.perl.org/~ferreira/journal/34486?from=rss
Daniel Berger has just published this very article: <a href="http://www.oreillynet.com/ruby/blog/2007/09/rubyforge_vs_cpan.html">RubyForge vs CPAN</a>. His conclusions (previsible due to the Ruby bias) were basically summarized by one of his commenters: The differences are "not as extreme as one might assume". I did not dive into the article yet, but it looks like it is founded on many hasty estimates/comparisons in many places.ferreira2007-09-19T12:42:38+00:00journalPerl 6 operator: Stitching
http://use.perl.org/~ferreira/journal/34481?from=rss
Now is the time of the string concatenation operator. Very simple. Departing from the Perl 5 tradition. Read and comment if you feel so.
<p>
<a href="http://ferreira.nfshost.com/perl6/stitching6.html">http://ferreira.nfshost.com/perl6/stitching6.html</a></p>ferreira2007-09-18T19:27:18+00:00journalMicro-articles on Perl 6 Operators
http://use.perl.org/~ferreira/journal/34473?from=rss
<a href="~jesse">Jesse</a>
has announced <a href="http://use.perl.org/~jesse/journal/34451">the acceptance of
my microgrant proposal</a>. It is a plain simple idea,
whose effects are yet to be seen. Comments
and feedback most welcome.
<p>
The plan is to write a series of
blog entries discussing a Perl 6 operator
at a time or a small group of closely related ones.
</p><p>
My working hypotheses are:
</p><ul>
<li> the audience is broader than Perl 6 developers</li>
<li> they should be educational</li>
<li> they should be light</li>
<li> they should not be long</li>
<li> they should show some nice Perl 6 code</li>
<li> they should be based on what's specified</li>
<li> if possible, they should be cool</li>
</ul><p>
The goals:
</p><ul>
<li> make people know more about Perl 6</li>
<li> allow them to do that in an entertaining fashion</li>
<li> entice the curiosity</li>
<li> estimulate the need for Perl 6</li>
<li> spread the word</li>
</ul><p>
The choice to approach Perl 6 via operators
was an artefact. Every single piece of
Perl 6 code would present a bunch
of features, hopefully good enough
to demonstrate the look and feel of the language.
And operators cross over the entire
realm of the language (even more than with Perl 5).
The pretention would be to compose a picture
of the language in small doses like
<i>Marvin Minsky</i>
did in <i>Society of Mind</i> with every chapter in
a single page, striving to get a comprehensible
whole from the component pieces. It's kind of
prententious, but hubris is a quality around here
and I hope not to be alone in this endeavour.
</p><p>
Any help will be much appreciated: suggestions,
corrections, grammar and typo fixes,
rephrasing, etc. As drafts got ready,
I will announce them in Perl channels
(#perl6 at freenode, use.perl, PerlMonks,
perl6-language mailing list) to have a chance
to improve the articles to be published at
ONLamp site.
</p><p>
Join me. The drafts of the introduction and
the first article are here:
</p><ul>
<li> <a href="http://ferreira.nfshost.com/perl6/intro.html">http://ferreira.nfshost.com/perl6/intro.html</a></li>
<li> <a href="http://ferreira.nfshost.com/perl6/zip.html">http://ferreira.nfshost.com/perl6/zip.html</a></li>
</ul>ferreira2007-09-17T17:58:15+00:00journalProgramming in Perl is hard
http://use.perl.org/~ferreira/journal/34365?from=rss
I failed miserably when trying to write
a simple sub <tt>&strip</tt> to trim
leading and trailing spaces, modifying
its argument in-place.
<a href="http://use.perl.org/comments.pl?sid=36848&cid=57535">My attempt</a> was:<blockquote><div><p> <tt># in-place version<br>sub strip { s/^\s+//; s/\s+$//; }<br># which would be used as<br>strip($msg);</tt></p></div> </blockquote><p>
promptly
<a href="http://use.perl.org/comments.pl?sid=36848&cid=57538">corrected</a>
by Aristotle in, not one, but two flavors:</p><blockquote><div><p> <tt>sub strip { $_[0] =~ s/^\s+//; $_[0] =~ s/\s+$//; }<br> <br># or maybe<br> <br>sub strip { s/^\s+//, s/\s+$// for $_[0] }</tt></p></div> </blockquote><p>
When I first thought about it, I believed my
sin was failing to find
<a href="http://www.perl.com/lpt/a/685">the topic</a>.
I mistakenly assumed the sub parameter
was already the topic, while one of the variants by
Aristotle did not use <tt>$_</tt> and the other
used a proper mechanism the modifier "<tt>for $_[0]</tt>"
to set it right. To tell the truth, my version
works if used just as <tt>strip()</tt>, acting on
whatever is in <tt>$_</tt>. (More on this on
a later blog entry.)
</p><p>
My mistake was like saying</p><p><div class="quote"><p>stripping the string is eating the leading and
trailing spaces from <b>something</b></p> </div><p>where that <b>something</b> was left hanging
like a dangling pointer. The phrase below
would be more correct:</p><p><div class="quote"><p>stripping the string is eating the leading and
trailing spaces from <b>it</b> (the string)</p></div><p>
My programming error (in Perl language) was like an ordinary error in a phrase in casual conversation (in natural language).
And the major culprit was not <i>proof-reading</i>
what I wrote.
</p><p>
(Of course, it is also an issue of proficiency.
More practice would often imply a smaller defect ratio
that could have set me free of that shame.
But this proficiency only sets higher the threshold
where mistakes are more likely. They will happen
anyway the issue is whether they have discovered
out there or while in the domestic environment.)
</p><p>
So while writing prose calls for proof-reading,
programming calls for documentation and testing
to be complete. With documentation, we make clear
what is the purpose of the code (even though
<tt>$_ = "this "; strip()</tt> works, it was not
what <tt>&strip</tt> was supposed to do). The
tests would establish a certain level of confidence
on the operation of the code, at least as long
as the usage was captured by the test cases.
Extrapolation is always an enterprise with
unknown consequences.
</p><p>
I was guilty of being a light commenter, typing
faster than my brain takes to write a
<i>correct</i> piece of code of 34 touches.
But it will never be easy. Fortunately, after
Aristotle, some careful documented design and testing, many pieces of code will be as robust as most applications
need.
</p><p>
Ok. The entry title was provocative. It
only means: Programming is hard. And you already knew that.</p>ferreira2007-09-06T18:46:05+00:00journalLanguage De-acquisition
http://use.perl.org/~ferreira/journal/34359?from=rss
<p>
Back in the university days, I've read a few
texts on
language acquisition and almost understood
some of the mechanisms used to learn a foreign
language. I enjoyed learning about learning.
A lot of reading helped me out with
English and a lot of practice allowed me
writing some comprehensible articles.
</p><p>
Nowadays, I am faced with the inverse phenomenon:
language de-acquisition. I never knew it existed.
But after years of non-practice, I don't have
any conversation skills in English and I just found out
that I am getting worse at writing too. Silly
me that thought that it was like riding a bike:
never to be forgotten.
</p><p>
I diminished a lot on the diversity and volume of reading.
Today it takes me too long to write
a few paragraphs. And when it is done, it does not
make much sense and is riddled with mistakes.
It sadly reminds me of a joke we use to tell
on a guy that went into
USA, could not learn some English and came back
home... dumb. Disgusting.</p>ferreira2007-09-06T00:36:47+00:00journal"perldoc -L" support gets easier
http://use.perl.org/~ferreira/journal/34336?from=rss
<a href="http://search.cpan.org/dist/Pod-Perldoc/">Pod::Perldoc</a> has a recently introduced feature via a new switch <tt>-L</tt>.<blockquote><div><p> <tt>$ perldoc -L it perlintro # perlintro in Italian<br>$ perldoc -L fr -f pack # read about pack in French<br>$ perldoc -L eo -q shell # search Esperanto FAQs about 'shell'<br>$ perldoc -L tlh Acme::DonMartin # the docs of Acme::DonMartin in Klingon</tt></p></div> </blockquote><p>
(Obviously, it works if you have installed the corresponding translated PODs.)
</p><p>
These changes were applied to bleadperl and published on CPAN in release <a href="http://search.cpan.org/~ferreira/Pod-Perldoc-3.14_01/">3.14_01</a>. The original work by Italian mongers were followed by a similar distribution of a French translation package (<a href="http://search.cpan.org/dist/POD2-IT/">POD2::IT </a> and <a href="http://search.cpan.org/dist/POD2-FR/">POD2::FR</a>). These distributions relied on a certain amount of code that <tt>Pod::Perldoc</tt> called in the manner of a plugin.
</p><p>
After some work on the underlying code, it became evident that the essential of the distribution of the translated PODs was amazingly simple. Place PODs in the corresponding <tt>POD2::<lang></tt> namespace. There's not much more about it (and there is some work in progress on the stuff that remains).
</p><p>With a lift in the original code in <tt>POD2::IT</tt> and some corresponding changes of <tt>Pod::Perldoc</tt>, it is possible to distribute and use translated PODs in a very simple way. The necessary steps are:
</p><ul>
<li>install <a href="http://search.cpan.org/dist/POD2-Base/">POD2::Base</a></li>
<li>install <a href="http://search.cpan.org/~ferreira/Pod-Perldoc-3.14_01/">Pod::Perldoc 3.14_03</a></li>
<li>just make sure your translated PODs get shipped and installed in <tt>POD2::<lang></tt> namespace</li>
</ul><p>
and voilà. Silly internationalization at perldoc level working.
</p><p>
I am taking a time, waiting for bugs to show up, feedback, and will submit these changes to bleadperl.</p>ferreira2007-09-04T15:25:40+00:00journal