I'm kind of a collector of machine languages. Here are some I've
done enough work in to get the general idea:
- I'm not sure it's a language per se, but the first program I
ever wrote was on my dad's Texas Instruments
TI-59 calculator, in 1978, I think, and it was:
2nd Lbl A + 1 = 2nd Pause 2nd Prt GTO 2 R/S . It
counts continuously starting from the value currently in the
accumulator. Actually Dad showed me this program, but I later
reconstructed it myself from memory. I then spent the next year or
so picking apart all the code in the TI-59 basic library module,
and all the code in the TI-59 programmer's manual. What fun.
- What I learned: the low-level details, and for quite a while
that's all I knew. But these machines were architecturally very
primitive, so moving along to real CPUs later was a very different
experience.
- BASIC: it was immensely
liberating to move from the TI-59 to the TRS-80's BASIC
interpreter. Hard not to get nostalgic.
- TRS-80 Model 1 Level 1: what a joke.
- Borland TurboBASIC: I wrote a really fast
implementation of John Conway's cellular-automata game, "Life".
- MS Visual Basic: nice for slapping together
some code to test a COM component. Anything
over a couple hundred lines gets pretty
unweildy, though.
- What I learned: how to structure code for maintainability.
Also that if you look at the same code for 10 hours a day for ten days
straight, you will dream about it.
- C: It's simple, and good to
have when you need it. I've written and maintained gobs of C code,
though my hard-core C days are far in the past. I do read Linux
kernel code from time to time.
- What I learned:
Be careful with pointers. Just because a language isn't assembly,
doesn't mean it's not, well, assembly.
- FORTRAN: I've written an
assortment of fairly trivial FORTRAN programs. It's been several
years since I wrote or looked at any FORTRAN code, and I don't
really miss it. I can puzzle out a FORTRAN program given time.
- What I learned:
I can learn a language in two days if I have to.
- C++: A lot of the
professional work I do these days is in C++. I've written some
fairly large applications in it. I've also taken an expert system
originally written in a proprietary AI shell language and
re-implemented it in C++. (Heh... seemed like a good idea at the
time...) I'm not particularly in love with C++ as a language, but
I'm comfortable enough with it to write correct, well-structured
code, and to understand pretty much anything written by someone
else (as long as it doesn't involve too many games with template
instantiation). It's a living.
- What I learned:
Object orientation. This was huge, although I don't think OO is
the eschaton of architectural paradigms.
At the time I learned C++ I was building an app that talked to
a number of different kinds of embedded devices via serial lines,
and all of them had different on-the-wire protocols to support.
When I realized that I could dynamically load a DLL under OS/2 (this
was before COM, incidentally),
call an entry point by name, and have that entry point return an
instance of a class derived from an abstract base class, my life
changed hugely for the better: all the device-specific support
became dynamically
loaded plug-ins, the core of the app became a relatively
changeless thing of abstract beauty, and we could deploy support
for new devices without having to update the core. This was an
absolutely pivotal experience in my development as a designer.
- Tcl is awesome for small to
medium-sized programming projects that don't require deadly
performance. I've written a lot of Tcl/Tk code, and I
like it - especially for banging together a quick GUI to drive
some underlying piece of software. My favorite Tcl project so far
was a generic multidrop device simulator: it listens on a serial
port, accepts commands, and returns responses based on a plug-in
device definition (also written in Tcl, of course); and it can
simulate an arbitrary number of devices, distinguished by a drop
number in each command packet. It can also, without any work by
the device-definition programmer, present a GUI that allows the
internal state of each simulated device to be viewed and
edited. This thing took me less than a week to write, including a
device definition for a particular kind of thingamajig I was
interested in at the time.
- What I learned:
Dynamic weak typing makes things easier, compared to the manifest
static typing in languages like C++. You can probably find Usenet
posts by me back in the early 1990s, trying to convince people how
necessary static typing is (without any real argument to back it
up, since I was just a baby developer, and all I knew was that
C++ was better than BASIC). Tcl cured me of that. It was arguably
also the first Lisp-like language I got really good at.
- Lisp: (It's getting hard
to order these...) I learned Lisp originally as an undergraduate,
just because I wanted to move beyond BASIC. But at the time the
only freeware Lisp implementation I had access to was not particularly
exciting. I did some exercises from an on-line tuturial, said "WTF
is the deal with all these parens?", and forgot about it for years.
Later, I learned the
rudiments of Common Lisp (CLTL1) as a requirement for a graduate
degree in AI while at the University of Georgia, and wrote some
fairly trivial AI exercises -- maze-solvers and so forth.
After ten years
away from Lisp, I'm starting to get interested in it again. The
material on Paul Graham's
site was mostly what inspired this renewed interest.
I've got a copy of Peter Norvig's Paradigms of AI Programming
that I'm working through slowly (amid many other ongoing reading/
learning projects).
- What I am still learning:
Lisp is the Platonic Reality behind essentially all high-level languages.
What Lisp is, is a convenient notation for ASTs that can be directly
manipulated (via macros, or just by building lists and eval-ing them).
Syntax has begun to irritate me.
- Forth: What a cool
language! It's nearly as hard to read Forth code as Perl code,
until you get used to it, but the utter simplicity and elegance of
the language make it worth significant study.
If you want an assembly language that is Lispy, Forth is the language
for you. It is exactly as dynamic as Lisp -- you have constant access
to the compiler, and lisp-style macros that allow you to write Forth
code that writes Forth code are a standard facility. (Eg [postpone].)
- What I learned:
Simplicity is incredibly important. Everything is easier
when simplicity is a priority.
I've written a
Forth(like) compiler/interpreter/runtime environment called
JKForth. I haven't tried booting
it in a long while, although I vaguely recall I got it to boot
on a VirtualBox instance in the past year or so.
The hardest part of getting JKForth working was the bootloader;
once that was done, the threaded Forth kernel was a cakewalk.
This is partly because of Forth's simple and elegant structure, and
partly because Leo Brodie is really good at explaining it in Starting Forth
- HP-48: The HP-48
calculator's programming language is a little like Forth, and a
little like Lisp... In fact, apparently HP refers to it as
"Reverse Polish Lisp". I have a
48G that I like to play with; I taught it to display IFS
fractals. Mostly it does checkbook-balancing... Back in college
I had an HP-28, which I liked better than the -48 because its
keyboard was easier to use. The -28 had a complete alpha keyboard
along side the numeric/scientific one, in a clamshell case. I'm
not sure why HP decided to go with a single, extremely dense
keyboard for the -48 series.
- What I learned:
Small can be really beautiful.
- Java: I mostly write Java
code these days, professionally. Prior to version 1.5 (which
introduced generics and autoboxing), Java <impression personality=Jon Stewart>
suhuuucked </impression>, but now I
kind of enjoy it. I wish they'd make reflection easier to use.
- What I learned:
Marketing trumps technical advantage.
- Perl: I used to dislike Perl
quite strongly. But a couple of years ago I had a brief contract to write
some Perl code to decode network traffic, and I got to like it. A little bit,
at least. Of course, my Perl code is beautifully structured and
a joy to read, while everyone else's...
- What I learned:
Once you find a language's underlying Lisp, things get easier.
- Scheme In order to pump up
this list, I'm also listing Scheme as a separate language. My
main motivation for this is continuations, which don't exist as a
first-class concept in CL (although as I understand it the CL
exception system is based on a similar idea).
- What I learned:
How to use continuations.
I wrote a simple
threading library with Scheme continuations, and it worked, which
convinced me I basically understood what continuations were all
about. I never used it in a serious project, though.
- Assembly
- Motorola 6811
- Intel x86 (where x mostly == 80)
The Forth(like) language mentioned above is
implemented in 8086 assembly, and I've
had to pick up a fair bit of 32-bit x86
assembly in order to really understand the
Linux kernel. I've also
goofed around with some trivial robotics
projects using the Miniboard, a single-board
computer about the size of a wallet, based
on the 6811.
- What I learned:
I enjoy working at the CPU level. It brings me back to the TI-58/59 days.
- JavaScript: a little while
back I bought a book called "Visual JavaScript", which was truly
horrid. But I picked up enough of the language (and dynamic HTML)
from the book and various web sites to be able to write a fun little
music box page.
- What I learned:
Prototype-based OO. Also, Javascript is essentially Lisp in Java's clothes,
so it is drastically more fun than most C-descended languages.
- Prolog: A language I really
enjoy. If you are just starting out learning programming, Prolog
might be a good one to investigate before you acquire too many
preconceptions about what programming languages have to be
like. It takes a unique perspective to write Prolog well, but once
you "get it" it's possible to write incredibly clear, simple, and
elegant code, and get fairly spectacular results. What you get
with Prolog is an inference engine and the tools to build a
declarative model of your problem domain, about which the
inference engine will reason; the trick lies in learning how best
to declare your domain knowledge. If you try to write procedural
code in Prolog, you're doomed. I wrote Prolog
professionally for a year - my very first year as a paid
programmer - until the company I was working for went
bankrupt. (I'm fairly certain I had nothing to do with that, by
the way.)
- SQL: Another more-or-less
declarative language (you tell the machine what you want done, not
how to do it). You can't really go very far in the software
industry without meeting up with an RDBMS, so everyone needs to
know some SQL. It's not bad as query languages go, I s'pose. As a
sometime Oracle, Sybase, and DB/2 administrator, I use it nearly
every day without noticing much, so I guess it's doing its job
well.
- What I learned:
I really don't like administering DB servers.
- HTML: It's not really a
language, exactly, but if it was, it would be declarative. Sort
of. Well, hard to say these days...
- What I learned:
It's not always easy to separate content from presentation.
- Bourne Shell: I write Bash
scripts occasionally for various purposes. I have to re-read the
man page every time, though.
- What I learned:
The unix way: tiny utilities + pipelines == some seriously powerful stuff.
- Pascal: I had to learn Pascal
as an AI graduate student in order to satisfy some silly CS
prerequisite.
- What I learned:
I don't believe I've written ten lines of Pascal
code since taking the final exam, but I got an A, so I must have
learned something.
- Modula 2: I was hired by a
firm that built insurance claim processing software to help them
transition to C++ from Modula 2. (Exactly why they wanted to do
this was not obvious.) So I spent six months maintaining the
Modula 2 code while figuring out how to re-architect the whole
shebang in C++.
- What I learned:
The rudiments of Modula 2, along with
the following very important fact: the insurance industry is just
too dull for words.
- Python: Python is my preferred
language at present. I've used it for a lot of small-to-medium apps, such as
an ASN.1-to-XML translator and an SNMP management UI, and I really enjoy working with it. Most
especially, the dynamicity of the language, embodied in such features
as the complete lack of variable declarations, makes it an excellent tool
for exploratory programming and rapid prototyping. It's sort of
Lisp with better syntax and a decent standard library. But without
macros.
- What I learned:
Syntactic whitespace good! Python has no fundamental features that I wasn't
already familiar with, but it's an extremely well-designed language. So
I suppose the lesson is that language design is important.
- XML: OK. I just have to rant a little bit here.
XML is probably the wrong answer. You almost certainly don't need it, unless
what you're doing is marking up some existing body of textual data so that you
can work with it in a more structured way. XML should not be the first tool you reach for
if you need to build a structured data store from scratch. It is really just a pain in
the ass.
I know, of course, because I made this mistake. I expressed a large amount of configuration
data in XML for a mission-critical app. Result: totally unmaintainable mess of XML, combined
with wretched performance of the application.
When I finally realized my mistake, I rewrote the whole thing to use a simple line-oriented
configuration format. The volume of configuration data shrank by something like 30% (partly
due to ditching XML, and partly due to the fact that on the second iteration, I Did Some Things
Right that I had previously been Doing Wrong. I found some new things to Do Wrong.) The
app's performance approximately quadrupled. And with my little-language toolset that I
mentioned above, writing a parser for the config data turned out to be easier than
dealing with XML SAX or DOM APIs. And oh yeah, it used about 25% less memory.
- What I learned:
See above.
- Haskell: a purely functional
language: everything is an expression returning a value, and there
are no side-effects. I've now written a couple hundred lines of Haskell code,
and I'm starting to really enjoy it. Since I already know Prolog well,
picking up Haskell hasn't been too difficult, even though my brain
has been polluted with the likes of Java. I still don't fully grok
monads (and in fact I haven't actually written any nontrivial I/O
code yet - I do all my work in the HUGS
or GHCi REPL).
- What I learned:
Algebraic typing is lovely. It gets out of the way, unlike manifest typing;
but it also really helps to structure code cleanly and catch bugs at compile time.
I am still very much a baby at Haskell, though, so my "insight" is not
particulary meaningful.