Skip to main content

Posts

Learning Perl5i #3 revisted

I was somewhat uncomfortable that my solution to the combinatorics task, which involved a single, not very long routine, became so long with the addition of command line processing and POD  documentation. For one thing, while it had some information about how to invoke the routine, it did not have tests. I still feel that a book on programming, say, should have a fully-implemented solution once a chapter, perhaps, to show the way things should be done. But that is too long for every single bit of code. Full documentation and sample implementations stretch on too long, compared to the few lines a snippet actually deserves. Providing tests may still be appropriate. They take up less space than full documentation, yet explain how the various components work, by the very act of stress-testing those lines of code. Tests provide examples of how the code should be invoked. Revising the combinatorics task into a module, this generates: use perl5i::2; # ---------------------------...

Learning Perl5i #3

I've long admired the way functional languages specify multiple implementations of a routine for different sets of argument values, to detect terminal conditions. Converting a Perl6 solution  of a combinatorics task to Perl5i, I realized the plain Perl solution isn't necessarily all that bad, either. The problem is to list the different ways you can select M elements from a set of N. Select 2 elements from a set of 4 would lead to the values ( 1, 2 ); ( 1, 3 ); ( 1, 4 ); ( 2, 3 ); ( 2, 4 ); ( 3, 4 ). Oh yeah, they want the characters in each combination in sorted order, and  the list of combinations sorted, too. So it all consists of a single routine which gets invoked as combine(3, ['a'..'e']) . Ignore the first couple of lines, for a moment. If the first character of the set exists in a combination, it must be in the first position, since the characters are in sorted order. That means the remainder of the combination must be one character shorter, made...

Learning Perl5i #2

Continuing the exploration of Perl5i beyond  part one , I decided to treat perl5i as a language and use it to implement tasks at  Rosetta Code . Since Moose is a complete OO solution, I use a lightweight approach to OO, where used. The first RC task I implemented is 100 doors : see  the full implementation. In terms of documentation, I gave each routine a small header in which I show how the routine is invoked, specify the inputs and outputs, and summarize the primary actions of the routine. Since the task is defined in terms of a number of doors, and operations on those doors, it seemed appropriate to use an object. "some object" + "operations on that object" ==> "segregate into an OO implementation". I used a simple constructor with initialization performed in _init() to simplify subclassing. The constructor doesn't need to be modified, just a new _init() written to handle additional attributes or arguments, if any. The new implementa...

Learning Perl5i

I've been looking at the module perl5i , which puts a sideways twist on Perl, eliminating tons of boring boilerplate, and introduce many conveniences. In this case, the i eliminates complexity. Installing perl5i installs a number of other modules as well, on the other hand life becomes better once they are installed. If you don't have cpanm or one of the other improved CPAN installers, the simplest way is to install perl5i and its friends using the command       sudo cpan perl5i You may need to type in yes to have cpan  install dependencies. Some modules are needed only temporarily during installation, and you are asked whether you want them permanently installed. Perl modules don't take up very much space, so I always go for it. Installation is a bit different on Windows or Linux machines, but you can figure it out, you're a mighty Perl programmer! One consideration is that major versions of perl5i may change in drastic ways. But you don't include p...

Are your files SM? M? XL? the procedural XL solution

I presented this challenge at work as a beat-the-winter-blahs activity. But then I felt I couldn't present a merely operative solution. As the local Perl geek, I felt required to demonstrate that Perl could do clean, well written solutions, not just line noise. I wanted a balance between advanced Perl features and easy comprehension. On the Unix command line, I prefer piping commands together, rather than using a bunch of intermediate files. Similarly in Perl I advocate using map{} and grep{}, and feeding the output of one function into the input of another. I consider those standard idioms any programmer needs to learn. On the other hand, there were a couple of situations where exceptions and oddities in the code made me uncomfortable. Pulling things into subroutines such as calc_field_width() simplified things and made the code clearer, I think. I guess the lesson of that is that short subroutines are better. I knew that! I'm open to suggestions for alternative ways of...

Are your files SM? M? L? XL? Mid-Size

What I actually had in mind when I came up with the challenge was something like the following ... the sort of thing you find in SysAdmin magazine or Randall Schwartz's columns. #!/usr/local/bin/perl5.10 use 5.010; use strict; use warnings; use Readonly; Readonly my $DOT => q{.}; Readonly my $DOTDOT => q{..}; Readonly my $ESCAPE_BACKSLASH => q{\\}; die "USAGE: $0 rootdir.\n" unless @ARGV; my @dirs = ( @ARGV ); my %stats; while (@dirs) { my $one_dir = shift @dirs; $one_dir =~ s{(\s)}{$ESCAPE_BACKSLASH$1}g; # escape spaces for glob() ENTRY: while ( my $entry = glob "$one_dir/*" ) { next ENTRY if $entry eq $DOT or $entry eq $DOTDOT; if ( -d $entry ) { push @dirs, $entry; } else { my $size = -s _; my $len = $size == 0 ? 0 : length $size; $stats{$len}++; } } } for my $size ( sort { $a $b} keys %stats ) { my $maxsize = 10**$size; say sprintf( ' Started with some di...

Are your files SM? M? L? XL? Kwick-N-EZ

When I first thought up the programming exercise I described last week in Are your files SM? M? L? XL? , my intention was to have a trivial exercise for applicants to carry out. HR was passing through lots of applicants who had detailed database knowledge, but were not at all programmers. They couldn't name simple Unix commands, couldn't talk about how to carry out a task in Perl or shell or as a pipeline of Unix commands. I thought this exercise would be simple for any experienced programmer to carry out, never mind style or performance points. Shortly after I came up with the idea, I realized it could mostly be done as a Unix pipeline. find ~/ -type f -printf "%s\n" |\ perl5.10 -n -E 'say length' |\ sort |\ uniq -c |\ perl5.10 -n -E ' |\ $fill, $count, $size) = split /\s+/; |\ $exp = 10**($size-1) |\ say "$exp $count" ' Although I hadn't used the option before, m...