Tuesday, April 20, 2010

Using J : Part I - A Super Calculator

J is a VERY complex language, which takes a lot of effort to master, but doing simple things with it is easy. In this post I will demonstrate how it can be used as an advanced calculator.

If you type '2+2' into J you will get the expected result of '4'.

Similarly '3-2'' will give the expended '1', '2*3' yields the expected '6'.

J does not use '/' for division, instead it uses '%'. This is the first of many idiosyncrasies. So '6%2' yields '3'.

The next idiosyncrasy in J is the order that operators are evaluated in. As long as you only perform one operation per line there is no question about order, but is you put multiple operations together in a single line than the order of evaluation can be important. What is '5-3-2'? Is it 4 or is it 0? In J it is 4, because J works from right to left when evaluating. This means that '5*2+3' is 25, not 13 as you might expect. If you want any evaluation order other than strict right to left you must use parenthesis. '(5-3)-2' is 0 and '(5*2)+3' is 13.

To see the next idiosyncrasy, enter '2-3'. Instead of the expected '-1', you get '_1'. The reason for this is that unlike most languages, J does not use the same notation to indicate the unary operator (called a 'monadic verb' in J) additive inverse and a negative number. In J '-1' is a verb ('-') followed by a noun ('1') the result of this computation is '_1', which is just a noun.

Which brings me to the subject of the representation of numbers.

The simplest way to represent a floating point number is with a decimal point like this '34.87', with the one caveat that a number can not start with a '.', so you must include the leading 0 if the number is between 1 and _1. Another common way to represent is in exponential form. In J exponential form is written as two numbers separated with an 'e' no spaces allowed. The second number must be an integer. The result is the first number multiplied by 10 raised to the power of the second number. So '1.234e3' is the same as 1234.

Many programming languages let you express integers in bases other than ten, must often only bases 2, 8 & 16. J lets you express floating point numbers in any base (however I have not figured out how to express digits representing values greater than z which represents 35). To express a number in a base other than 10 first give the base then 'b' then the number represented in that base. It is interesting to note that the base does not need to be an integer. I have not yet though of any use for this feature, but you may be able to.

Two other unusual representations are supported by J. Exponential notation in bases Pi and e, 1p1 is Pi, 2p1 is 2*Pi, 1p2 is Pi squared, 2p2 is twice Pi Squared, etc. Similarly 1x1 is e (the base of natural logarithms, 2.71828 . . .) , 2x1 is 2e, 1x2 is e squared, etc.

Two other important numbers you might find useful are '_' and '__' which are the values the limit of 1 % x as x approaches 0 and the value of the limit of _1%x as x approaches 0. It is interesting to note that J believes that '0%0' is '0'.

Sometime you want more precision that you can get with floating point. If I enter the integer 1 J will assume I mean a floating point number very close to the integer 1. If I want the integer 1 I type '1x' for 1 exact. Now type '1x % 2' and see the results. '1r2' is a rational number with a numerator of 1 and a denominator of 2. 2r3 is two thirds.

J also supports complex numbers which are represented by the real and imaginary parts separated by a lowercase j. For example 2 + 4i is written as '2j4'.

You can give something an alias. For example, if you would rather use 'Pi' than '1p1' you could type 'Pi =: 1p1' and then any time you type 'Pi" it will be the same as if you had typed '1p1'. Any thing can be given an alias. If you type 'Plus =: +' then you can type '2 Plus 2' to get 4.

As you have seen '-' can be used as either a binary operator (called a 'dyadic verb' in J) is in '3-2' or as a unary operator (called a 'monadic verb' in J) as in '-2'. This is fairly common, But in J nearly all verbs have both a monodic and dyadic form.

The verb '%' has the dyadic form 'divide' and the monadic form 'reciprocal' so '%2' yields '0.5' and '%2x' yields '1r2'.

The verb '*' has the dyadic form 'times' and the monadic for 'signum' which returns '1' if the argument is positive, '_1' if it is negative and '0' if it is '0'.

The verb '+' has the dyadic form 'plus' and the monadic form 'conjugate'. Conjugating leave it unchanged, But when you conjugate a complex number it changes the sign of the imaginary component.

The square root operator (monadic verb) is '%:'. The dyadic form of %: is 'Root'. '3 %: 8' yields the third root of 8, or 2. One thing that does confuse me is how it choses which branch of the root to take. '3 %: _8' yields '1j1.73205' not '_2' as I would expect.

The power operator is '^'. In its dyadic form it raised its first operand to the power of its second operand. So '2^3' yields 8. In it monadic form it is called 'Exponential' and it raises Euler's number (the base of natural logarithms, e) to the given power.

The log operator is '^.' The Monadic form yield the natural log. The dyadic form yields the log given the bases. To get the common log of 100 us '10 ^. 100'. You can define a monadic verb to take the common log 'log =: 10&^.'. The '&' binds the left operand of 10 to the operator '^.'.

The residue operator is '|'. Residue is like mod, except that the order of the operand is reversed. If want the traditional mod operator it is easy to define 'mod =: |~'. Now you can use 'mod' like an any built in operator, '187 mod 10' yields '7', just as you would expect. The adverb '~' commutes the operands to the verb it modifies. The dyadic form of '|' is the magnitude, or the distance from zero, '|2' yields 2, as does '|_2', '|3j4' yields 5.

The factorial operator is '!', its dyadic form is called 'out of' or 'combinations', 'x!y' is '(!y)%(!x)*(!y-x)'.

Any good calculator needs to provide trigonometric functions. J does this in an unusual manner. The operator 'o.' is used. In it monadic form it simply multiplies a value by Pi. The dyadic form provides the trigonometric functions: '1o.' is the sine function; '_1o.' is the arcsine function; '2o.' and '_2o.' are cos and arccos respectively; '3o.' & '_3o.' are tan & arctan. The hyperbolic function are similar using 5, 6 & 7 for sinh, cosh and tanh. You may want to define the monadic following verbs:

  • sin=:1&o.
  • asin=:_1&o.
  • cos=:2&o.
  • acos=:_2&o.
  • tan=:3&o.
  • atan=:_3&o.
  • sinh=:5&o.
  • asinh=:_5&o.
  • cosh=:6&o.
  • acosh=:_6&o.
  • tanh=:7&o.
  • atanh=:_7&o.
the '&' operator binds an operand to an operator. I hope to discuss it in detail in a future post. Of course this assumes the angle is measured in radians. If you have it in degrees you need to multiply it by (1p1%180).

This gives you a good start, but it has not really scratched the suffice of the true power of J. Arrays are the heart of J, I hope to write about them soon. If you really want to get the full power out of J you will need to grok tacit programming, but you can go far without it.

Labels: , ,

Sunday, December 06, 2009

New Software Documentation Tool

Yesterday I published the first beta release of a software documentation tool I developed which I named Code Extractor. It is inspired by ProgDoc but is much simpler. ProgDoc is designed to work with LaTeX and performs source highlighting. This also means it needs to know the source language it is dealing with.

Code Extractor, on the other hand, is designed to work with Asciidoc or Quickbook, both of which can do their own source code highlighting, so there is no need for Code Extractor to do it.

When I registered the project at BerliOS I made a typo and skipped the 'r', so the project is http://developer.berlios.de/projects/codeextactor/. I hope you find it useful.

Labels:

Wednesday, October 28, 2009

An Interview Question

At a recent job interview I was asked to write a program to solve the following problem:

You have a sorted array of integer values, you need to generated a sorted array of the results of the results obtained when there values are plugged into the quadratic equation ax^2 + bx + c.

My first thought was that this was a problem best suited to the J programming language. Unfortunately I did not have my handy dandy J dictionary with me, and I do not have it memorized, so I had to wait until I got home to write:

fa =: monad : '/:~(c,b,a)p.y'

A J expert would make this tacit, and therefor shorter, but I'm not that good yet.

Using C++ with the Boost Lambda Library I would write:

std::Vector& fa(std::Vector& x)
{
    std::transform(x.begin(), x.end(), x.begin(), a*_1*_1 + b*_1 + c);
    std::sort(x.begin(),x.end());
    return x;
}

This does all the work in place so it only consumes memory for one array.

It can be made more efficient by taking advantage of the fact that the input array is sorted, so sorting the output array can be done in linear time, but that is left as an exercise for the reader.

I should look into how to do it in Ocaml, Erlang and Oz. But I do not think any of them will be as succinct as J or as efficient as C++. If the polynomial were of higher order it might be worth pursuing an Erlang solution that distributed the evaluation of the polynomial across several machines.

Labels:

Thursday, February 05, 2009

Return to Assembler

I got a copy of The Art of Assembly Language from a local library and am working my way through it. I downloaded it from Webster years ago and have been meaning to read it, but it is much more pleasant to read a hard copy.

Assembly Language was my first programming language, but is has been two decades since I used it. I programmed 6800, 6502, 8080, Z-80 & 8086 CPUs in Assembly Language and read up on the 80386 instruction set, but never used it. Things have changed a bit. I never used the FPU before, it is a bit different; and the MMX instruction are not at all what I'm used to. But the basics are still the same.

I have read lots of complaints about HLA. I understand the complaints. The whole point of writing in assembler is to exercise total control over the machine code, polymorphic functions and exception handling seem to fly in the face of this idea. However, I find to be a very good learning tool. It allows me focus my attention of what I'm trying to understand, not the gory details of I/O etc.

The book assumes that you have an operating system, so it does not get into issues like resets and IPL. I wish it covered this because I'm very curious how IPL is handled on a multi core CPU.

Labels:

Tuesday, December 30, 2008

The problem with OO programming languages

In Object Oriented Programming we extend a class by specializing it with a subclass. Going from the General to the specific. This seems to be the excepted way things should be. But it seems backward from the way things work in the real world.

In the real world primitive man had the whole numbers. Eventually problems were encountered that the whole numbers could not solve, so the integers were introduces. Later integers were found to insufficient to solve some problems, so rational numbers were developed. Eventually it was necessary to extend the rational numbers with the real numbers. Much latter rational numbers were extended to the complex numbers. Each extension required creating a super class of the existing class, not a subclass. I am hard pressed to think of a single field of endeavor where a breakthrough was made by specializing an existing concept to make a subclass of an existing class, it always seems to be the other way around.

The other problem is that the subclasses must carry all the baggage of the super classes. Yet in the real world specialized subclasses are less complex than the general super class, not more complex. Consider the classic shapes example, we will consider the specializations of a quadrilateral.

To specify a quadrilateral, we must specify the lengths of all four sides and two of the angles.

We derive a parallelogram from the quadrilateral. Now all we need to specify are the lengths of two sides and one angle, only half as much information. But in most OO languages (Ocaml being the only exception I can think of), we need to carry around all the data needed by the super class, a big waist, but it gets worse.

If we now derive a rectangle (a parallelogram the right angles) and a rhombus (a parallelogram with equal sides) from the parallelogram. The parallelogram requires three data points, but the rectangle and the rhombus each require only two, the lengths of two sides in the case of the rectangle and the length of a side and one angle in the case of the rhombus.

A square is both a rectangle and a rhombus (the dreaded diamond), this is the definition. Only one data point is required to define a square, It is simpler than either the rectangle or the rhombus, so why should it carry the overhead of both?

It seems to me the the existing OO programming concept of going from general to specific is backward. We should be going from the specific to the general in most cases.

Labels:

Friday, January 11, 2008

There are no bugs in software

A 'bug' is a wingless or four winged insect with mouth parts adapted for piercing and sucking of the order Hemitera.

Code does not have bugs, it has defects!

When you make an error in your thinking (or your typing) you introduce a defect in your code, if you do not catch it before it goes to testing (or worse, it ships) it will show up as a fault when the code is running. Faults are caused by defects. Defects are caused by errors. Bugs hatch from eggs.

Defects are cancer in code; the earlier there are detected the easier they are to remove.

  • If it is detected before it is checked in, it is as if it never happened.
  • If it is detected by the testing team, it can be eliminated before the customer sees it.
  • If the beta testers detect it, it will not ship to the main customer base.
  • If it ships, you will need to deal with it for as long as the defective release is being supported!
For this reason it is best to catch defects ASAP! It is best if the compiler can catch them. Next best is if they can be caught by the automated unit tests run automatically by the version control system. Either way they will not be checked in.

We are convinced that code is defect free when either:

  1. It is so simple there is obviously nothing wrong with it
  2. or
  3. It is so complex there is nothing obviously wrong with it.
The first is fine, the second is not. Never give code the benefit of the doubt, if you are not sure it is defect free, assume it is defective. You should only assume code is defect free after you have:
  1. Mathematically proven it to be defect free (and proven that your proof is correct),
  2. and
  3. Run it through a full coverage test suite that deals with restricted resources, device failures, all possible timing issues, and all other possible condition under which the code could fail (such a test suit is probably not even theoretically possible).
Since it is very rare (if not imposable) to do either of these, let alone both, it is very rare that you can assume code to be defect free.

But always remember, bugs do not sneak into code, programmers put defects there!

Labels:

Monday, March 12, 2007

Surrogate Keys

I may be putting my foot in it with this post. I believe wars have been fought over whether or not to use surrogate keys. There are those who will tell you that the use of surrogate keys is proof that the designer of the database did not know anything about database design. There are others who always use surrogate keys and claim anyone who designs a database with natural keys is asking for trouble. My position is, as it is so often, that both are right.

Before getting to the debate I will need to define a few terms. You probably already know most of them, but I need be sure what I say is understood, so I need to make it clear what I mean by the terms I am using.

Candidate Key
A set of one or more columns that can be used to uniquely identify a record.
Primary Key
The set of one or more columns is used internally to uniquely identify a record.
Natural Key
A primary key composed of one or more columns of data which are used by the users in the natural course of their work.
Surrogate Key
A single column, created by the data modeller solely for the purpose of uniquely identifying a record. A Surrogate Key is not derived from application data. The value of a surrogate key contains no semantic meaning.
Foreign Key
A copy of the primary key of one table, put in another table to reference that table.
Logical Data Model
the data model as seen by the user.
Physical Data Model
the data model as implemented in the DBMS.

The first step is to identify candidate keys. Candidate keys must be guaranteed unique, not coincidentally unique in the current data set. Selecting candidate keys is a business decision, not a technical decision. A database for a small club may use first name as a primary key. The club may have a policy that any new member with the same first name as an existing member will be assigned a nickname which will be unique. This is a perfectly valid business rule. Do not tell the client how they should be doing business, just make sure you understand how they do business, and that you make them aware of potential problems.

Every table MUST have one or more natural candidate keys. If you cannot identify a candidate key for a table, you have a problem in your datamodel. Do not generate a surrogate key because you can not find a natural candidate key. This is a common miss use of a surrogate key, and is, I suspect, the main reason that surrogate keys have gotten a bad name. The structure of the database must reflect the business rules. If there is no natural candidate key for a table that is saying that there are records in that table that the business dose not recognize as being different, in otherwords the table contains duplicate data. You do not want duplicate data in the database.

After you have identified, and documented, one or more candidate keys for each table, it is necessary to select a single primary key for each table. A natural key would be one of the candidate keys that have already been identified, but not all candidate keys make good primary keys.

So what is wrong with Natural keys? Imagine a small business that we are designing a customer database for. This business has a policy against assigning customers a customer number, they consider it to be dehumanizing. So they identify customers by name. There is a small problem, names are not unique. The client has a solution to this problem. Instead of using First, Middle and Last name alone as the key they will add date of first order, city, state, and street address. Now there can only be a problem if two people with the same name, living at the same address, place their first order on the same day. An unlikely event which would probably cause lots of confusion no matter how the database is designed. So we run with this as a candidate key.

Would (First_Name, Middle_Name, Last_Name, Date_of_first_order, City, State, Street_address) be a good primary key? The primary key will be used as a foreign key. The customer table will probably have lots of other tables referencing it via foreign keys. Every table that references this table will need to add seven columns to hold this foreign key. Many of these tables will probably have fewer than seven columns of data so more space will be taken up by foreign keys than by data. With disk prices dropping this may not be a big problem. but it is something you might want to think about.

There is a bigger problem. What will happen if a customer gets married and changes her name? All the foreign keys into the customer table must be changed. According to Codd, this is not a problem. Codd said that any relational database management system must provide a command to change a primary key and all associated foreign keys. Unfortunately, there is no system available that fits Codd's definition of a relational database management system, and we will need to use an existing system to implement our database. So this will be a problem. We have the same problem if someone moves.

This case is screaming for a surrogate key. In fact it is contrived, most businesses would assign a customer number. It could be argued that customernumber is a surrogate key, except that the customer number has meaning at the business level, a surrogate key does not. The important things to realize are that; A candidate key has been identified, but for technical reasons it is not well suited to be used as a primary key. Some database designers claim that no natural key is ever well suited to be a primary keybecause they are entered by users and therefor subject to data entry errors and therefor may need to be changed to correct these errors. They have a very good point.

What is wrong with surrogate keys? The biggest problem is when they are used to cover up problems in the data model by creating a key for tables that otherwise have no candidate keys. This is a big no-no. All tables must have well documented, natural, candidate keys. But there is another problem, admittedly a small one, but a problem none the less, and that is that natural keys are more natural. If the client wants to query the credit history of acustomer the natural key is the natural data to query on. If the database uses a surrogate key then it will be necessary to either do a join or a sub query to the customer data table to get the surrogate key. This can make queries significantly more complex if all tables use surrogate keys.

There are two definitions I gave at the top of this post that I have not used yet. logical data model and physical data model. IMHO these two terms are the solution to the problem of surrogate keys. The logical data model is the model you design to. The physical data model is an implementation detail that should be encapsulated at the lowest possible level of abstraction, and definitely should never show up in the business logic. You should consider implementing the logical model as views and only access the data through these views, this way you can encapsulate the physical data model inside the RDBMS.

Like I said, both sides of the surrogate key debate are right. There is no place for surrogate keys in the logical data model, and there should be no user generated primary keys in the physical data model. This give you the best of both worlds.

Labels: ,

Sunday, March 11, 2007

Data Normalization

A data element must depend on the key, the whole key and nothing but the key, so help me Codd. - Ray Kirk

I studied database normalization in the early 1990's when I was working in data modelling with Clive Finkelstein, the father of Information Engineering, and his disciples at Information Engineering Systems, Corp. I am surprised by the aura of mysticism that seems to surrounds data normalization. Most people seem to view data normalization as something that is :

  1. highly complicated that requires an advanced degree in mathematics to understand.
  2. Of no practical value, and not something you'd want to do to a real database.
Both are wrong.

Data normalization is nothing more than a restatement of the 'DRY' principal; every piece of data must have a single, unambiguous, authoritative representation within the database.

Data normalization captures the business rules and encodes them in the data model. Many people believe that normalizing data causes performances problems. It is debatable if this ever was the case, the reported performance improvements were usually gained by ignoring the business rules. But even if it was in the past, it is not now with modern databases.

So how do you capture the business rule in the data model?

Each discrete piece of data should be in its own field. Do not encode many pieces of data in a single field. Each field can be independently queried. If many pieces of data are encoded in a single field they can not be independently queried. Just because you do not need to query them independently now, does not mean you will not need to at some time in the future, so do not store compound data in a single field.

Each discrete piece of data should be recorded in exactly one place in the database (except for foreign keys). If you store the same data in multiple places you will need to put in constraints and triggers to guarantee that the data always remains constant for all copies, if you do not do this they may become inconsistent and since you do not know which copy is authoritative, you will not know what the value really is. The studies that showed data normalization hurt performance ignored this.

Eliminate repeating data. If your customer data table has columns for home phone number, work phone number, cell phone number, voice mail phone number, pager number, etc. This may represent a problem, many of your customers may not have all the phone numbers in your table, and some may have additional phone numbers that are not in your table. You should consider creating a new table to hold the phone numbers. The primary key should be a foreign key to the customer table and a description column which will contain "home", "work", "cell", etc. You can allow the description column to be free form, or you can create a type table which will have a single column containing all the legal values for the description field and making the description in the phone number table a foreign key to this type table.

Eliminate inapplicable data. Codd made a distinction between null values that are unknown and null values that are inapplicable. An example of an inapplicable null value would be if my customer data table has a column for SEX, to record whether the customer is male or female. What value should this field have in the case of a corporate customer? The correct answer is to create a secondary table, with the same primary key as the customer table, which only exists for individual customers, which will contain the sex column, and no corporate customers will have any data in this secondary table.

This is not all there is to be said about data normalization, many entire books have been written on the subject. But this should be enough to solve 80% of the data normalization problems you are likely to face. To learn more read Codd, Date, and Finkelstein.

Next time: surrogate keys.

Labels: ,

Monday, February 26, 2007

Software Quality

If builders built buildings the way programmers wrote programs, then the first woodpecker that came along would destroy civilization. - Gerald Weinberg

I'm not sure when this was written, but I first saw it reproduced in the mid seventies. At that time I thought it was funny, but did not appreciate the truth of it. After spending 20 years writing programs I do not think it would require a woodpecker, a strong breeze would be sufficient.

I have heard many times that computer programs are the most complex structures ever built by man. I'm not sure what this claim is based on, but I find it hard to believe. If it were true we would see a lot more software failures than we do.

When Roman engineers built a bridge, they had to stand under it while the first legion marched across. If programmers today worked under similar ground rules, they might well find themselves getting much more interested in Ada! -- Robert Dewar (President Ada Core Technologies)

The Romans did not have sufficiently developed mathematics, physics and material science to be able to determine in advance whether or not a bridge would be able to support a legion marching across it. So the engineer was made to stand under it to demonstrate his confidence in his design. Since the engineer had to stake his life on his bridge not falling, but had no objective way of determining whether or not it would, he was forced to make sure the bridge could not possibly collapse when the legion marched over it, as a result many of these bridges are still standing thousands of years after their construction. I strongly suspect that many of the people who funded the building of these bridges would have preferred to save a few bucks by building a bridge that would have stood for only a tenth as long, but they were not given the option.

True Software Engineering is still a dream, but many tools do exists. For some reason they seem to be universally regarded as being of interest only to academics. Industry shuns them, I have worked on many projects, on only one was a simple Lint tool used. Most professional programmers believe Lint generates too many warnings when run against production code, so they will not use it. Is the problem with Lint, or with the production code?

Why does the software industry shun any of the tools that could move it toward a true engineering discipline? I cannot say for sure, but I can make an educated guess. I think it is because they think it may slow things down. On all projects I've worked on, with only one exception (which was also the one with the most ridged schedule and the one that used Lint), the goal was to ship something, anything, on the ship date. I think most of my managers would have been perfectly happy shipping blank diskettes if they though they could get them past the test team. Many times there were known serious problems with the software, but they did not need to be fixed because the test team had not found them, and hopefully we would ship before they did. This is patently false economy, since it is less expensive to write good software than to fix bad software. But the mindset in American business for the past several decades has been that it is better to spend $100 tomorrow than it is to spend $1 today. We have to maximize quarterly profits, not long term profits.

I heard that in a resent study American consumers were given a choice of a low quality item which cost $1 and would last a year or a similar higher quality item which cost $4 and would last ten years, over 80% of them chose the less expensive item. So writing poor quality software may not be as foolish as it seems, particularly if you can avoid maintaining the software, and can get your customers to pay for an upgrade to fix the defects. If builders could get away with it I'm sure they would rather build buildings like programmers write programs, and sell new buildings to replace the ones destroyed by woodpeckers.

Labels:

Project Euler

Project Euler is a lot of fun. They post challenging mathematical/computer programming problems for users to solve. Some are quite easy, some are very challenging. I go there to challenge myself. I first solve the problem, usually in J, Python, Ocaml, R, Oz, or Euler (I do not use C++, I write C++ programs professionally, for fun I work with something else). Then I usually try to find a different way of solving it in another language, then I go to the forum (which is only open to users who have solved the problem) and see how others have solved it. Frequently my first attempt does not make the one minute requirement, but I refine it until it does. Maybe I'm weird, but I think it's fun.

Labels: ,

Monday, January 22, 2007

Programming Languages

A language that doesn’t affect the way you think about programming is not worth knowing. – Alan Perlis
Little correlation has been found between performance and years of experience in the field. Actual productivity is better correlated with the number of programming languages the person knows. - Edward Yourdon

Programming Languages I Have Used

I have used many languages. This is a list of those I can remember.

C++

I first used C++ in 1990. My first impression was that regardless of whether or not this OO stuff was any good, being a type safe version of C was a good thing. Soon I decided that this OO stuff was a good thing. I fell in love with RAII long before I ever heard that awful name. My eyes really opened when I read Barton & Nackman's Scientific and Engineering C++, opened even wider when I read Josuttis' The C++ Standard Library: A Tutorial and Reference, and nearly fell out of my head when I read Alexandrescu's Modern C++ Design: Generic Programming and Design Patterns Applied. This is a language that you can continue to learn your whole life!

Don't get me wrong, C++ is far from perfect. I still think its syntax is ugly (see SPECS for a proposed improvement); It needs a real macro capability, template meta programming is good, but not good enough (unfortunately FOG is not it). Design by Contact is a bear. And I wish functional programming were easier. But when you use good libraries like STL, Boost, Loki, STLsoft, FC++ and LC++, it is a very good language. It supposedly was Stroustrup who said "in C it's fairly easy to shoot yourself in the foot, whereas in C++ it's harder to shoot yourself in the foot, but when you do, you usually blow your whole leg off", so watch out for the gotchas.

C

I first used C in 1985. C is the Lingua Franca. If you want to call the same function from C++, Java, Python, J, R, & Clips you have to call it through a C interface. C is very dangerous to work in, but there are good tools to solve this problem. Most note worthy is splint.

Java

I have not done a lot with Java. I worked through all of Sun's Java Tutorial in the late 1990's and read several books on the subjects. I have used Java on two contracts in the early 2000's, both time writing installers. One setting up an Axis SOAP server, the other setting up an Oracle Database and a J2EE Server using JMX.

Java has been getting a lot of hype, but it looks like back to the future to me. Am I the only person who remembers the p-System? It was a virtual machine that executed p-Code on any machine that ran the p-System so you could write once and run anywhere in the late 1970's! The p-System died because p-Code was much slower than native code. Java claims to have solved this problem, I do not know whether or not this is true, but I do know that the JVM takes forever to load on every system I've used it on, and it chews up memory.

I am told that Java 'fixes the problems with C++'. But I'm not convinced. It is garbage collected, but memory is only one resource that the programmer needs to manage, garbage collection does not stop you from dropping file handles or other system resources. Using RAII in C++ make managing memory, and any other resource, fairly painless. Besides, I've always believed that if you did not know the life cycle of your objects, you have bigger problems than just resource management. I have also noted that on every large scale Java project I am familiar with a lot of developer effort has been devoted to controlling the garbage collector. To get the dubious advantaged of garbage collection I have to give up RAII, templates, multiple inheritance, conditional compilation, free functions, and link time checking. I'm not convinced. And if I really want garbage collection in C++ I can us the Hans-Boehm conservative garbage collector.

Don't get me wrong, Java has its place: Applets are great; Swing is nice; Reflection can be useful; and being able to replace a component at run time has some appeal. I just have to remember to release all resources inside finally blocks, not too big a price to pay. It will never replace C++, but it is a useful tool to add to the tool box. It still feels like writing C++ with one hand tied behind my back, I'm sure this will change as I get more experience with it.

JavaScript

I've been using JavaScript since the late 1990's. If you want to write portable DHTML you must use ECMAScript ( Ecma-262 a.k.a. JavaScript, a.k.a. JScript, a.k.a. Live Script, . . . ). JavaScript has been called the most misunderstood programming language. Just as no one seems to be able to agree what name it should go by, no one seems to give it the respect it deserves. The syntax of JavaScript is a lot like Java, but the semantics are completely different, closer to Lisp. It is a powerful functional programming language. Its prototype based object system is under appreciated. While it is the only language for DHTML, it can also be used to develop .NET assemblies, to script either Windows (WSH) or Macintosh (OSA), as a server side scripting language (Whitebeam), and there is a wxWidgets interface to it (wxJS).

C#

I have not done much with C# yet. C# is Microsoft's attempt to kill Java, but they are doing it right. While Java is proprietary, C# is an international standard ( Ecma-334). I have not used either one enough to say what make either better than the other, but I have observed that that CRL seems to load a lot faster than the JVM, but you can't deploy portable web applets in it.

APL, J

J is a modern version of APL. I used APL a little in the early 1980's, and used J a little in the late 1990's and started using it again a few weeks ago.

Like APL, J is a cryptic read only language, but you do not need a special keyboard like you do for APL. There is a good reason that it is the language of choice for the highest scoring users at Project Euler. Once you get past the steep learning curve, it is very easy to do serious number crunching in J. J is great for crunching numbers but not as good at accessing external data. While you can do data analysis in J, reading the data files is no fun (the command to read from a file is 1!:1, I told you it was cryptic).

R (Gnu S)

I have not done much with R, just worked through a tutorial and done some simple statistical analysis. I like what I have seen. R is a language for data analysis. It is a powerful language with a plethora of libraries (see CRAN ). The learning curve for R is much less steep than it is for J. The J wiki even has a page explaining how to call J from R to get the best of both worlds.

Python

I've been using Python since the mid 1990's. Python is object oriented and dynamically typed. Many people get hung up on the fact that white space is significant. All I can say is 'get over it'. You indent your code consistently anyway (at least I Hope you do) so what difference does it make if the language requires it? Python code is easy to read and write. It borrows a lot of good ideas from Lisp & Icon. There are a lot of good libraries available. It scales well, you can throw out a simple script quickly, or write a complex application. It is JIT compiled to byte code, it also can run on either the JVM ( Jython) or CRL ( Iron Python) either interpreted or compiled. Python is my scripting language of choice at this time.

Oz

Oz supports declarative programming, object-oriented programming, constraint programming, and concurrency as part of a coherent whole. The syntax is different from what I'm used to, but not hard to adjust to. I find the single asignment dataflow variables very interesting. In Oz the bind operator (used to bind a variable to a value or another variable) is symentric so X = 7 is the same as 7 = X and binds the variable X to the value 7.

I am working my way through Van Roy and Haridi's Concepts, Techniques, and Models of Computer Programming, I recommend it highly. I suspect that in time Oz may rival both C++ and Python as my language of choice.

Clips

Clips is not billed as a language, but as an expert system shell. Quoting from the Clips User's Guide:

A program written in CLIPS may consist of rules, facts, and objects. The inference engine decides which rules should be executed and when. A rule-based expert system written in CLIPS is a data-driven program where the facts, and objects if desired, are the data that stimulate execution via the inference engine.
So a Clips program is quite a bit different from a program in most other languages. Clips can be used standalone, but more often it is embed in a C program.

ML: Objective Caml, SML, F#, Alice

ML is a polymorphicly typed, strict, impure functional programming language that I have been playing with for a few years. It is strongly, statically typed, but the types are inferred, not declared, meaning the programmer does not tell the system what the types are, the compiler figures it out for itsself. The syntax takes some getting use to, but I like the pattern matching syntax. ML seems to be both safe and powerful, not any easy feat. Most of my experience, and most of the literature, is in imperative programming; and functional programming is significantly different. I suspect that functional programming might be easier for a beginner to learn than empirical programming (frequently writing a functional program is as simple as restating the specification in the syntax of the language), but it is not what I have studied and am use to. I am just starting to learn the Camlp4 pre-processor, it seems to be a great tool.

Haskell

Haskell is a polymorphicly typed, lazy, purely functional language. Since it is lazy, it does not evaluate function parameters until they are needed. it is pure because it is stateless. I have not done much with it yet, but I am going to because there are several book on functional programming that I want to read that use it.

Assembler

Assembler is not really one language, but a family of languages, one for each CPU. 6800 Assembler was the first language I learned back in the mid-1970's. Later I learned 6502, Z80, 8086 & 80386 Assembler. Everyone should be required to learn assembler before they are allowed to call themselves a programmer, because no mater what language you write in, it will need to be translated into assembler (well actually machine code, but no need to get technical) before it can run. If you need to program directly to the hardware you need to do it in either C, Forth, or Assembler and only assembler can give you total control. Only Assembler can maximize performance, but this is often over rated because the code is only as good as the programmer and a good optimizing compiler is frequently better than the average assembler programmer.

D

D is intended to be the successor to C++. Like all the other languages that try to be the next C++, it is garbage collected. I have already expressed my doubts about garbage collection. But, D does offer some real improvements including true modules, closures, lazy evaluation, and design by contract. D does not support multiple inheritance, but I think 90% all the cases where I might use multiple inheritance can be covered by interfaces or mix-ins much more safely. I think I could learn to like D, but I have not used it enough to say for sure yet.

Scala

Scala is a very effective blend of functional, imperative and object oriented techniques and has a practical minded design despite supporting very advanced techniques. Scala's type system is based on vObj, a calculus and dependent type system for objects and classes which can have types as members. It runs on the JVM or .NET, I have only used it on the JVM. It definitely offers a higher level of abstraction than Java, but to deploy an applet you need to also deploy the Scala run time system, which is not small, I'm not sure how big a problem that is.

Boo

Boo is an object oriented statically typed programming language for the Common Language Infrastructure with a python inspired syntax and a special focus on language and compiler extensibility. #delelop supports Boo out of the box, including a Boo interpreter window. Boo is staticly typed but it also supports 'Duck typing' which basicly allows the type to be tested at run time, not compile time. This seems to give the best of both worlds. There is also a good macro system. I'm still learning Boo, but so far I like it. I hope Boo becomes the langage of choice of .NET development.

PHP

When I first learned PHP in the mid 1990's PHP was an acronym for Personal Home Page now it has changed to the recusive PHP Hypertext Processor. It is primarily used for server side web page programming, but it can be used from the command line and there is a GTK+ interface to it (PHP-GTK). I used it to write a few web pages in the mid to late 1990's. I think a good stratagy for web page construction would be to code the static content is Spyce, a python based tool, code the dynamic servers side processing in PHP, because it runs on most hosting servers, and code the client side DHTML code in JavaScript. While I have used each of this componant parts I have never put them together in this fasion. I hope to be doing so soon on my new website at ed_keith.byethost18.com/.

Perl

I have been required to use Perl for a couple of jobs, once for CGI in the late 1990's and once for scripting a build system in the early 2000's. I do not like Perl. It is almost as ugly as J and does not give me anything I can't get in any number of other languages. There was a time when it might have been worth using Perl to get its regular expressions, but now just about any language offers Perl compatible regular expressions. I do have to admit that CPAN is impressive.

XSLT

XML Style Language Transformations is used for transforming XML documents. It is an XML application, and it is a Turing complete language. I have only used it for a few simple things and have not started to plumb it's depths. To get a glimpse of the depths see FXSL - the Functional Programming Library for XSLT.

Icon, Unicon

I used Icon a bit in the mid 1980's I liked it, but for some reason I drifted away from it, now most of the features I liked about it can be found in Python. Unicon bills itself as the unified extended dialect of Icon. It looks like it may be worth another look.

LISP: Scheme, Common Lisp

I first encountered Lisp in the mid 1980's when I read Lisp by Winston and Horn. I used XLISP in 1993 when I read Genetic Programming: On the Programming of Computers by Means of Natural Selection by John Koza. Last year I read Hal Abelson's, Jerry Sussman's and Julie Sussman's Structure and Interpretation of Computer Programs which is based on Scheme, if you have not read this book you should. I plan to read Practical Common Lisp by Peter Seibel this year.

Lisp is the second oldest language listed here, older than COBOL, but not as old as Fortran, many people claim it is still the best language around. Its greatest strength is also its greatest weakness, its syntax. Generally I do not think syntax is nearly as important as semantics, but I'm tempted to make an exception for Lisp. The syntax of Lisp is so simple that it is easy to do metaprogamming for Lisp, in Lisp. Therefor you can use the full power of Lisp to write macros for Lisp. It is hard to comprehend how powerful this is unless you have done it. Also, since the syntax is the same for data as for code it is easy to write a program that writes code on the fly. On the flip side the syntax can be infuriating. Many people claim Lisp is an acronym for 'Lost In Stupid Parentheses'. Lisp has a reputation for being inefficient, but with modern implementations this is no longer true. Lisp is also the macro language for emacs, the gimp, and autoCAD.

Eiffel

Designed by Bertrand Meyer and featured in his excellent book Object-Oriented Software Construction, which I recomend to anyone working in any OO language, not just Eiffel. Eiffel is best known for featuring Design By Contract in the core of the language. It has been standardized as ECMA-367 & ISO/IEC DIS 25436

Ada

I worked through the Lovelace tutorial in the mid 1990's. Ada has a bad reputation as a language designed by a committee but the fact is that all language standards are written by committees. I have not used Ada much, but it seem to be pretty good. If I were in charge of a very large scale project, I'd seriously consider using Ada.

Prolog

Prolog (PROgramming in LOGic) is a logic programming language. A prolog program is not composed of instructions to be executed, but of a set of constraints to be solved. My first exposure prolog was in the mid 1980's when I used it in an emergency room triage system. I used it again in the early 1990's to validate data models. I have not used it since, but am thinking of revisiting it because the LC++ library uses a language that is semantical very similar to Prolog, and XPCE, the GUI tool kit that is part of SWI Prolog, looks very interesting.

μC++

μC++ extends C++ with advanced control-flow including light-weight concurrency. It supports static multi-level exits from nested loops, enhanced exception handling, coroutines, and concurrent tasks. Unfortunatly it dose not suport MS-Windows at this time. I should look into how dificult it would be to port it. μC++ is featured in Understanding Control Flow with Concurrent Programming using μC++ by Peter A. Buhr, which is avalable in the μC++ web site. I strongly recomend all programmers read this paper, even if you have no interest in learning a new language, just to improve your understanding of control flow.

Fortran

To the best of my knowledge Fortran is the oldest language still in use today. I first used it in 1979, it has changed a lot since then, but nowhere near as much as BASIC. While many C programmers may have a hard time accepting this, under some circumstances Fortran can be more efficient than C. The reason for this is that due to Fortran's more restrictive semantics the compiler may be better able to take advantage of pipelining and concurrency.

PL/I

I used PL/I in early 1980's, I've forgotten most of it, but as I recall it was like Pascal on steroids. Anything you wanted to do, there was a built in function to do it. I think the compiler was too big to be ported to a microcomputer. Of course now microcomputers are more powerful than the mainframe was them, but PL/1 was dead before that happened.

Basic

It is hard to say anything meaningful about Basic. I learned BASIC in the late 1970's, at that time BASIC was an unstructured language, all flow control was done with goto's. When I used it again in the late 1990's it was a structured language and I did not use a single goto. The BASIC I used in the 1990's was like an untyped Pascal (I know the phrase 'untyped Pascal' is heresy, but I can't think of a better way of describing it.) Recently I have only used BASIC as the macro language for Microsoft Office tools (Word, Excel and Access).

Pascal, Delphi

I first used Pascal in the early 1980's, and last used Delphi in the late 1990's. Pascal is a nice, under rated language. It might have become more popular than it is if Wirth had not tried to cripple it. Like many students in the 1980's, I wrote a Pascal compiler as a class project.

Modula 2

Wirth did not want Pascal to be extended to make it a useful language to do real work in. He intended it to remain a toy language for teaching and Modula 2 was to be the language do do real work in. When I learned Modula 2, in the mid 1980's, I was used to Pascal, and hated the fact that Modula 2 was case sensitive. Now I dislike languages that are not case sensitive.

AspectJ, AspectC++, FeatureC++

AOP is a great idea, but these implementations of it are seriously flawed. The all suffer from the same non-locality problem as exhibited by Intercal's come from statement. For more information read 'AOP Considered Harmful' by Constantinos Constantinides, Therapon Skotiniotis & Maximilian Stoerzer. I highly recommend you read Clarke & Baniassad's Aspect-Oriented Analysis and Design: The Theme Approach and use it's ideas in your analysis and design but do the implementation in an OOP language until a better AOP is developed. To see some ways to do this refer to Christopher Diggins' Aspect-Oriented Programming & C++ and the tutorial entitled Aspect-Oriented Programming with C++ and AspectC++ which can be found at the AspectC++ web site.

Cmm, Frost

Cmm and Frost are two different extensions to C++ that add multiple dispatch. C++ support single dispatch, meaning that the method called can be determined at run time based on the type of the object the method is invoked on. Multiple dispatch extends this to also allow selection based on the types of the parameters. This eliminates the need of visitor patterns. Cmm has a few additional features, the most useful are embedded functions, allowing whole function definitions inside expressions, and reflection. It also allows block structure from indentation, like python, and an alternative declaration syntax.

Matlab, Scilab, Octave

MatLab was developed as a substitute for Fortran that would be easier for students to use. I used it on several projects in the mid to late 1990's and early 2000's. Scilab and Octave are open source clones of Matlab, each slightly different.

Euler

Euler is similar to Matlab, but not a clone. One nice feature is that you can embed yacas code in it.

Yacas

Yacas (Yet Another Computer Algebra System) is, as the name suggests, a computer algebra system. It is used to do symbolic math.

Maple V

Maple V is a language for doing symbolic math. I first used Maple V in the early 1990's and have not used it extensively.

Mathmatica

I used Mathmatica briefly in the early to mid 1990's. It is a powerful computer algebra systems. At that time it was a real memory hog and brought my PC to its knees.

Frink

Another mathematical language which distinguishes itself by its support of dimensionality and units.

Forth

Forth is a very small language, it has even be written into the microcode of some CPU's. I first heard of Forth when I heard that the controllers used to control the cameras and models to create the special effects in the first star wars movie were programmed in Forth. The best thing about Forth is Leo Brodie's Starting Forth which is arguably the best programming language book ever written! I learned Forth in the early 1980's. I even wrote a simple version of Forth in Z80 assembler.

COBOL

COBOL (COmmon Business-Oriented Language) is the third oldest language on this page (after FORTRAN and LISP) and there are probably more COBOL programs running at this moment that FORTRAN and LISP combined. What gives COBOL its staying power? I don't know, but I suspect decimal arithmetic is part of the answer. I think COBOL is the only language listed here that does decimal arithmetic out of the box (there are some good C++ class libraries for decimal arithmetic, but they are not standard).

Rexx

I read somewhere that there are more lines of Rexx code in existence than there are of COBOL, that is quite a claim. I used it as the primary scripting language for OS/2 and as the macro language for the Kedit editor. I have not used Rexx Since I gave up both OS/2 and Kedit in the late 1990's.

xBase: dBase, Clipper, Harbor xHarbor

I used dBase in the mid 1980's and Clipper in the early 1990's. It is a good environment for small to mid sized database applications. I thought that it was dead, but I see that dBase is still available and that there are three open source Clipper compilers available. I'll keep them in mind next time I need to created a small database application.

SQL

SQL fails to properly capture the relational data model as expresses in relational calculus, but it is ubiquitous. If you are going to develop databases you need to know SQL (you should also know relational calculus). I've been using SQL since 1990.

Suneido

Suneido has some good ideas. It looks like a well designed language that captures the relational model better than SQL. But I have a big problem with it. The program is stored in the database file! This causes several problems. First, you need to write the program in the IDE, you are not free to use the editor of your choice. This is inconvenient, but I can live with it. The more important problems are that since all the code lives in the same file it is difficult for a team to work on it and version control is a nightmare. The application, test data, and unit tests all are in the same file. I'll let you imagine the trouble that can cause. Deploying an update to an existing system with live data in the database is not easy since you need to replace part of the file, but not other parts. All in all while there are many good things to be said for this language, it is far more trouble than it is worth.

PC Focus

I worked with PC Focus in the late 1980's. It was a hierarchical database language. I do not know whether it still exists.

PostScript

Many programmers are not even aware that PostScript is a full blown programming language, it is a dialect of FORTH. If you have never programmed in PostScript you may want to try it.

tcl

Tcl (Tool Command Language) syntax resembles Lisp, but its semantics are no where near as expressive as Lisp. I think the only reasons anyone ever used tcl was for tk and expect. You can now use tk from almost any language, But while there have been two attempts to create a version of expect for python, neither one ever worked properly to my knowledge, so you still need to learn tcl if want to use expect.

ISETL

ISETL (Interactive SET Language) is an interpreted mathematical programming language closely resembling the language of sets and functions used by Mathematicians. I used ISETL when I was working my way through Learning Discreete Mathematics with ISETL by Baxter, Dubinsky & Levin some time in the 1990's.

SNOBOL

SNOBOL stands for StriNg Oriented symBOlic Language, is a language for text processing and pattern matching. I used SNOBOL briefly in the early 1980's. It had some nice features, but its lack of high level control structures turned me off and I quickly moved to Icon.

Intercal

No list of programming languages would be complete without Intercal. INTERCAL is purposely different from all other computer languages. Based on the well-known and oft-demonstrated fact that a person whose work is incomprehensible is held in high esteem, intercal is designed to make any program incomprehensible. (I sometimes think Perl and J are based on the same philosophy). Someday I'm going to write a useful program in Intercal, just to say I did. I'm sure developing something complex in intercal would change the way you think.

Other

I have also used MS-DOS batch language, Unix Shell scripts, lex, yacc, and the macro languages for many applications including MS-Word 2, Word Perfect, and the Brief & VIM editors.

There are several Languages I have not used yet, but interest me:

Ruby
Ruby looks like Perl done right. I first looked at Ruby many years ago, but at that time all the documentation was in Japanese. Now there is plenty of English documentation, so It is time to give it a second look.
Q
Q is a functional programming language based on term rewriting.
Erlang
A functional language that supports fine grained concurrency, transparent distribution, fault detection, persistence, and hot code replacement. The YAWS web server and ErlyWeb web development framework look very promising for developing web services.
Nemerle
Nemerle is a high-level statically-typed programming language for the .NET platform. It offers functional, object-oriented and imperative features. It has a simple C#-like syntax and a powerful meta-programming system.
Lua
Lua is a powerful light-weight programming language. It combines simple procedural syntax with powerful data description and extensible semantics.
Io
Io is a small, prototype-based programming language.
Joy
Joy is a functional programming language which is not based on the application of functions to arguments but on the composition of functions.
Onyx
Onyx is a powerful stack-based, multi-threaded, interpreted, general purpose programming language similar to PostScript.
Mercury
Mercury is a logic/functional programming language, which combines the clarity and expressiveness of declarative programming with advanced static analysis and error detection features. Its highly optimized execution algorithm delivers efficiency close to conventional programming systems. Mercury addresses the problems of large-scale program development, allowing modularity, separate compilation, and numerous optimization/time trade-offs.
FLORA-2
FLORA-2 is an advanced object-oriented knowledge base language and application development environment. The language of FLORA-2 is a dialect of F-logic with numerous extensions, including meta-programming in the style of HiLog and logical updates in the style of Transaction Logic. FLORA-2 was designed with extensibility and flexibility in mind, and it provides strong support for modular software design through its unique feature of dynamic modules.
Dylan
Dylan (DYnamic LANguage) is a multi-paradigm language that includes support for functional and object-oriented programming, and is dynamic and reflective while providing a programming model designed to support efficient machine code generation.
Factor
Factor is a dynamically typed, stack-based programming language.
Heron
Reading the creator's blog, it looks like he and I have similar views of we want in a programming language. It looks like Heron may be my idea of a replacement for C++.
Felix
Felix is an advanced Algol like procedural programming language with a strong functional subsystem. It features ML style static typing, first class functions, pattern matching, garbage collection, polymorphism, and has built in support for high performance microthreading, regular expressions and context free parsing.
Cat
The Cat language is a pure functional language, inspired by Joy. All constructs in Cat behave as functions which takes a single stack as input and returns a new stack. Cat not only has no variable declaration, there are no argument declarations.
Sather
Sather is an object oriented language designed to be simple, efficient, safe, flexible and non-proprietary. One way of placing it in the "space of languages" is to say that it aims to be as efficient as C, C++, or Fortran, as elegant as and safer than Eiffel, and support higher-order functions and iteration abstraction as well as Common Lisp, CLU or Scheme.
Squeak
Squeak is a popular dialect of SmallTalk. The IDE looks a bit strange. I find Croquet particularly interesting.
StrongTalk
StrongTalk is a strong static typed dialect of SmallTalk.
Stratego
Stratego is a modular language for the specification of fully automatic program transformation systems based on the paradigm of rewriting strategies.
Nice
Nice extends the ideas behind object-orientation in order to better support modular programming and static type safety. It also incorporates features from functional programming. It is one of the few languages that support multi-methods
TeLa
Tela (TEnsor LAnguage) is a scientific computing language and environment. It is mainly targeted for prototyping large-scale numerical simulations and doing pre- and post-processing for them.
Yoric
Yorick is an interpreted programming language, designed for postprocessing or steering large scientific simulation codes. The language features a compact syntax for many common array operations, so it processes large arrays of numbers very efficiently. Superficially, yorick code resembles C code, but yorick variables are never explicitly declared and have a dynamic scoping similar to many Lisp dialects.
Pari/GP
PARI/GP is a specialized computer algebra system, primarily aimed at number theorists, and for speed.
GAP
GAP (Groups, Algorithms and Programming) is a system for computational discrete algebra, with particular emphasis on Computational Group Theory.
Lush
Lush is an object-oriented programming language for large-scale numerical and graphic applications.
Glee
Glee, like J, is derived from APL. it looks like it handles files and string much better than J.
Nial
NIAL, which stands for the Nested Interactive Array Language, is also derived from APL. It claims to combine some of the best features of functional and procedural programming.
Limbo
Limbo is the application programming language for Inferno. Like Java, Limbo is compiled to architecture-independent object code which is then interpreted by the Dis virtual machine or JIT compiled. Communication channel is a primitive data type in Limbo.

Conclusions

A good craftsman needs many tools in his tool box. A good programmer needs to be able to use many languages. I find myself reaching for C++ or Python first for most tasks. This changes over time, at various time in the past I might have picked, Pascal, C, Rexx or Icon, in the future I my pick D, Oz, Objective Caml, Alice ML, Scala, Boo, Heron or Unicon. If I'm accessing a database I use SQL, for DHTML I use JavaScript, I do not have much choice in either case. If I'm writing an expert system I'd use Clips. If I'm crunching numbers I'd pick J, R, Euler or a MatLab clone.

So the question many people want me to answer here will be 'What is the best language?' but that is a question that has no answer. Every language represents trade offs, as a results each language has both strengths and weaknesses. With the possible exception of Intercal, there is probably some task for which any language you chose will be best suited for (if you need to write a program to print the full lyrics to the song 99 Bottles of Beer on the Wall then HQ9+ might be a good choice, even though it is not Turing Complete).

The secret of successful program design is to work at the highest level of abstraction possible at all times. For this reason you should always work with the language which offers the best high level abstraction of the problem domain. If the problem is mathematical in nature use J, R, Yacas or another mathematical language. If the problem involves manipulating relational data tables use SQL, Suneido, or xBase. If the problem involves graphic layout use PostScript. If the problem is to directly control computer hardware you will need to use C, Forth or Assembler. If you are developing an Expert system you should use Clips. If you are solving a logic problem use Prolog, Mercury, or Oz. In most cases there will not be an existing language which embodies the necessary abstraction so you will need to develop your own abstraction in the language you chose, so choose a language which will make developing an abstraction easy, such as C++, Oz, Scala, Nice, Heron, Boo, Nemerle, Unicon, etc.

I recommend that all programmers learn C, C++, Assembler, and some dialect of Lisp. I do not recommend C or C++ as a first language, and a strong case can be made against Assembler or Lisp as a first language, although Assembler was my first language, and many people recommend Scheme as a first language. Pascal is a good first language, it was designed for teaching. I have heard good things about Euphoria as a first language, but have no experience with it. A dilect of ML might be a good first language, but I'm not sure.

For a chuckle see http://www.netfunny.com/rhf/jokes/88q2/3785.4.html or http://www.cs.caltech.edu/~mvanier/hacking/rants/cars.html.

Labels: