March 22, 2011

Abstraction, indirection, and programming languages

A common mistake programmers seem to make is assuming that abstraction is about putting a layer of indirection (whether through function calls or data structures) into a program. Indirection is one of the more commonly used tools to implement abstractions, but just because there is now an extra layer of function calls in your program doesn't make it more understandable, maintainable, or a better fit to the domain. Those are better (although somewhat subjective) criteria for what makes effective abstractions than layers of indirection.

Another thing programmers like to do is argue about programming languages and the abstractions (over machine language) they provide. Oftentimes you'll hear "language A has feature X" and the refrain "language B doesn't have feature X and is good enough, so feature X isn't important/is harmful." When iterated enough times, it's easy to see that this becomes a sort of reductio ad assembler argument.

Is a sufficiently powerful assembler good enough? So what makes C better than assembler? Why is C special? And what's better than C?

It is productive to be able to both ask and answer the last question, which is why real metaprogramming is an invaluable thing to have.

1 comment:

Warren Wilkinson said...

Indirection is dereferencing pointers. The layers you refer to (like using cffi instead of your lisps native foreign function interface) I'd call a 'wrappers' and/or compatibility layers.

Whats a sufficiently powerful assembler?
An assembly language should have 1:1 correspondence with the underlying machine language, to contrast it with high-level languages (C, Lisp & everything else) where a single statement (* 4 (+ a b)) will expand into many machine codes.

High level languages extend your reach, but they're just a model of your CPU.

To measure a language, you'd probably want to compare how much it speeds development against how suboptimal it forces your solution to be.