ferreira's Journal http://use.perl.org/~ferreira/journal/ ferreira's use Perl Journal en-us use 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:00 pudge pudge@perl.org Technology hourly 1 1970-01-01T00:00+00:00 ferreira's Journal http://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&#227;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> ferreira 2008-09-16T22:36:46+00:00 journal Bye 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> ferreira 2008-05-31T22:20:31+00:00 journal Is 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> ferreira 2008-05-01T02:50:08+00:00 journal Clashes 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-&gt;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>&nbsp; &nbsp; my $self = shift;<br>&nbsp; &nbsp; my $on_warn = $self-&gt;on_warn;<br>&nbsp; &nbsp; if ( $on_warn ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;$on_warn-&gt;(@_);<br>&nbsp; &nbsp; } else {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Carp::carp(@_);<br>&nbsp; &nbsp; }<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>&nbsp; &nbsp;<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>&nbsp; &nbsp;$self-&gt;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-&gt;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> ferreira 2008-05-01T02:37:56+00:00 journal Being 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>&nbsp; &nbsp; 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>&nbsp; &nbsp; push @array, @$x;<br>}</tt></p></div> </blockquote><p> whick is ok (as long as <code>$x</code> contains array refs or undefs). </p> ferreira 2008-04-25T12:10:40+00:00 journal "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> ferreira 2008-04-23T13:06:31+00:00 journal Nancy: 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> ferreira 2008-03-09T20:13:29+00:00 journal Abusing "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>&nbsp; my ($sz, $opt) = @_;<br> <br>&nbsp; my $format = $opt-&gt;{format};<br>&nbsp; if ( $format eq 'h' ) {<br>&nbsp; &nbsp; require Numbers::Bytes::Human;<br>&nbsp; &nbsp; return Number::Bytes::Human-&gt;new-&gt;format( $sz );<br>&nbsp; }<br>&nbsp; else { # raw bytes<br>&nbsp; &nbsp; return $sz;<br>&nbsp; }<br>}</tt></p></div> </blockquote><p> Of course, loading <code>Number::Bytes::Human</code> and creating a instance every time <code>$f-&gt;size({ format =&gt; '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>&nbsp; require Number::Bytes::Human;<br>&nbsp; return Number::Bytes::Human-&gt;new;<br>}<br>memoize('_size_formatter');<br> <br>sub _format_size {<br>&nbsp; my ($sz, $opt) = @_;<br> <br>&nbsp; my $format = $opt-&gt;{format};<br>&nbsp; if ( $format eq 'h' ) {<br>&nbsp; &nbsp; return _size_formatter-&gt;format( $sz );<br>&nbsp;<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>&nbsp; require Number::Bytes::Human;<br>&nbsp; return Number::Bytes::Human-&gt;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> ferreira 2008-03-05T20:13:03+00:00 journal Wanna 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> ferreira 2008-02-14T16:07:10+00:00 journal What'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> ferreira 2008-02-13T17:13:46+00:00 journal Another 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&nbsp;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-&gt;()&nbsp; &nbsp; &nbsp; &nbsp; returns ()<br>$id-&gt;(42)&nbsp; &nbsp; &nbsp; returns (42)<br>$id-&gt;(42,42)&nbsp; &nbsp;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-&gt;(42);&nbsp; &nbsp;# 1 gets assigned to $c (from scalar @_)<br>($a) = $id-&gt;(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>&nbsp; &nbsp; 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&nbsp;-&gt;&nbsp;A</code>. Then, if we consider the non-void contexts Perl&nbsp;5 provides: list and scalar, we have not one but two identity functions to consider. Namely, </p><blockquote><div><p> <tt>sub { @_ }&nbsp; &nbsp; # for list context, LIST -&gt; LIST<br>sub ($) { $_[0] } # for scalar context, SCALAR -&gt; 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>&nbsp; &nbsp; if ( wantarray ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; @_;<br>&nbsp; &nbsp; } else {<br>&nbsp; &nbsp; &nbsp; &nbsp; die "too many arguments" unless @_==1;<br>&nbsp; &nbsp; &nbsp; &nbsp; $_[0];<br>&nbsp; &nbsp; }<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&nbsp;6 will have to do with this? You bet no one is going to draw back and "relieve" Perl&nbsp;6 of that extra expressiveness her mother language has. On contrary, Perl&nbsp;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 -&gt; Any: ) { $x }</tt></p></div> </blockquote> ferreira 2008-02-09T17:14:00+00:00 journal A 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-&gt;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>&nbsp; &nbsp; shift;<br>&nbsp; &nbsp; 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>&nbsp; &nbsp; shift;<br>&nbsp; &nbsp; 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&#231;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> ferreira 2008-02-07T18:08:47+00:00 journal SMTP/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>{&nbsp; &nbsp;auth =&gt; { user =&gt; 'me', pass =&gt; '***' } }</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> ferreira 2008-01-25T18:41:07+00:00 journal WWW::CPAN-&gt;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> ferreira 2008-01-14T22:51:06+00:00 journal Perl 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&nbsp;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&nbsp;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&nbsp;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&nbsp;6 is finally released. </li></ul><p> So I want to thank everyone that contributed to the current state of Perl&nbsp;6-related development and to wish much fun in the future work that will bring us this long-awaited Christmas gift. </p> ferreira 2007-12-28T20:53:12+00:00 journal The 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__-&gt;mk_constructor0({<br>&nbsp; foo =&gt; 42,<br>&nbsp; bar =&gt; 'fourty-two',<br>});<br>__PACKAGE__-&gt;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>&amp;Foo::new</code> to work out the wanted magic. </p><blockquote><div><p> <tt>my $foo = Foo-&gt;new();<br>is( $foo-&gt;foo, 42 );<br>is( $foo-&gt;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>&nbsp; my $self = shift;<br>&nbsp;<nobr> <wbr></nobr>...<br> <br>&nbsp; # return a closure<br>&nbsp; return sub {<br>&nbsp; &nbsp; my $self = shift;<br>&nbsp; &nbsp;<nobr> <wbr></nobr>...<br>&nbsp; &nbsp; return $self-&gt;SUPER::new-&gt;( $self, \%f ); # XXX the offender<br>&nbsp; };<br>}</tt></p></div> </blockquote><p> I must say that this code is deceptively simple and wrong. Because <code>-&gt;SUPER::new</code> tried to invoke the <code>&amp;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>-&gt;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>&nbsp; &nbsp; return $self-&gt;super('new')-&gt;( $self, \%f );</tt></p></div> </blockquote><p> After this, the <code>&amp;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>-&gt;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> ferreira 2007-12-28T17:01:31+00:00 journal More 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&nbsp;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> ferreira 2007-12-22T19:37:03+00:00 journal Five 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> ferreira 2007-12-17T19:38:20+00:00 journal Micro-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> ferreira 2007-12-11T20:15:16+00:00 journal BEGIN { 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>&nbsp; &nbsp; plan tests =&gt; 1; # this will happen at runtime<br>} else {<br>&nbsp; &nbsp; plan 'skip_all' =&gt; 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>&nbsp; &nbsp; if ( $exp_which_tells_test_should_be_skipped )&nbsp; &nbsp; &nbsp;{<br>&nbsp; &nbsp; &nbsp; &nbsp; plan tests =&gt; 2;<br>&nbsp; &nbsp; } else {<br>&nbsp; &nbsp; &nbsp; &nbsp; plan 'skip_all' =&gt; 1;<br>&nbsp; &nbsp; }<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> ferreira 2007-12-10T15:59:17+00:00 journal Newer 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&gt; 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>&nbsp; use Exporter 'import';</tt></p></div> </blockquote><p> which allows a module to get the Exporter's <tt>&amp;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> ferreira 2007-12-10T11:49:38+00:00 journal DON'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> ferreira 2007-12-10T00:56:40+00:00 journal A 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>&nbsp; &nbsp; use Test::WWW::Mechanize;<br> <br>&nbsp; &nbsp; 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>&nbsp; &nbsp; get_ok( $url, { ':content_file' =&gt; '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>&nbsp; &nbsp; use File::Slurp qw( write_file );<br>&nbsp; &nbsp; write_file( 'p.html', $mech-&gt;content );</tt></p></div> </blockquote><p>worked as I needed it.</p> ferreira 2007-10-03T22:27:29+00:00 journal Perl 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&nbsp;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> ferreira 2007-09-21T14:51:24+00:00 journal RubyForge 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. ferreira 2007-09-19T12:42:38+00:00 journal Perl 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> ferreira 2007-09-18T19:27:18+00:00 journal Micro-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> ferreira 2007-09-17T17:58:15+00:00 journal Programming in Perl is hard http://use.perl.org/~ferreira/journal/34365?from=rss I failed miserably when trying to write a simple sub <tt>&amp;strip</tt> to trim leading and trailing spaces, modifying its argument in-place. <a href="http://use.perl.org/comments.pl?sid=36848&amp;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&amp;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>&amp;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> ferreira 2007-09-06T18:46:05+00:00 journal Language 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> ferreira 2007-09-06T00:36:47+00:00 journal "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::&lt;lang&gt;</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::&lt;lang&gt;</tt> namespace</li> </ul><p> and voil&#224;. 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> ferreira 2007-09-04T15:25:40+00:00 journal