So far, what’s biting me in the ass most often when playing with newLISP is the fact that you have to explicitly control what lists get executed when. It’s a logical thing, because the interpreter has no way of knowing what lists are data and what lists are code at any given point in time (which is the point of LISP-y languages), but it’s taking me some effort getting used to that. My old primate brain finds syntactical markings easier to understand (e.g., Python), but that makes hardens the (artificial) barrier between data and code.

Which suggests the question of why the hell should I have to choose? Isn’t there an IDE that, say, rewrites on the fly a LISP list making educated guesses about what will get applied when? E.g., it could render (inc a) as inc(a), and so on. And it could go the other way around, rendering (I use the word deliberately) the parse tree of Python code into a LISP format that would make it easier to think about and write code manipulation code. I read something about such a project a long while ago, although I have yet to track it back — essentially, specific languages are conventions to describe computations, so we should be able to render any particular computation into whatever language is most convenient to the task at hand. Compilers do that, which is nice for the CPU, but my brain spends time dealing with programs, too.

Functional programming is not about lack of side effects. Functional programming is about manipulating code (really, computations/functions/algorithms) instead of, or at least as much as, data. Lack of side effects in functions makes it easier to think about them, but that’s all. Here’s a good example of what thinking functionally looks like.

For a much worse example, here is a quick and brain-dead version of “apply” I just wrote that allows you to do things like


dataparser = [ stripped, split(','), (str, int, capitalized) ]
for line in datafile:
    print apply(dataparser, line)

The important lines are the last three; once you have your basic functions (and leaving aside questions of arity, debugging, types, and such), you shouldn’t need to write scaffolding code in order to compose them in simple ways. In this example, the dataparser = [ stripped, split(','), (str, int, capitalized) ] line simply says “this is the function that applies stripped, then split(‘,’), and then str, int, and capitalized to each of the three elements of the result tuple.” There’s a large number of simple scripts that use this sort of process a lot, and I feel that even if it’s not really that much of an issue to explicitly define the composed function, it compounds over a large number of tasks, and subtly discourages reuse of components and strategies and, most importantly, makes it subtly harder to work over the process.

I’ve been playing with newLISP. So far so good; it’s a relatively simple LISP with more batteries included than the usual. Python is still my main development language, but I’m willing to sink some time into newLISP, to see if I can get properly enlightened. For all of the language’s elegance in most contexts, Python metaprogramming is indeed kludgy.

By the way, I think Ruby is more powerful in this regard, although still not elegant at all. And, as EWD would say, elegance is nothing else but another word for conceptual usability; inelegant tools lead to solutions that cannot be understood by either designers or implementators; lack of understanding leads to undying bugs, unsound algorithms, and multi-decade technological dead-ends.

Been using a tiling window manager (Ion) for less than a day now, already feels more natural than any other window management system I’ve ever used.

It’s sad that we have spent so much time fiddling with useless functionality in software, that taking out flexibility actually improves your productivity.

Hacking the Django admin is both bad form and, at times, a great time saver. As this post shows, subclassing admin.ModelAdmin can get you very far, specially if (unlike in that post), you go beyond save_model and start wrapping and replacing other methods of the base class (e.g., you can wrap form generation to preload useful dynamic values — and why the hell don’t default callables take arguments?). The obvious use case is creatively restricting what admin users can do (yes, I know, not what the admin is there for… or so we are told), but you can do very arbitrarily funny things.

Let’s implement the classic “Maybe” monad, for simple functions.


#!/usr/local/bin/python

class Undefined:
    pass

class Maybe:
    def __init__(self, x=Undefined):
        self.value = x

    def apply(self, f):
        if not self.is_defined:
            return Maybe()
        else:
            return Maybe(f(self.value))

    def __repr__(self):
        if not self.is_defined:
            return '<Undefined>'
        else:
            return repr(self.value)

    @property
    def is_defined(self):
        return not self.value is Undefined

def monad_aware(f):
    def fprime(x):
        return x.apply(f)
    return fprime

if __name__ == '__main__':

    @monad_aware
    def double(x):
        return 2*x

    x = Maybe()
    print double(x)
    assert(not double(x).is_defined)

    x = Maybe(2)
    print double(x)
    assert(double(x).is_defined)
    assert(double(x).value == 4)

Pastebin link

Long story short: When you apply a function to a value, the function controls the process. When you apply a function to a monad, the monad controls the process. That is what allows monads to extend the semantics of functions (e.g., adding side effects, or whatever).

And why not? Why should values be passive? (Note that accessors are a bit like half-monads; but full monads can do whatever the hell they want with functions, way beyond playing with what they see.)