Hi! Please consider following me on twitter: @hanekomu.
2010年03月18日
Boolean normalization using the logical negation operator
The perlsyn manpage says the following about truth and
falsehood:
The number 0, the strings '0' and '', the empty list "()", and "undef" are all false in a boolean context. All other values are true. Negation of a true value by "!" or "not" returns a special false value. When evaluated as a string it is treated as '', but as a number, it is treated as 0.
Sometimes you want to normalize a value so that it is 1 if it is a true value and 0 if it is a false value. This is sometimes called boolean normalization.
Usually you will see something like this:
my $b = $value ? 1 : 0;
There is an easier way. You could make use of the logical negation operator,
!. When it is applied to a true value, it returns a dual value
that is the number zero in numerical context and the empty string in string
context. When the logical negation operator is applied to a false value, it
returns a dual value that is the number 1 in numerical context and the string
"1" in string context. Let's see this in detail:
$ perl -MDevel::Peek -le'Dump !42' SV = PVNV(0x802000) at 0x12fef8 REFCNT = 2147483647 FLAGS = (IOK,NOK,POK,READONLY,pIOK,pNOK,pPOK) IV = 0 NV = 0 PV = 0x200160 ""\0 CUR = 0 LEN = 4 $ perl -MDevel::Peek -le'Dump !0' SV = PVNV(0x802014) at 0x12ff08 REFCNT = 2147483646 FLAGS = (IOK,NOK,POK,READONLY,pIOK,pNOK,pPOK) IV = 1 NV = 1 PV = 0x200170 "1"\0 CUR = 1 LEN = 4
By using the logical negation operator twice you can therefore simplify the above statement to:
my $b = !!$value;
And if you wanted the opposite boolean normalization, it's even easier:
my $b = $value ? 0 : 1;
becomes:
my $b = !$value;
posted at: 08:22 | path: /dev | permalink | 5 comments | 0 trackbacks
2010年03月17日
Use parent.pm instead of base.pm
For years, the common way for your class to inherit from one or more superclasses was the base module. For example:
package Game; sub new { bless {}, shift } package Baduk; use base 'Game';
This works, but some people, me included, aren't quite happy with that. Basically, the above could also be expressed as:
package Game; sub new { bless {}, shift } package Baduk; our @ISA = qw(Game);
If the two packages were in different files, the Baduk package
would have to load the file where the Game package lives in as
well. But that's about it.
However, base.pm goes further than that. It supports deprecated
pseudohases, tries to be clever with $VERSION and generally just
does too much. A lot of cruft has accumulated over the years. So a new module,
parent, was forked from base.pm and cleaned
up.
Using parent.pm is pretty much the same as
base.pm:
package Game; sub new { bless {}, shift } package Baduk; use parent 'Game';
This will try to load Game.pm as well. If the Game
package is in a different file that is already loaded, you can tell
parent.pm not to try to load the file:
package Game; sub new { bless {}, shift } package Baduk; use parent -norequire, 'Game';
Compare the source of the two modules and you will find that
parent.pm is a lot cleaner and easier to understand.
posted at: 23:26 | path: /cpan_gems | permalink | 2 comments | 0 trackbacks
2009年12月13日
Plack::Middleware::Debug
I wrote and released a new middleware for Plack: Plack::Middleware::Debug. It was on miyagawa's wishlist for Plack and is based heavily on the Django Debug Toolbar. miyagawa also helped to get this middleware in proper shape to play nicely with the rest of Plack.
Here is an example of how to use it. Put this in your
app.psgi:
use Plack::Builder; use File::Basename; my $app = sub { ... }; builder { enable 'Debug', panels => [ qw(Environment Response Timer Memory DBITrace) ]; $app; };
The debug middleware offers a configurable set of panels that displays
information about the current request and response. The information is
generated only for responses with a status of 200 (OK) and a
Content-Type that contains text/html and is embedded
in the HTML that is sent back to the browser.
If you pass a list of panel base names to the enable() call,
only those panels will be enabled. If you don't pass an argument, the default
list of panels — Environment, Response,
Timer and Memory — will be enabled.
As of version 0.01, the following panels are available:
DBITracedisplay DBI trace information.Environmentdisplays the PSGI environment from the request.Memorydisplays memory usage before the request and after the response.ModuleVersionsdisplays the loaded modules and their versions.PerlConfigdisplays the configuration information of the Perl interpreter itself.Responsedisplays the status code and response headers.Timerdisplays how long the request took.
The following two screenshots demonstrate the DBITrace and
Environment panels.
You could use the power of the debug toolbar for your own framework or web
application. It is quite easy to write custom panels. Just subclass
Plack::Middleware::Debug::Base, then use your panel in the
enable() call.
If you are interested, join us on #plack on irc.perl.org. The development repository is on GitHub.
posted at: 12:04 | path: /dev | permalink | 0 comments | 1 trackback
2009年10月20日
HTML stack trace from the Perl debugger
Tatsuhiko Miyagawa released Devel::StackTrace::AsHTML and blogged about it.
I thought this would make a neat Perl debugger command, so I wrote DB::Pluggable::StackTraceAsHTML. It is a plugin to DB::Pluggable. It adds the Th command to the
debugger, which displays a stack trace in HTML format, with lexical variables.
It then opens the page in the default browser.
Here is an example of how to use it:
$ perl -d test.pl Loading DB routines from perl5db.pl version 1.3 Editor support available. Enter h or `h h' for help, or `man perldebug' for more help. main::(test.pl:14): my $n = 12; DB<1> r main::fib(test.pl:12): return fib($i - 1) + fib($i - 2); DB<1> Th
The result would look something like:

To enable the plugin, just add it to your ~/.perldb, like so:
use DB::Pluggable; use YAML; $DB::PluginHandler = DB::Pluggable->new(config => Load <<EOYAML); global: log: level: error plugins: - module: BreakOnTestNumber - module: StackTraceAsHTML EOYAML $DB::PluginHandler->run;
By the way, to be minimally invasive to the existing Perl debugger, the
command is defined using the debugger's aliasing mechanism. Normally you define
an alias as a regular expression that will change the command the user enters
to a known command, but here we circumvent that and call our command handler
directly. The following method is from DB::Pluggable::Plugin:
sub make_command { my ($self, $cmd_name, $code) = @_; no strict 'refs'; my $sub_name = "DB::cmd_$cmd_name"; *{$sub_name} = $code; $DB::alias{$cmd_name} = "/./; &$sub_name;"; }
To define a new foo command in a plugin, you then use:
package DB::Pluggable::StackTraceAsHTML; use strict; use warnings; use base qw(DB::Pluggable::Plugin); sub register { my ($self, $context) = @_; $self->make_command( foo => sub { # ... } ); }
posted at: 22:09 | path: /dev | permalink | 0 comments | 0 trackbacks
2009年10月05日
Repeatedly installing Task::* distributions
First there were Bundle::* distributions to install several
dependencies at once without the actual bundle distribution doing anything,
but this required magic in the toolchain. A newer concept is that of a
Task::* distribution, as described in Task.
Task modules are just normal Perl modules; they don't require toolchain
magic. When the dependencies listed in Makefile.PL have been
installed, the actual Task module, for example Task::Catalyst, will be installed as well.
This is a problem because if the task's dependencies are being updated,
the task module needs to be updated as well. For example, DBD::SQLite is a dependency of
Task::Catalyst. If there is a new version of
DBD::SQLite, just running
install Task::Catalyst in the CPAN shell won't have any
effect, because the CPAN shell will see that the latest version of
Task::Catalyst is already installed. Of course you can force
with force install Task::Catalyst, but even if that would
work, it would be ugly because I don't want to install dependencies that
fail their tests.
One solution is to prevent the task module itself to be installed. That
way, every time you rerun install Task::Foo in the CPAN
shell, it will see that the task module isn't installed and try to install
it again, with all the desired dependency checking.
How do we prevent the module from being installed? Put these lines in
your Makefile.PL — I always use Module::Install, but I think this should work for all
MakeMaker-based files:
exit 0 if $ENV{AUTOMATED_TESTING}; sub MY::install { "install ::\n" }
First, we don't need to waste the time of CPAN testers by having them
install all the dependencies for a task module that doesn't really do
anything anyway. Second, and more importantly, we override the
install :: target that is generated for the
Makefile to effectively be a no-op.
I have demonstrated this technique in Task::BeLike::hanekomu, a somewhat pointless distribution
that serves mainly as proof-of-concept, and as a way to install my
favourite modules onto a new perl installation. If you don't mind the
dependencies, then go ahead and repeatedly run
install Task::BeLike::hanekomu in the CPAN shell; the
task module itself should never be installed and it should recheck the
dependencies every time.
I think this would be a good thing to put in existing task distributions such as Task::Kensho and Task::Catalyst.
posted at: 12:27 | path: /dev | permalink | 6 comments | 1 trackback
2009年09月17日
Text::Pipe trademark controversy
There has been a series of curious emails from a software developer in Australia who argues that one of my Perl module distributions on CPAN infringe on his trademark. He has a Windows product called "TextPipe Pro" and thinks that my Perl module called Text::Pipe dilutes his desired search results.
It all started in December 2008; I've lost his original mail — I don't keep every bit of rubbish some random people send me — but here is my reply from that time (I've deleted his last name and all email addresses and other contact details):
From: Marcel Grünauer Sent: Tuesday, 16 December 2008 9:42 AM To: Simon Subject: Re: Text-Pipe Importance: High Hi Simon, On Dec 15, 2008, at 10:49 PM, Simon wrote: > I would greatly appreciate it if you could rename your Text-Pipe > package to avoid confusion and to prevent dilution of the keywords I > use to earn an income. Sorry, I won't rename my Perl distributions. "Text-Pipe" and its related distributions are only found on CPAN and on github and are Perl-specific. There are also people who use this package and I don't want to inconvenience them by renaming my packages. It would also be a major undertaking for me as I would have to think of a new name, replace the names, create a new repository and import the whole history from the old one (you can't rename a repository on github), re-uploading all the distributions (there are several related ones), notifying everyone and so on. Also, neither the word "text" nor the word "pipe" express particularly novel concepts in software, nor does the combination of the two. Regarding keywords: googling for "textpipe", "text pipe" and "text- pipe" lists your software as the top hits, so I don't think you have to fear anything from my set of perl modules. Further, I could also object that your description "A Swiss Army knife for fixing text" dilutes keywords normally referring to Perl. "Text::Pipe" is not a trademark, nor does it challenge yours. [...] Marcel Grünauer
After that, I didn't hear any more from him for nine months, so I forgot all about it. Until the 17th September 2009, when Simon saw fit to bring up the topic again:
From: Simon Subject: RE: Text-Pipe Date: September 17, 2009 5:29:03 AM GMT+02:00 To: Marcel Grünauer Hi Marcel, TextPipe forms my entire income, and supports my wife, our 4 kids, and my house mortgage. TextPipe is a registered trademark (in Australia), but yes, I'd probably have to register it in every country on the planet. I've been using that name to describe it for over 10 years. I am simply asking if you could please change your Perl module name to Text::Filter, Text::Adaptor or something else. Please reconsider. Regards, Simon
I considered. However, a few hours later, he made the questionable move of contacting my bosses at work about this matter:
Subject: Infringment of trademark TextPipe by Marcel Grünauer Date: Thu, 17 Sep 2009 12:38:50 +1000 From: Simon Organisation: DataMystic To: Marcel's Boss [...] I see this growing into a commercial vs free, trademarked vs 'I can do whatever I like and you can't stop me because I work for a University' type-war. I would like you to get Marcel to change the name of his package to something that does not conflict. Failing that, I'd like you to mediate, or appoint a mediator from your department who has worked for a software company, to help resolve this matter in the best interests of all. [...]
Now he was beginning to piss me off. I explained to my boss that I developed this module in my spare time and that we don't even use it at work, and my boss is cool, so he wrote that back to the guy. I also replied to the guy:
Subject: Re: Text-Pipe From: Marcel Grünauer Date: September 17, 2009 2:40:46 PM GMT+02:00 To: Simon Hi Simon, [...] Text-Pipe is a Perl module distribution which I have developed purely in my private time and it has nothing to do with work; it's not even used in any code at work. As such I see you writing to my boss(es) as highly inappropriate. It is also a sure way to get me to not consider any changes. My boss has spoken to the company's lawyers - basically you don't stand a legal chance to force me to change it. The lawyers see my original arguments (not novel concepts, more general terms etc.) as valid as well; they also explicitly stated that trademark law is not applicable in this particular case. Besides I don't want to set a precedent for this kind of behavior - there would be no end to it. I am pleased to hear that your software financially supports you, your wife, four children and a mortgage. Therefore let me repeat my original offer (from nine months ago): If you would like to contract me to make any changes you like, I can send you my rate card. Regards, Marcel Grünauer
At the time of writing this blog entry, the Google link Simon wrote about in his email would show mostly his software; my module came in third position on both the first and second page of search results. Maybe he just has a SEO problem, who knows.
The reason I'm writing about this at length is that it raises a potential problem. There are CPAN mirrors in many countries and I guess it would be next to impossible to make sure that no module name resembles any trademarked name in every country. So I ask the perl community to discuss this aspect.
Then something else happened which shows why it is a bad idea to piss off geeks who run the infrastructure. I discussed the whole matter with the fine folks on the #london.pm IRC channel when, after it had been noted that text-pipe.com was still available, Ash Berlin registered the domain without further ado and made it to point to the CPAN distribution.
It is possible that because of this, the ratio of Google search results for TextPipe Pro and Text::Pipe is going to change. I wonder if Simon is familiar with the term Streisand effect.
Note that I have no intention of infringing on anyone's trademark and I have no desire to take away business from TextPipe Pro. Anyone who is looking for a Windows text manipulation application will, upon landing on the CPAN web pages, quickly realize that this isn't what they were looking for and look at other search results. That being said, I don't take kindly to threats — however politely they may be phrased — and pestering my boss about it is a certain way to not get on my good side.
I've also put a link to the TextPipe Pro product web site in the SEE
ALSO section of all modules of Text-Pipe 0.09, so
maybe that'll be ok.
Anyway, like I wrote, this is a potential concern for the Perl community, so a discussion about it is welcome.
Update: He sent me another mail asking me to remove the links to his site again because "this is going to make the current situation worse, not better". So I did and uploaded version 0.10
posted at: 17:37 | path: /misc | permalink | 19 comments | 0 trackbacks
2009年09月14日
Easy metadata for CPAN modules
Earlier I wrote about how to enhance a CPAN distribution by including metadata about that distribution's place in its infrastructure — where to find its homepage, bug tracker and repository.
There are now Module::Install plugins on CPAN that make
this task easier. Tatsuhiko Miyagawa wrote Module::Install::Repository and I wrote Module::Install::Homepage and Module::Install::Bugtracker. So now your
Makefile.PL can simply include these lines:
auto_set_homepage; auto_set_bugtracker; auto_set_repository;
To set the repository link, your distribution's version control is examined. The distribution's homepage is set to its page on http://search.cpan.org, and the distribution's bugtracker is set to its RT queue on http://rt.cpan.org.
posted at: 10:13 | path: /dev | permalink | 0 comments | 0 trackbacks
2009年08月25日
Perl modules past their sell-by date
Audrey wrote about _why's disappearance and although I have honestly never heard about _why up until the recent excitement (must not have been popular in my cave). But there was a quote from _why in her blog post that made me think:
programming is rather thankless. u see your works become replaced by superior ones in a year. unable to run at all in a few more.
That is very true. I have written and uploaded to CPAN quite a number of Perl module distributions. I obviously found them useful at the time I wrote them, but the Perl world moves on (rather fast as of late), and most of my distributions have fallen out of favor.
So I ask myself why I leave my deprecated distributions on CPAN. I don't need them anymore, and I certainly don't want to maintain them. I also don't care about having a three-digit number of CPAN distributions for the sake of some useless ranking. The modules will turn up as search results, and someone else might find them useful, but if other people asked me about the module in question I would probably refer them to some more modern code.
Just deleting them is proabably not a good idea either because someone might have the modules in use, though I don't flatter myself — I'm probably the only user of most of my code.
Is there some drop-off account where you can leave unloved modules?
posted at: 11:23 | path: /misc | permalink | 10 comments | 0 trackbacks
2009年08月24日
First names in the Perl community
There are some names that don't really need further qualifying; the first name is enough. "Larry", "Audrey", "Damian" — I think that even outside the Perl world, a lot of people will know who is meant. "Miyagawa" is an exception, but then in Japan the first name is generally de-emphasized and instead the given name is used even among colleagues.
posted at: 10:15 | path: /misc | permalink | 4 comments | 0 trackbacks
2009年08月23日
Signals from Audrey
Blog replies, blog posts, github activity and tweets — there have been quite a few signals from Audrey Tang lately. I'm glad Audrey is gradually coming back; I remember being inspired and awe-struck by her (back then, "his") brilliance at an Austrian Perl Workshop.
posted at: 19:04 | path: /misc | permalink | 0 comments | 0 trackbacks

