Stuff with the Perl Foundation. A couple of patches in the Perl core. A few CPAN modules. That about sums it up.
Do a little research into COBOL and a few interesting things jump out at you. Some of this information is from Gartner Group and the rest can easily be verified by doing even a brief survey of the field. Taking the following bits of information:
People really, really underestimate these problems. For example, I've seen several companies express a desire to move away from Perl but find out they can't because they don't realize quite how reliant on the language they are. Now imagine a multi-national corporation with several million lines of COBOL code. What are they going to do?
COBOL salaries, from what I've seen, are trending upwards. Older programmers are sometimes being enticed out of retirement to maintain legacy systems (this is rather hit or miss as there appears to still be some age discrimination here). There are companies out there offering software to allow COBOL programmers to write NetBeans, integrate with
So let's summarize the above:
You see the issue here? There's a fortune to be made for the people who figure out how to turn this trick. My thought is to not write supplementary tools for COBOL. It's to write a COBOL compiler on top of Parrot. Imagine coming across the following COBOL[1]:
000510 MAIN-PARA.
000520 OPEN INPUT IN-FILE
000530 OUTPUT OUT-FILE
000535
000540 PERFORM UNTIL END-OF-FILE
000550 ADD 10 TO LINE-NUMBER
000560 READ IN-FILE AT END
000570 MOVE 'Y' TO EOF-FLAG
000580 NOT AT END
000590 IF (CHAR-1 = '*')
000600 OR (CHAR-1 = '/')
000610 OR (CHAR-1 = '-') THEN
000620 MOVE LINE-CODE-IN TO L-COMMENT
000630 MOVE LINE-NUMBER TO L-NUM-COM
000640 WRITE LINE-CODE-OUT FROM NUMBER-COMMENT
000660 ELSE
000670 MOVE LINE-CODE-IN TO L-CODE
000680 MOVE LINE-NUMBER TO L-NUM-CODE
000690 WRITE LINE-CODE-OUT FROM NUMBER-CODE
000720 END-IF
000730 END-READ
000740 INITIALIZE NUMBER-CODE NUMBER-COMMENT
000750 END-PERFORM
With Parrot and a COBOL compiler, you could allow a more modern langauge (say, Rakudo) to be embedded:
000510 MAIN-PARA.
000520 OPEN INPUT IN-FILE
000530 OUTPUT OUT-FILE
000535
000540+Rakudo
my $line_num = 0;
while <C:IN-FILE> {
$line_num += 10;
my $c_area =/^[-*/]/ ?? '' !! ' '; # is this a comment?
print C:OUT_FILE sprintf "%06d$c_area%-100s" => $lin_num, $line;
}
000550
Now this example isn't the greatest (but being able to declare the variables next to where they're used is a huge win), but imagine working with free-form text. I once took a huge bit of COBOL translating CSV data to a fixed-width format and got it down to 10 lines of Perl (with error checking). With this strategy, you could gradually migrate away from COBOL by embedding a modern language directly inside the COBOL instead of keeping the COBOL and wrapping modern tools around it.
I'm surprised I've never seen this approach before. It really shouldn't be too hard. (If anyone wants to pay me a bazillion dollars to do this, let me know
1. If you look carefully at the COBOL and the Perl 6, you have no way of knowing if they're functionally equivalent due to how COBOL variables are declared. In fact, if you don't know COBOL, you might be misled into thinking that the COBOL code can't possibly be correct (look at the variable names), but it is.
From the front page of getcoboljobs.com:
"I've used the service for some weeks now and even though I haven't had an offer from anyone yet, I'll keep using the service. Thanks for providing it." - Michael Mayes, Mainframe Developer Analyst
Yeah, that would make me rush right out and sign up! (Does just getting close to COBOL make you stupid?)
Until the issues are sorted out with blogs.perl.org, I'll still be posting here for a while (probably cross-posting for a while after, too).
Recently I've wanted a simple hash object:
my $object = Hash::Object->new({
id => $some_id,
this => 'that',
name => 'john',
});
print $object->name; # john
The problem is that current implementations I've found have limitations. One uses AUTOLOAD so any method name becomes valid. Another doesn't do that, but it also does nothing else. I'd like to be able to autoinflate an object such that if I call an unknown method, it inflates the hash object into a full-blown object and redispatches to that object, only displaying a "Can't locate object method" error if the "inflated" version of that object doesn't provide the requested method.
my $object = Hash::Object->new(
data => {
id => $some_id,
this => 'that',
name => 'john',
},
inflate => sub { Customer->find({ id => shift->id }) }
);
print $object->name;
# inflates to full Customer object and redispatches method
print $object->fullname;
The reason for this is that we sometimes have very expensive objects, but we only need one or two pieces of data from them. It would be nice to return a "proxy" object, containing the data we probably want, but will transparently work like the real thing if needed.
This is on the CPAN, yes? What's it called?
It's official! We've a new blogging site available for the Perl community. Dave Cross has now made the announcement. I've a blog post over there explaining a few things about it. It's still alpha and there will be bugs, so keep that in mind. That being said, play around and have fun.
At least one person has objected quite strongly to my patch for Test::Builder which adds an implicit done_testing() to subtests with no plan. I was kind of surprised with the vehemence of the discussion, so I want to clear this up.Consider the following test subtests:
subtest 'with plan' => sub {
plan => 2;
is $this, $that, 'this is that';
is $foo, $bar, 'foo is bar';
};
subtest 'without plan' => sub {
is $this, $that, 'this is that';
is $foo, $bar, 'foo is bar';
};
Now imagine that this is a test suite you're currently working on and you keep adding tests to each. It will be annoying to keep updating the plan and sometimes get spurious test failures when your code is fine. The "without plan" subtest is much easier to use. If you want plans in your subtests, fine! Use them. There's nothing stopping you, but if you forget, I've added a safety net. Don't sweat it and have fun.
Unlike with the overall test program, you know exactly when that subtest ends. The plan buys you virtually nothing. In a subtest, instead of an annoyance which actually helps, it's an annoyance which hinders. Heck, for my top level tests, I'm thinking about writing a vim macro which automatically inserts this:
use Test::Most; END { done_testing() }
Plans are almost not needed any more (this isn't entirely true, but for subtests, why bother?). I'm hard-pressed to believe that they now add enough value to overcome the annoyance of using them.
So I've been checking out Google's new "Go" language. There's an interesting example at the Go tutorial. Specifically, the following code is a simple very of "echo".
package main
import (
"os";
"flag";// command line option parser
)
var omitNewLine = flag.Bool("n", false, "don't print final newline");
const (
Space = " ";
Newline = "\n";
)
func main() {
flag.Parse();
s:= "";
for i:= 0; i < flag.NArg(); i++ {
if i > 0 {
s += Space;
}
s += flag.Arg(i);
}
if !*omitNewLine {
s += Newline
}
os.Stdout.WriteString(s);
}
Basically, it checks your leading options for the presence of an "-n" switch and, if present, does not emit a trailing new line. Other than that, it prints the arguments to the program, separated by spaces. It might seem rather verbose, but you have to remember that Google envisions this as a systems language. Note that you don't have to reallocate anything for the "s" variable as Go handles that for you. Trying to dynamically resize strings in C leads to fun bugs, but you don't have to do that here. Go takes care of memory management for you.
You might have noticed the var s string = ""; line. Go doesn't support type inference, but it has a simplified version for variable declaration. In the above, you could omit the "string" keyword, or just use the ":=" operator and declare and assign in one fell swoop:
var s string = "";
var s = ""; // go knows you wanted a string
s:= ""; // same thing
Unlike some dynamic languages, declaration and assignment are clearly separate, making it easy to put proper scoping semantics into the language (though I haven't really checked out how they handle scoping yet) and avoiding silly issues where you think you're assigning to a variable but you've mistyped the name and you're also declaring it.
I'm also intrigued by their lack of a type hierarchy in favor of interfaces. In short, you don't get inheritance. Going with interfaces seems a poor choice because you still have the reimplementation problem, but I'm curious to see what will become of this. Dr. Michele Simionato has an interesting blog entry discussing his initial surprise at being introduced to objects. His background is mathematical in nature and he just didn't understand the need for type hierarchies.
Another interesting bit about Go is that you can't do pointer math wrong. That's because they have pointers, but no pointer math. Kind of like references in Perl, eh? Seems an obvious step.
I'll play more with Go as I have time, but it's beginning to look like there are some interesting ideas for a systems language. I'm curious to know if the lack of full-blown type inference was a deliberate design decision to ensure that the developer can see what's happening at every step of the way, except for the common cases where it's frickin' obvious (such as assigning an int to a variable).
Doing a bit of POD munging and using Pod::Parser::Groffmom with this. The following is OS X specific, but it should be easy to adjust for another system. It automatically opens any POD file as a PDF document with cover page and table of contents:
au! FileType pod :call PodMappings()
function! PodMappings()
noremap <buffer>,r :call PodToPDF()<cr>
endfunction
function! PodToPDF()
let filename = bufname("%")
let postscript = filename . ".ps"
let command = 'perl $(which pod2mom) --cover --toc --ps '
\ . filename
\ . ' && open ' . postscript
echo system(command)
endfunction
After writing some vim code to run your POD code, I realized I needed another snippet to simply tell me if my POD code compiled (without running it). The vim mapping:
vnoremap <silent> <leader>c
:!perl ~/bin/validperl<cr>
Select a region of Perl code, hit ",c" (or whatever your leader is) and if no compilation errors are detected, you'll see no change. Otherwise, they will be added after an "__END__" token. Here's the code for validperl:
#!/usr/bin/env perl
use strict;
use warnings;
use File::Temp 'tempfile';
my $tmpdir = '/var/tmp';
my ( $fh, $snippet ) = tempfile(
'eval_XXXX',
SUFFIX => '.pl',
DIR => $tmpdir,
);
my $code = do { local $/; <STDIN> };
print $fh $code or die "Could not print code to ($snippet): $!";
close $fh or die "Could not close ($snippet): $!";
my $perl = $^X;
print $code;
my $output = qx{ $perl -Ilib -c $snippet 2>&1 };
exit if $output =~ m{^$tmpdir/eval_\w+.pl syntax OK$};
$output =~ s/\n/\n/g;
print " __END__\n $output";
Per a previous blog entry, I've submitted a pull request on github to implement an implicit done_testing() on subtests with no plan. This is due to the following:
subtest 'trim' => sub {
plan tests => 2;
# snip
};
subtest 'escape' => sub {
plan tests => 2;
# snip
};
subtest 'interior sequences' => sub {
plan tests => 6;
# snip
};
It was getting awfully annoying having to maintain plans for all of the subtests when I could clearly distinguish when a subtest was finished. If the pull request is accepted, you can just do this:
subtest 'some subtest' => sub {
isa_ok my $cust = Customer->new({
given => 'John',
family => 'Public' }
), 'Customer';
can_ok $cust, 'given';
is $cust->given, 'John',
can_ok $cust, 'family';
is $cust->family, 'Public';
};
done_testing() will be implicitly called at the end of that (and you can list it explicitly, if you want). This allows you to safely add extra tests to all subtests without worrying about the plan, nor do you have to worry about annoying plan management unless it's really important.
perl.org actually looks modern now! This has been in the works for a while now and, as far as I know, Leo Lapworth was the principle designer. And no, this was not a result of the marketing committee. Just another great volunteer who wanted to make Perl not look dead
There are other nice things to come, too. I'm really looking forward to some of the changes which are occurring in the Perl community.
Update: Apparently, Foxtons is responsible for sponsoring this work. For those outside the UK: Foxtons, from what I understand, is one of the largest estate agents in the UK. Apparently, they got there by being very innovative and investing in a top-notch IT department. An IT department which, not surprisingly, uses a lot of Perl