Easy as E-Mail:
I wrote a mailing list manager today, based on Mail::Audit.
My buddy circle includes people in and out of the area. We send a lot of e-mail back and forth, making plans for weekends and weeknights and passing around interesting tidbits. That usually means creating large address lists based on random criteria -- who's in town, who's not, who might be interested in a subject and who isn't.
A few weeks ago, we were discussing some subject or another, and my brother replied and said, "Can you guys take me off of the cc-list? I'm not interested in this topic." That started my brain a-thinkin'.
My little mailing list manager lets you create new, temporary mailing lists by sending an e-mail with *NEW* in the subject to the proper address. The body has to be a list of e-mail addresses to which the mailing list will apply. It replies with the address of the new list -- just an alphanumeric addition to the main mailing last address. For example, if the list were sml@localhost, a list may be sml+a0f4b918@localhost.
All posts to that address go to everyone on the list. Anyone on the list can unsubscribe by sending an e-mail with *UNSUBSCRIBE* in the subject.
It runs from a .forward file, so it's a bit slow, but it was a whole lot easier than doing this out of procmail or writing a dedicated C program.
It needs a few more features, like limiting the people who can create a mailing list and optionally preventing people not on the list from posting to it. As well, I'm having trouble adding a little "For help, send an e-mail to this address with *HELP* in the subject" disclaimer to the end of the message body. It doesn't seem to stick when I get an arrayref back from $audit->body(). It doesn't do much logging, either.
It does appear to work pretty well, though, and it's 300 lines of code (including blank lines), though that's 2/3 test suite. It's pretty good for a day's work, though, especially since I got a bit of laundry and cleaning done.
On the other hand, it did absolutely nothing for finishing my book (draft due the 17th) or getting Everything 1.0 out the door, or working on my super secret space game. Still, it was pretty fun, and it's one more accomplishment.
Code available here, for the time being. It's not an official module package yet; early adopters and willing patchers only. Be sure to create an aliases file before you run it -- if it doesn't exist, it won't work. Big limitation; probably the first I want to fix.
Last week, the Linux in Boise Club allowed me to present a short talk. Since they found me through my Perl work, I gave a small advocacy talk entitled Why I Like Perl. It went really well, though having several books and miscellaneous pieces of swag to give away always helps.
You might notice that there's not a lot of traditional "advocacy" in the style that turns people off. I was more interested in talking about the advantages of Perl that I enjoy than discussing the bits of other languages I don't enjoy. In retrospect, that worked pretty well -- there were several interesting questions about Parrot, Ruby, and Java.
The Noble Chamois:
Generally found on less steep or severe mountains than Thar, Chamois are never the less capable of traversing steep and difficult terrain at high speed. They have excellent hearing, eyesight and sense of smell.
I also like the Latin name Rupicapra rupicapra.
I'm not a language purist by any means. I consider myself pragmatic, but realize I'm often idealistic. It's hard to reconcile those two ideas, though.
Consider polymorphism. I've most often seen it explained in terms of inheritance. I'm not a big fan of strong typing in general (at least as C and its descendants do it), but mixing polymorphism with the typing system seems... really wrong. Part of the reason Test::MockObject works is because polymorphism isn't limited to objects that share a common ancestor.
The secret is, objects which share a common interface are isomorphic.
Okay, it's not a very well-kept secret. Still, I've seen (and written) too much Perl code that relies on isa(). (Hey, at least I'm way over checking ref() so often!)
I'd like to see that Perl 6 doesn't encourage falling into that trap. At least, I'd like to see that Perl 6 encourages composition and delegation as well as it encourages inheritance. (Having failed to convince Allison completely through mad rhetorical skills, I resorted to code.)
As always, I may be way off track here. Once I figured out the way things really ought to work, though, they made a great deal more sense.
I'm on holiday this week, visiting my parents. Part of being on holiday means not doing my day job. (Those of you who've seen me work or who have seen the output of my work know that this is pretty rare.) I do have most of my work resources with me -- my laptop, my phone, a notepad, and an Internet connection, but this week is devoted to something besides writing and editing.
One of my goals this week was to do more work on Everything. Though the company's long since out of business, it's still viable software. There are still plenty of improvements to make, and I'd like to use it for a couple of projects in the future.
To aid in my goals, I decided to write yet another standalone web server. Being a smart (read lazy) programmer, I used HTTP::Daemon. I could install Apache and mod_perl on my laptop and work through the configuration there, but this allows other people to debug Everything on their laptops and will help with a future goal.
HTTP::Daemon and CGI.pm have never played well together. With the GET request method, it's not difficult to populate %ENV appropriately. It's harder with POSTed parameters. One solution is to tie *STDIN. I've done it before. Another idea is to write your own CGI parser. Good luck. (I've done that too.)
This time, I took a two-pronged approach. Since Gisle had already explained the wonders of headers_only last July (thanks, Gisle!), I didn't have to work around HTTP::Daemon having already read the entire request. First, I modified Everything slightly so as to pass an initializer filehandle to the CGI constructor. Then, I overloaded the iterator (readline, basically) in HTTP::Daemon::ClientConn. With a few lines of code to read a line at a time (respecting buffers and reading from sockets), CGI now gets something it expects.
GET works, POST works, images work (and can be generalized to regular files easily), and cookies work. I'm pretty sure uploads work, but I haven't tested them. All of this in a hundred and thirty lines of readable code: EVServer.
That was a big boost to my mood. As it turns out, though, I was coming down with a nasty, nasty head cold. That explains why I've been wanting to sleep twelve hours a day for the last week.
Warning, tangentially technical.
I'm starting to think there's a tendency towards depression or melancholia that's associated with some of the other traits that make gifted system administrators and programmers. The correlation to musical or linguistic ability is pretty evident. Likewise, there are trends toward problem solving, logical thinking, and medium to strong introversion.
It's tempting to simplify, but I have a hard time picking one of the options. Is this personality type drawn very strongly to this industry? Does the state of the industry magnify latent traits? Is adolescence prolonged in the types of people drawn to computers and technology? Does participating in these activities prolong adolescence?
For example, patching systems that must have perfect uptime during business hours means working after hours or on weekends. The creative energy it takes to solve a thorny programming problem can strike anytime: during a walk, a shower, or in the middle of a dream. Sometimes it takes wrestling with a bit of software or an API for several hours before it starts to make sense. A great deal of free software is written on non-bank hours.
Let's also not forget the sense of play -- online debates and flame wars -- that take up so much time and energy. Granted, I see part of that as normal masculinity (in the C. S. Lewis sense), but there are lots of "debates" that lack some of the simpler social skills.
I bring this up because I worry sometimes about my ability to relate to other people. I suffer from insomnia and the lack of a set schedule takes its toll on me pretty quickly. I've done a lot of travelling in the past couple of years, had a few really big life changes, and live in a land of overcast, rainy winters. I've been really edgy lately, and have lost a lot of motivation.
Granted, worrying if I'm crazy is a pretty good sign that I'm not... but sometimes I care a great deal about what kind of a world I'm helping to build. I want to make a place of peace, a place of learning, a place of healing, and a place that helps people to become better and more complete. It's a huge goal, and the best way I know of is to be a good example.
I don't feel like the best example right now... but I'm trying. Here's my list of goals for the next little while.
Eat more fruit and vegetables. Drink lots of water. Go to bed early. Get up early and go for a walk. Clean out your inbox. Call your parents. Tell the people you love and appreciate one more reason you feel the way you do. Teach someone else to do these things.
If you're like me and haven't been feeling fully-charged lately, play along at home.
Back to Java:
When I returned to computer programming during my senior year of college, I chose Java. The Internet was the Big Thing back then, and applet programming looked pretty interesting. I'd dabbled in C++, but it was a lot more than I wanted back then.
In my subsequent job as a printing and imaging guru (color laser printers), I wrote a couple of in-house apps in Java. This was where and how I really got into Linux -- my brother was a fan and showed me how much easier development was than on a Windows (especially 3.11) machine.
I realized that Java wasn't meeting all of my goals when one of my projects could have been implemented in a 10-line shell script instead of several times that much Java. This was back in the 1.1 days, before the 1.2 beta, and part of my dissatisfaction was also in the awkwardness of AWT. Of course, it was also before the language was retargeted at desktop development, then server-side development, and before Linux had "official" support.
After several years of Perl, I'm brushing up on Java again. Why? Secret work project.
I don't know that I'd do a big project in Java, but it's always good to exercise the ol' computer science brain by exploring some of the Other Ways To Do It.
Having been nominated as a Perl 6 Testing Guy, I spent some time trying to get new Perl 6 tests to work. In the process, I edited some documentation and fixed some bugs in the debugging framework. My tests are still not working, but at least what the documentation promises is now available. Tomorrow, I'll have a better chance of tracking down what's wrong.
The moral of the story: developers cannot rise above the quality of their tools.
With a little more research today, a little more hacking, and a lot of debugging help from my roommate ("wait, is that a void pointer?"), I now have two animated smiley faces bouncing across the screen. Here's the relevant Parrot assembler:new P0, .SDLAnim new P1, .SDLAnim set I0, 0 set P0["filename"], "smile.bmp" set P0["blankfile"], "blank.bmp" set P1["filename"], "smile.bmp" set P1["blankfile"], "blank.bmp" set I1, 320 LOOP: eq I0, 320, LAST inc I0 dec I1 set P0["x"], I0 set P0["y"], I0 set P1["x"], I0 set P1["y"], I1 branch LOOP
I have several enhancements to make before I release the code. First, I need to separate the window creation from the actual image objects. That's easy -- just create another PMC and make a way to associate the images with the screen. I have a pointer reserved just for that purpose. Second, I'd like to figure out how to add a new function to the PMC. Currently, the PMC redraws the image on each coordinate assignment. That's not so good for speed. I think this has something to do with the 'invoke' opcode, but I'm not sure.
Finally, I'd like to figure out how to make my new PMCs work without having to be core PMCs. Yep, I'm running a hacked version of Parrot. If I can figure out how to load a PMC dynamically, I'm good to go.
This has been a good learning experience (and I'm very glad to have gdb at my disposal). It's also been a little frustrating, as my C is rusty when it's not ignorant. Besides that, I have a feeling I'm at the very fringe of Parrot development here.
It's nice to do something no one else has ever done, though, and to get it to work.
New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.
Keep up with the latest Advogato features by reading the Advogato status blog.
If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!