Friday, September 29, 2006

Nightly Rewrites

After literally an all-nighter yesterday Oort 0.2 is now up for grabs. A very sparse example at that page will serve as a stand-in for a proper introduction for a while. After the cleanup mentioned earlier, I can finally toy with some operator overloading sugar (>> for now). There are some tests included now, and then there is the addition of RdfDisplay and JsonDisplay to remove the need for templates to carry out serialization of query results to those formats.

Thursday, September 28, 2006

Within the Outer Space

While closures are very interesting and useful, they may be less of a wise tool when implementing an extendable toolkit. The first version of Oort used them extensively in the oort.rdfview package. My code was quite illegible and obviously a case of failing to be "clever". A more "properly dressed" class-based approach was (as I honestly felt even when I first stepped off the beaten path) evidently much more easy to maintain. Still, state change is less evident in the flat representation of a class, which doesn't give a structural hint of the intended temporal aspect. Using stuff like IllegalStateException doesn't alleviate this much at all (it's a "formally polite design" though). The impression of "loading" a state and bundling a nice nest of code to unfold at each state change is a quite powerful aspect of closures, I guess.

So I thought, let's do that in a somewhat declarative manner.. And thus I (just now) sketched up a way to declare a state change as an hierarchical closure nest which must be unfolded in the proper sequence:

class stateflow(object):
def __init__(self, start_func):
self.start_func = start_func
self.steps = []
self.reset()
def start(self, *args, **kw):
self._started = True
return self.start_func(*args, **kw)
def next(self, step_func):
self.steps.append(step_func)
def __getattr__(self, name):
return self.__dict__.get(name) or self._get_next(name)
def _get_next(self, name):
if not self._started:
raise BadStateError("Not started.")
step_func = self.steps[self._at_step]
if step_func.__name__ != name:
raise BadStateError("Must call %s before %s."
% (step_func.__name__, name))
self._at_step += 1
return step_func
def reset(self):
self._started = False
self._at_step = 0

class BadStateError(LookupError):
pass

#== Let's test it ==

@stateflow
def query(database, subject):
@query.next
def with_query_data(predicate):
@query.next
def run_query(context):
return database[subject][predicate] % context

database = {'s': {'p': "value in %s"}}

query.start(database, 's')
query.with_query_data('p')
assert query.run_query("context") == "value in context"

query.reset()
query.start(database, 's')
try:
query.run_query("context")
except BadStateError, mess:
assert str(mess) == "Must call with_query_data before run_query."
else:
assert False

query.reset()
try:
query.run_query("context")
except BadStateError, mess:
assert str(mess) == "Not started."
else:
assert False

Pretty interesting, I guess. Won't be putting that into my toolkit just yet though (if ever). So, dear closures, it was a nice experience, but I just have to let some of you go. Till next time, keep it simple!

(Oort 0.2 is on the way, by the by. I oort to create an introductory tutorial for it.. And a logo. Yes yes, of course; without a logo, what kind of a toolkit would it be?)

Wednesday, September 27, 2006

Programming Languages for Cineasts

  • C: Robert Duvall
  • C++: Jack Nicholson
  • Perl: Chuck Norris
  • Python: David Hasselhoff
  • Ruby: Jackie Chan
  • Java: Richard Gere
  • C#: Patrick Swayze
This list may be completely revised without prior notice.

.. I really need to sleep more at night. Sorry 'bout this. Or in the words of the nascent Darth Vader: Noooooooooo...

Whisky Pasting Space Clouds

My spirits somewhat rekindled by this nice presentation about WSGI, Paste and Pylons, I finally undertook the actually easy task of switching from CherryPy to a pure Paste-utilizing WSGI. Why? What? Last things first: Oort, as previously mentioned, is a little web toolkit for building RDF-driven web apps. It has a very specific scope, and thus the why-answer is: because it's better suited as a small WSGI-thing composable with whatever else you want to build legac* ehrm, regular web apps with. So go ahead and publish your RDF Graphs (I'm sure you have an abundance of them) with Oort, right among your other object branches in CherryPy, or mod_python, or among the URLs of a Pylons app, or whatever.

WSGI is a really neat thing, being so simple (to use) as it is. Same goes for RDF, in my opinion, but that's another rant. (A quite reoccurring one at that, if you happen to know me..)

Oh, where is Oort, you may ask? I finally put it up for display at the CheeseShop tonight. Like so many other things, it's alpha software and all. It is used for real work though. Next thing could be a little how-to (and why not a nice logo..).

Tuesday, September 26, 2006

Logix

I get a fuzzy feeling (with a dash of vertigo) when I look at Logix. For something managing to utterly violate many of the finer points of restriction that make Python programming resistant to cases of obfuscated cleverness, Logix is one of the coolest things I've seen lately (I guess I'm a year late to the party though). I've been doing some Ruby inquiries recently, to capture the finer things and evaluating my potential Python bias (while interesting, I see no reason to abandon my current favorite; still: YAR (Yet Another Rant)). I've also taken some time to look closer at Haskell, with some fun effects on my sleep cycle.

Although I might sometimes ponder if the Python syntax could be tweaked some to great effect, I often realise that I'm picking daisies instead of harvesting for the winter. Python is brutally straight-forward and effective as it is. Still, Logix is what I obviously overlooked when I saw Pluvo earlier this year and felt the lure of language experiments. Logix may be in a state of flux, but I really wish that it would prosper as somewhat of a hyper-intelligent, mind-boggling but brutally powerful layer on top of Python. If nothing else, it would give me and everyone else believing that this or that could be a better syntax for the job an easy way to test it. And possibly discover that it was a better syntax for a job, but perhaps not the right job. Still, Logix can definitely make declarative programming and design of DSLs a breeze. Or perhaps a tornado.

For a concise example, see this excellent article.

Wednesday, September 13, 2006

Think Outside The Box

I just realized it. The reason for the increasing popularity of dynamic languages may just be:

  • Some years ago, many developers sat in front of humongous 19" CRTs and about 1600x1200 or whatnot.

  • Nowadays, most of us sit with sleek notebooks with quite the lesser screen size and resolution.


Thus, it's much more of an annoyance that we have to scroll through rows and rows of boilerplate and wrapped lines of type declaration harnessing. It simply has to go.

(Nevermind productivity or the fact that these new tiny things pack enough CPU power to make DNA sequence processing a BLAST (pardon the pun).)

The Tenfold Error in Language Choice

Sometimes I just know I must have missed some convienience method..
static String makeEncodedValue(String value) {
try {
MessageDigest digester =
MessageDigest.getInstance("MD5");
byte[] digest = digester.digest(
value.getBytes());

StringBuffer buf = new StringBuffer();
for (int i=0; i < digest.length; i++) {
int nValue = ((int) digest[i]) & 0xFF;
buf.append(Integer.toHexString(nValue));
}
return buf.toString();
} catch (NoSuchAlgorithmException e) {
// ... must.. do.. error.. recovery..
}
return value;
}

Oh..
import md5

def makeEncodedValue(value):
return md5.md5(value).hexdigest()

Time for coffee.

Tuesday, September 05, 2006

All About the Package

I'm currently in the process of cleaning up and packaging Oort - a Python-based thingy used for making web apps driven by RDF graphs (there will be more where that comes from, rest assured).

Following is my little list of good starters when doing Python package development.

Most obvious: take a good look at setuptools (especially the concepts and usage of eggs, easy_install and pypi).

For testing, Nose is my one-stop-shop for now. Avoids the articificality of the xUnit-API; uses automatic discovery (with filtering); finds doctests if desired; uses coverage.py if available.

It's probably always wise to follow the practises of the most modern and well-renowned packages. I think Paste is a good example of this.

The Dawn at Dusk

Really, getting my act together and start emitting random thoughts has been on my agenda for far too many years now. Perhaps I'll just do this here instead. We'll see.