Esoteric Programming Languages
led_belly writes: "I came across this interesting page from the #alt.linux IRC chat room topic (irc.keystreams.com). It is an interesting read for all those who have ever been baffled by why/how some people do things. The Yahoo! Webring listing of similar topics is here."
As an intellectual challenge, rewrite DeCSS in any of these languages. Feel free to share your results with us.
To get something done, a committee should consist of no more than three persons, two of them absent.
A mere 371 bits suffice to encode a universal combinator equivalent to ...(a) universal Turing machine:
11100110010100110010110011000010001110010101110010 110 0 100 1 100 1 100 0 010 0 110 0 001
0110010100110010110010100110010110010101110011001
0110111001100110011000101101011010010101110010101
1011001100101001100001000111001100101001001010010
0111000101110011000010001101110011001010011001011
1001100101100101011100110010100011011100110001011
0011011100110010100110011001010011000010001100011
Dan Brumleve has a written a combinator interpreter in Perl that may be capable of evaluating Tromp's strange machine.
Seastead this.
I find it odd how every syntax I have ever seen in a computer language looks ugly and stupid to me, until I become fluent in it, then I won't abide any change after.
Letter To Iran
I mean really, in Haskell, "factorial" looks like this:
fact 0 = 1
fact n = n * fact (n - 1)
Write that, and "fact 20" works just fine:
Examples> fact 20
2432902008176640000
Examples>
However, implementing Haskell (or Self) on a von Neumann architecture is non-trivial. Implementing an efficient compiler or interpreter is tres difficil. People get Ph. D. dissertations for that sort of thing. For someone deeply used to C, Haskell and Self are perverse.
To wit:
- In Haskell, nothing changes. Ever. State change is handled by creating a new state from the old one. Semantically clean, but about as far from C as you can get.
- In Self, anything can change at any time. Yes, Virginia, you can redefine "if-then" whenever you feel like it. Change the inheritance hierarchy? No problem! Whoops! I made a cycle in the inheritance hierarchy! No problem! (yes, A can inherit from B and B can inherit from A). Think of C without the reliability that any particular operation (function call, operator, whatever) maps to the same place more than once. This kind of thing gives most C-family compilers hives. It used to be that C++ was perceived as significantly slower than C - I don't see anyone complaining about it anymore, but Haskell and Self are more extreme examples. C++ made it easy to use jump tables. Haskell makes it easy to use recursion, lazy evaluation, and a bunch of other things. Self makes it easy to use dynamic inheritance, multiple inheritance, even cyclical inheritance.
What is most impressive about these kinds of languages is that you can build efficient implementations, without the compromises to the semantics that C (or its derivatives) entails. The fastest FFT library out there is in C, but the C code itself was generated by Haskell code (code that came up with some original optimizations along the way). The Self compiler is the root technology for Java JIT compilers (when Sun killed the Self project, all the compiler people went to work on "virtual machine" compilers). Self was able to hit 50% of the speed of optimized C while maintaining:- Full source-level debugging
- Garbage collection
- Checks for stack and integer overflow
- and the ability to change the "class" of any object at any time (I put class in quotes because Self is an object-oriented language without classes - part of the super-simple semantics)..
In short, there isn't anything wrong with clean linguistic semantics. But essentially every computer sold today is built around the von Neumann architecture, and non-von-Neumann semantics (like that used by Self and Haskell) are non-trivial to implement.-----
Klactovedestene!
APL was a lot more common than you might think. It was the first language to treat matrices as first-class entities, and so was popular for a time among the mathematics set. It was amazingly fast, in part due to its innovative use of lazy evaluation (e.g. if you only wanted a single column of a large matrix, it wouldn't bother computing the rest of it).
A bit of APL lore: Back in the late 1970's, Ken Thompson (one of Unix's creators) spent a summer at UC Berkeley (an event that was rather influential in BSD's development). Just for fun, he wrote an entire APL interpreter -- in one weekend. It was a real pain to work with since it used two-letter codes instead of the APL character set, but other than some of the quad functions (various OS primitives and so on) it was complete.
It's one of the more spectacular feats of programming I've ever heard of.