Ionrock Dot Org

by Eric Larson

My Weblog

Let Down with PuSH

In the CherryPy IRC channel, I heard about an async framework called Circuits. While I’m still in the midst of getting well versed in Diesel, it occurred to me that I don’t really have a go to idea for what to implement when learning an async framework. In the past I would often write a blogging system to learn a new language, but even that became somewhat tired once I started learning more esoteric languages. The benefits of functional languages and async frameworks is that they can scale. So what is a project that has some obvious scaling issues out of the gate.

What I came up with was PubSubHubBub (PuSH). The idea of PuSH is that you have a server that listens to content producers and potentially multiplies that content to a huge set of subscribers. I don’t know that a PuSH server really needs to scale, but I’d imagine that if one content producer becomes popular, the multiplier for that content’s subscribers seems could balloon easily. With that in mind, after looking at the spec, I’m pretty let down.

I can accept that it uses XML. Google is pretty dedicated to Atom and while I’ve most definitely moved on from building systems with XML, it has its positives. That said, the idea of PuSH is to notify subscribers of changes to content. The content is a resource, so it seems somewhat odd that the protocol requires that the server to do a diff of new content in order to push the changes to the subscribers. Finding the differences in XML, even in a known format like Atom, is very difficult. If there was an understanding that the document should be able to be diff’d by lines and characters, then it wouldn’t really bother me. The system could be built on patches in a way that is similar to the distributed version control systems. But that is not how it works. The PuSH server has to analyze the content, find the differences and send it along to the subscriber.

From an efficiency standpoint, passing around changes is helpful in reducing the payload, but again, differences in XML is difficult. Just as deep object comparisons can be costly, so are finding XML differences. Maybe in practice it is not that hard or a problem, but personally I’d rather not find out. I suppose reducing the payload might be more beneficial than lowering the processing time in terms of providing realtime updates.

What I think makes a better model would be much lighter. First off, the payload would be JSON. It is easier to work with. Second, the most important aspect of the payloads would be the URLs. The goal would be to send a signal instead of a payload. The realtime requirement seems difficult over the web. Sending two medium sized payloads instead of two really small payloads and the content feels much better to me. If the system will have a set number of subscribers that will always be present, then yes, sending the diff’d payload makes sense. But in the case where you are supporting many subscribers, but very few truly require realtime updates, the extra latency would be negligible.

But back to my system idea. The payload to the signal server (I just named it this) would be a URL to the content that changed. The subscribers would be notified via a ping that might use the Location header to signify where to get the update. If the signal server is meant to be used a caching proxy, that could point back to the signal server URL or it could point back to the original source. The subscriber, assuming it needs the data right then and there, can fetch it.

I think the biggest benefit is that the system is so simple. Implementing it on a small level using an intranet makes a ton of sense, while large scale implementations would have the benefit of being able to use something like an nginx plugin or some other simple module written in C that piggybacks a well tested server.

I’m going to try an implement this kind of service as my example application for async/functional languages. It should be easy enough to do without having to get involved in library monotony while still presenting enough problems to make it worthwhile. I’d also hope that in fleshing out the idea, it might present another option in the world push based systems.


Posted Thu Apr 1 07:20:23 2010 by Eric Larson

Refactoring Code

I’ve spent the last few days updating a rather large Javascript code base. There are a couple issues I’d like to solve. The first is settling on one Javascript library, jQuery in this case. It is currently a mix of jQuery and Mochikit, where most of the oldest functionality uses Mochikit and the newer features, jQuery. The second issue is to write a new feature to lazy load some of the data it uses in hopes of making things feel a bit snappier. The big picture though is to get the entire code base up to a more modern version of jQuery so as to take advantage of more plugins and the widget features. Once I get thing decoupled from Mochikit, I’m hoping to do a refactoring to get the code more organized.

Refactoring is a great way to learn a code base. If you force yourself to go over every line and change things, you often break them. This is a good thing because for every bug you create, you are given the opportunity to understand something about the code. It is pretty obvious that you’ll have to see why a certain change broke something. But beyond that you also end up seeing tons of mundane decisions that were made. Little things like whether or not to include braces for one line if/else statements. You see where spaces are added or not added within the context things like function definitions and variable declarations. While a lot of these sorts of things are pretty inconsequential things to pay attention to, they are still important.

The little details help by describing the dialect of the code. Every author will develop a style. There will be a cadence and rhythm to the tone of the text. Refactoring helps you to see the style of the code, which in turn helps in more quickly understanding the code. Knowing an author’s style doesn’t help make the message clearer, but it does make it more palatable. When you start a book you might need to reread small portions to remember something about characters or situations, but by the end, assuming you’re enjoying yourself, reading becomes a guide for your imagination. The characters have faces and feelings. The same goes for code. Refactoring is how you gain the intimate understanding of the ideas and characteristics of the code, no matter how small.

The other thing I’ve realized working on this code is that it is better to refactor earlier. I realize there are time constraints, especially in a startup scenario, but if possible effort should be spent simply organizing the code. For the author, it keeps the code fresh and relevant. For the developers that haven’t looked at the code, they get the benefit of more iterations and potentially seeing the progression of where the code is going. Using this codebase as an example, the initial code was pretty much a large set of functions. As things have progressed in other areas though, jQuery became more pervasive. The most current code adopts jQuery conventions more thoroughly and uses the $.widget tools for making that jQuery interactions more convenient. Refactoring helps to share this story and signifies where new code should be. It also makes it clear that there is still work to do on the code to bring everything to a more unified model.

Unfortunately, as helpful as refactoring can be, it is also somewhat dangerous. There are personal opinions on code quality that are rarely universal. “If it ain’t broke, don’t fix it” really does make sense in the real world of software development. That said, I think the risk is eventually worth it. Testing, which is a good thing, is one great way to prevent breaking things through refactoring. Sometimes refactoring can even be beneficial in finding new bugs or use cases that were not considered before.

The important thing about refactoring is that you get to know the code better. Even if you try and fail, you’ve learned more about the code. The intent might be clearer and you’ve started to see the author’s cadence and style. When learning a code base, failing at refactoring is going to be common, but still helpful. And when you’ve been working on some code for years, refactoring can help reinvigorate a stale codebase.


Posted Sat Apr 3 08:41:07 2010 by Eric Larson

Some Recent jQuery Thoughts

After a rather long stretch I’ve finally got back into programming more with Javascript, which essentially means a whole bunch of jQuery. Unfortunately, I’ve been stuck using a rather old version. The result is that I do miss out on some improvements that would have been helpful. All things considered though, jQuery is a library that I believe has stood the test of time.

The big win with jQuery is the DOM. The DOM sucks. Imagine a world of I/O where you could almost never be sure the file handle you’re reading from is accurate and you can begin to see some problems with the DOM. Thank goodness though for jQuery, as it makes the vast majority of the DOM bearable. Some things I’m specifically a fan of are:

The Data API makes it possible to have a persistent store for keeping data both globally and specific to elements. While the version of jQuery that I was using didn’t have this feature, implementing a temporary version was trivial. This concept is insanely valuable because you have a simple consistent way to store information that is specific to elements. This use case is the critical one since the rest of jQuery all focuses on elements through selectors. There is a single pattern in jQuery that one could compare to a command line interface. If you pass in some HTML, you’ll get an element back. If you pass in a selector, you get an element. If you want to filter a set of elements, grab a subset or do anything else with some set of elements, just use selectors. I’m generalizing here by “selector” to mean anything you pass to the “$” function. Chaining, lastly, is helpful not so much because you can chain calls, but rather because it provides a protocol for performing an operation on one or a set of elements. The newer widget APIs abstract this away, but the patterns have been present forever and while I’ve been confused in the past with them, I’ve come to really appreciate how it works and supports the rest of the framework.

The amazing thing about jQuery is not so much the set of features but rather how it did such a great job nailing the key feature. Web development is all about DOM manipulation and traversing. Almost every feature helps to make one of the stickier problems of web development easier, which is why jQuery is such a successful framework. In Python list comprehensions have become a central optimization alongside dicts. The choice provides a huge bang for your buck and I believe jQuery’s focus on the DOM provides the same returns.

Gushing praises aside, there are some other areas that I’d hope to see some optimizations. As I mentioned before, my recent worked involved removing MochiKit. In going through some of the code it became clear that MochiKit had some rather interesting features. One specifically I appreciated was the partial function. A partial was just an easy way to return partially applied function. Mapping a usage of partial to jQuery was pretty simple. It was just an in-line function. Here is an example:


// Mochikit
$('#foo').click(partial(handle_click, 'bar'));

// jQuery or just not MochiKit
$('#foo').click( function () { handle_click('bar'); });

This doesn’t really reflect why the idea is powerful. In fact, I would argue the latter is clearer in what is happening. The only thing that really interests me about the partial function is that it provides an optimization point. There is a good deal of overhead with using anonymous functions because the machine/vm instructions can’t be saved by the interpreter. The result is that attaching an anonymous function to a control that fires frequently means the interpreter spends a large amount of time re-interpreting that function’s code.

It is pretty common to extensive use of anonymous functions within jQuery code. The common idiom for plugins is that a dict is use for arguments and it can be really easy to just do things like:


$('#foo').my_plugin('run', {
    success: function () {
        // do other things...
    }
});

Honestly, I like the style a lot. But, it would be nice if jQuery had a way to cache that function reference so the interpreter could avoid having to recompile it all the time. I’m not sure how it would be implemented, but it seems like another effective place to optimize. Maybe something like this that further abuses the $ function:


// I can't imagine this would work effectively... but who knows
$('#foo').my_plugin('run', {
    success: $( function () {
        // do other things...
    })
});

// a terrible implementation idea?
if ($.isFunction(selector)) {
    if (!$._cache_methods[selector]) {
        $._cached_methods[stringified(selector)] = selector;
    }
    return $._cache_methods[selector];
}

Another thing MochiKit did that was interesting to me was contexts within the DOM. You could define a block of code (usually using an anonymous function) that let to make sure whatever operations would be performed within that document’s context. The interesting thing about this is that it is another use case that would be helpful within the scope of jQuery code. jQuery does a good job of utilizing “this” within things like the $.each function. Having a way to do $.with and sets what “this” should be within the context of the calling method would be helpful avoiding some of the confusion that can happen using “this”. The data API helps this situation because you have the ability to use that as a context, but at the same time constantly using $('#foo').data('key') means constantly going through the $ function, while saving the value as a new variable might not be an appropriate solution since it may get overwritten or changed.

I could be totally off the mark with my context idea, but I do think providing syntax for caching anonymous functions would be kind of slick. At the same time it doesn’t take much to save the function as a variable, so I can’t imagine I’ll see it. In any case, I think it is a popular way of writing code that if optimized might help improve performance across the board. Or not ;)


Posted Thu Apr 8 02:17:06 2010 by Eric Larson

Ideas for Starting a Record Label

Lately I’ve been thinking about record labels. Not the majors but the small and relatively successful indie labels. There are still a set of popular indies that despite the downturn in the music industry have seemed to thrive. I’m talking about labels like Matador, Merge, Subpop, KRS, etc. By thrive, I mean they manage to be financially viable selling music. Of course, this is an assumption on my part. For all I know they might be simply living on the revenue of past releases. No matter what their books look like, it is clear that they are successful by some measure. I think if someone were to start a label there are definite things to take from the experience of these labels.

A label needs to represent a brand. KRS is a good example here. They started and represented female musicians and embraced accepting a person’s sexual identity. While I don’t know that it has the same vision now, it definitely still maintains its brand. Previously labels that had a good brand had the opportunity to garner a captive audience. Fans were not only fans of certain bands, but they were fans of labels. The label acted as a filter and there were not very many resources for finding music at the time. While this isn’t the case anymore, a label that creates a real brand creates a story. The name of the game is selling music and the way to do that is to let people hear it. The best way to get music heard is through the web and the influence of hundreds of bloggers alongside music websites. The label’s brand then allows this influence to percolate to the bloggers instead of to the people directly. Those that publish need a story and a brand helps to provide that story.

In the indie world, the brand should represent a mission. Again, using KRS as an example, when they started, they had a mission of getting experimental and punk inspired music based partly on gender to those interested. It was definitely a niche, but they in turn helped define a genre through bands like Bikini Kill and Sleater Kinney. They succeeded in their mission. Starting a label means having a mission. It is important to see the mission as something that is not financial. Dischord is another example of a label with a mission. They aimed to raise awareness of the DC music scene. A mission is something fans respect and want to be a part of. It lets a fan know that instead of supporting some money grabbing record label, they are providing great bands a means to put out music.

Lastly, if I were to start a record label, it would be regionally focused. This is partly because I live in Austin, but it also helps to reveal a mission as not only an idea, but a place. It doesn’t have to be a label that resides in a huge city either. Polyvinyl helped represent mid-west indie and (non-eyeliner) emo. They did this from the small college down of Champagne, IL. The idea though is to create a scene. The scene is really nothing more than a community. It doesn’t have to represent a single sound, but it does need to have some sense of originality that identifies it. This identity is critical for everyone involved, the band and the label.

The music industry now requires bands create a brand. It is no longer enough to simply be in a band, just as it is no long enough to put out CDs. You need to have the band and the people surrounding the band representing something larger. This is obviously good for a band, but it is also good for a label because it allows success beyond one artist.

I think Josh Homme or Jack White is a good example of this concept. You have some sense of success that helps to further other projects. The first successes don’t need to be that large as long as they tell a story. A band might have only played a few shows but have been ingrained as someone important within some scene. If that person starts another band or project, the story is clear that amidst the short turbulent yet influential series of events that was the previous band, arose a new and innovative project. It is a really common thread you see today where members quickly work on side projects in between albums. One might consider it a overflow of music, but I’d argue that these musicians realize that they need to constantly produce content and understand that one way to do so is to expand the brand of a single band to that of its members. Animal Collective is a good example of this as well as Neon Indian.

This last aspect of creating the brand is the key aspect for a new label. If a label can help bands establish this brand then I think a label can be successful by associating their own brand with that of the band. The label can be a huge supporter or a bank. If I were to start a label I would do everything I could to help partner with a band to create their personal brand. That means tons of small releases, cheap videos and help with lots of web content. It means making things happen and telling the story. In the past labels were in the position where they would throw things on the wall to see what sticks. That can’t happen anymore. There are too many bands. What should happen is that the label should be similar to a manager in that they make every effort to forward the career of the band. This needs to be the core mission of anyone starting a label. Money is not going to happen by chance, you have to make every band profitable to make money. This also means the bands cannot sit idly by and wait for the big recording budget and tour support. It needs to be a partnership where everyone establishes their brand in order to tell their story and spread the music.

Unfortunately, I don’t have the time to run a label. But if I did, the above would be my priority. I’d have a label of local Austin bands that tell the state of the Austin music scene and establish the Austin sound. It would all encompassing in sound and would make every effort to get the music outside of Austin. You never know, maybe I’ll win the lottery and see what happens!


Posted Fri Apr 9 00:18:14 2010 by Eric Larson

Looping Over Lines in Emacs

I can’t tell you how many times I’ve wanted to take some selection of text and just do some operation over every line. If this desire gets strong enough, I’ll save the text as a file and crack open my ipython shell. Eventually things devolve into writing a short script. In reality none of this is a big deal, but it is obviously something that could be optimized. This is especially true when a vast majority of the operations are simply analyzing a line for bit of information.

As I am an avid Emacs user, there is a pretty serious voice in the front of my head screaming at me to figure out how to do this in my editor of choice. This kind of monotony has in fact driven me to learn how to make keyboard macros and get familiar with Emacs regex. My most recent foray, I realized that I needed to take yet another step and learn some lisp.

The hardest part of figuring things out was simply finding the documentation and learning how to read it. Emacs contains quite an unbelievable amount of help available to the curious user, but unfortunately, I’m pretty bad at finding what I need. That is another skill I’ve been working on brushing up slowly but surely. Once I found some helpful bits, the process was really simple.

Here is the code:


(defun regex-keep-lines ( )
  "Keeps a line in a region if the regex matches"
  (interactive)
  (setq msg (read-string "regex: "))
  (setq num-lines (count-lines (mark) (point)))
  (setq line-direction nil)
  (if ( num-lines 0)
    (if (not (string-match msg (buffer-substring (line-beginning-position) (line-end-position))))
	(kill-line 1))
    (forward-line line-direction)
    (setq num-lines (1- num-lines))))

What this function does is takes in a regex string and if a line doesn’t match, it gets yanked. The lines it goes over are the lines in some selection.

The reason I messed with this in the first place was because I needed to transplant a large number of changesets in mercurial. With a little hg log filtering and reading, I narrowed down the output to the changesets I needed. It would have been pretty easy to just move around in my buffer and clean things up, but curiosity got the best of me and I wrote the above function (as well as a inverse of it, removing lines if they contain the regex).

I’m always pleasantly surprised with how trivial little functions like these end up. It is never very difficult and the output works really well in more cases than I would have expected. For example, I wondered if I would need to settle on having to start the selection at the top and move down since that provides an obvious path for traversing the selection. That ended up being really easy to get around.

I’m sure this sort of thing has been done before. I’m pretty sure there is an “occur” function that effectively does the same sort of thing. That said, it is pleasing to realize that with a little work I can learn to customize my editor while learning a rather innovative language.


Posted Wed Apr 21 00:42:58 2010 by Eric Larson

Describing Logic and Refactoring

I’ve been staring at a rather large snippet of code trying to think of how to refactor things so they can be easier to follow. While my definition of “easy to follow” is going to differ from others, it is clear that when the code is a long set of nested if/else if/else statements, there could be a better way. The problem is I can’t seem to find it!

One of the issues is defining what the logic is really checking against. Here is an example:


if self.context.baseline != current_status and 'foo' in self.new_data:
   next_segment = self.content.next_segment()

This code is totally made up but it hopefully expresses the problem. The test is checking a few different details in order to set some variable that gets used in another if test later. The obvious thing to do is to simplify the value to see if it can be made into something like:


need_segment = (self.context.baseline != current_status and 'foo' in self.new_data)
if need_segment:
   next_segment = self.content.next_segment()

This small change helps make the if statement a little more encapsulated, but really it doesn’t help that much. It would be much nicer to have something like:


if self.need_segment(current_status):
    next_segment = self.content.next_segment()

At this point you might feel there is some progress towards a more understandable set of logic, but in reality you’re simply just masking the massive if/else tree with syntax. There is still a deeply nested tree and as we know, flat is better than nested.

It is in these sorts of situations that I miss XSLT. XSLT had match templates. Haskell has the facility by which you define a set of functions and the signature of the input is used to decide what function to actually call. XSLT used a slightly more specific version of this by using the current context of the document. In both cases you have a situation where you can have some set of state analyzed and a single caller handle what needs to be done. In some ways this is just like a big case statement, but the difference is that the language abstracts it away to being implicit. This is not an easy thing to understand and when I first started using XSLT it was difficult to grok what was really happening. Only after I understood did I really appreciate the elegance of it and saw effectiveness of the technique. My favorite example the identity pattern in XSLT. A really common pattern there was simply copying everything. This was done in a couple lines. You could then add another match template to filter out specific node. Turn on the pretty printing and you had a pretty slick way to filter massive amounts of XML with a startling small amount of code.

In this situation, what I’d like is to have a match on the current state of the application, like in XSLT. Then the nested if/else could be removed for a set of functions. If the state was correct, the function would be applied. Here is an example of what some framework might look like:


@apply([has_page, has_foo])
def set_segment(self, *args, **kw):
    self.ctx['next_segment'] = self.content.find('segment', 1)

def some_handler(self, *args, **kw):
    run_matches(self.context, self.page, self.some_other_necessary_state)

The apply decorator would take a list of functions that would get applied to set of arguments. If they all returned True, then the function gets called. The run_matches function would run through all the apply decorated methods and if none were called would return the changes to the context. The “context” in this case would most likely be something like a dict. In some ways this is similar to WSGI with the main difference being the application of functions is always tested before it happens where in WSGI, the middleware and application have to decide whether or not to call the next method. Unlike functional languages, I would presume the context could change between function calls. In that way you could chain applied functions together by providing “events” or “triggers” in the context dictionary. For example, one applied function might add a ‘foo.bar’ key where another applied function might look for the ‘foo.bar’ and use it’s value to adjust some other value in the context dictionary.

I have no idea if this sort of thing would really make life any easier when dealing with large logic problems. While it is a pain in the neck keeping everything in your head, there is an obvious path to follow in the code. It really does take a lot of concentration, but that doesn’t mean it is a bad thing. Another concern would be efficiency. In theory it would be nice to do the whole process recursively, but in practice it would really need to be done based on looping just because Python couldn’t do the matching process infinitely. The looping would most likely be faster anyway, but there are a lot of extra function calls that add a good deal of overhead when compared to the if/else tree. Of course worrying about it is probably a premature optimization.

The last thing that makes me leery of this kind of system is that someone else would need to read it. Being someone that has spent a non-trivial amount of time with XSLT makes me somewhat unique. I’ve seen first hand how difficult it can be for people to learn and understand the concepts behind it. This might feel more like adding complexity than solving the problem of making the code more clear.

One upside that I should point out is you get more testable code. Even though the methods have side effects, the fact is you would have had to break up your entire logic into relatively composable parts. Each part should be relatively autonomous, which means testing it should be simple. My favorite tests to write have been for some small text parsing or name generating code. You can make a huge list of input and call a function on each to verify things are working as expected. This feels advantageous in that you test the code in isolation easily.

I might give this idea a try, but I’m not holding my breath. One thing I’ve learned is that functional concepts don’t always map easily to non-functional languages. While it seems easy to start using more recursion and functional tools, the reality is languages are designed and optimized for specific use cases. If functional patterns are not part of that design, then you’ll be swimming up hill. At the same time, it seems there should be a more object oriented means of doing a similar approach to defining large bits of logic. If I do find one, I’ll definitely post it here.

UPDATE!

Seeing as there is no point in thinking about these sorts of things without actually trying them I decided to take a go at coming up with a simple system. Talking to Christian a bit about it, he presented the idea of using an iterator for the code in question. That made me realize an iterator would be a good track for making my idea feel a bit more pythonic.

I’m not claiming this is revolutionary or anything, but it seems like a good start for an API or system that is more customized. Ultimately, this kind of system really shouldn’t be too generic just because it would add a lot of extra code. I think the following is small enough and simple enough to be helpful without making a bunch of extra classes/objects that only obfuscate the intent. This is presented with no real world practical usage though, so take it with a huge giant salt lick. Here is the code:


'''trying to make a match template / multi method like pattern for
python'''

class match(object):
    def __init__(self, paths):
        self.paths = paths

    def __get__(self, obj, type=None):
        if obj is None:
            return self
        new_func = self.__get__(obj, type)
        return self.__class__(new_func)

    def wrapper(self, ctx):
        matches = True
        for path in self.paths:
            if callable(path):
                matches = path(ctx)
            elif not path in ctx:
                matches = False
        if matches:
            self.func(ctx)
        return matches

    def __call__(self, f):
        self.func = f
        return self.wrapper

class Applicator(object):

    def __init__(self, funcs, ctx):
        self.funcs = funcs
        self.ctx = ctx

    def apply(self):
        finished = False
        while not finished:
            go_again = False
            for f in self.funcs:
                go_again = f(self.ctx)
            finished = go_again

@match(['input'])
def sums(ctx):
    ctx['sums'] = sum(ctx['input'])

@match(['sums'])
def sum_range(ctx):
    ctx['range'] = range(0, ctx['sums'])

@match(['range'])
def larger_than_ten(ctx):
    if max(ctx['range']) > 10:
        ctx['larger_than_ten'] = True

if __name__ == '__main__':
    ctx = {
        'input': [1,2,3]
    }
    applicator = Applicator([sums, sum_range, larger_than_ten], ctx)
    applicator.apply()
    print ctx

    ctx['input'] = [4,5,6]
    applicator.apply()
    print ctx

Enjoy!


Posted Thu Apr 22 02:59:22 2010 by Eric Larson

Wanderlust Folder Filters

I’ve been using Wanderlust as my email client within Emacs for a while now and it now has become pretty natural. Whenever I go back to using the gmail interface it always feels so slow. While working in Wanderlust is not the fastest thing, I’ve noticed that being able to do things like moving mail messages and working through my inbox is much faster than doing it on the web page. The reason is that in Wanderlust (WL) you simply mark messages and then execute the marks. Obviously, if you have to execute a ton of marks, it takes a while, but that is something you can run and walk away from.

What would be nicer is if I didn’t have to mark so many items. For example, I get error emails for our applications at work. Some are really important but many are just notices of some small user errors or attempts to use incorrect information. There is a ton of mail that comes in from this (even though we’re trying to reduce it) and it can be a pain to manage.

Enter virtual folders!

WL has a concept of virtual folders, which when I read about it, seemed to be about making meta folders that included other folders. This seemed sort of helpful, but I wanted to filter a single folder into more specific messages without actually having to make new folders. I found out this kind of thing is really easy to do!

I’ve been able to now create a filter for the error emails I get from different data centers:


/subject:othapp1|subject:othapp2|!subject:thisapp/%error-emails

I can further filter on date or flags (unread/read) and get a really concise overview without much work at all.

Now, I know this is possible in other email clients and there is nothing revolutionary here. The thing is, most other clients that I’ve tried do a horrible job with this. Evolution, for example, was always extremely slow and would always managed to peak the CPU when using this feature. The benefit is that I’m getting something closer to Gmail without having to actually use Gmail. After all, most labels I use tend to be linked to a filter based on a pretty simple search.

Again, I know none of this is revolutionary. But, when you use alternative tools it can be eye opening. I have tried to be more efficient with email in the past and it never really worked out. The interfaces always caused problems and seemed to need too much attention. I never wanted to “work” on my email. With Wanderlust, it is now a function of my editor and more importantly my overall environment. Checking email is the same as using the terminal, irc or writing code. Finding virtual folders makes things more efficient as well as provides a little excitement that once again your environment has been customized to fit your own needs and not the other way around. Of course, it is kind of a silly quest to always be adjusting your environment, but that is partially why programmers are different from other folks.


Posted Tue Apr 27 17:49:40 2010 by Eric Larson
Created using Python, jQuery and Emacs