The Apple Calculator Language Primer

Source: Jef Raskin, "The Apple Calculator Language Primer" (13 October 1979)-- in "The Macintosh Project: Selected Papers from Jef Raskin (First Macintosh Designer), Circa 1979," document 14A, version 10.
Location: M1007, Apple Computer Inc. Papers, Series 3, Box 10, Folder 1.

{Note: material in braces is notes to myself, or notes to the advanced reader. The reader might well comment that the following language seems similar to the work done by K. Iverson over eighteen years ago. Apple is based on a re- spelling of Iverson's work. Even the name "Apple" might seem derivative from the name he chose for his language.}

Chapter 1, It's a Simple Calculator

To begin with, this language only uses the numbers, the signs for simple arithmetic, and the large key over on the right side of the keyboard marked with the word "RETURN". Press this key whenever you see the word "RETURN" in a box. Later we will use the other keys too, so as not to be wasteful.

You can tell that it is your turn to type whenever you see an exclamation point (!) sitting at the left edge of the screen. As soon as you begin typing, the first character that you type replaces the "!". The exclamation point is called the "prompt" character, because it prompts you to type something.

Now you know when you can type something. Type

5+2 [RETURN]

The computer responds by showing the result

7

We must say a word about fixing typing errors. You can correct a typing error by backspacing over it and typing the correct information. To backspace, hold down either button marked "SHIFT" and press the space bar.

Subtraction is indicated by the usual minus sign

5-2 [RETURN]

3

{Negative numbers are indicated by preceding them with an underscore (_), e.g. _45.4}

In this manual, any line not followed by [RETURN] is produced by the computer, in this case, the answer 3.

Multiplication is indicated not with an "X" but with an asterisk (*).

3*4 [RETURN]

12

Division is indicated by a slash (/)

4/2 [RETURN]

2

7/4 [RETURN]

1.75

You can do more than one arithmetic operations in the same line, for example

6/3+2*5 [RETURN]

20

A combination of a number of operations such as this is called an "expression". The rule for evaluating an expression is very simple: Start at the left and move to the right. The expression 6/3+2*5 starts out as 6, the leftmost number. It is then divided by 3. That's 2. Then you have to add 2: that makes 4. Now multiply the result by 5: the result is 20.

If you are familiar with simple pocket calculators, you will recognize that this is exactly how they work. You put in a number, then an operation, then a second number and press the button with an equal sign. In this language you press [RETURN] instead of the equal sign. Evaluating an expression is exactly like doing a "chain calculation" on a pocket calculator where you don't bother to get intermediate results.

If you are familiar with other computer languages, or do a lot of algebra, you might find this strict left-to-right scanning a bit unfamiliar. Actually, if you think about it, this method is more consistent and simpler. This is one of those cases where the beginner with no prior computer experience has the advantage.

If you wanted to add 6/3 to 2*5, you could write the expression

(6/3)+(2*5) [RETURN]

12

Parentheses are used to group items that are to be evaluated together and subsequently used as a single entity.

What would be the value of

55/11+1+12/6*2-3

as interpreted by the computer? The answer isn't 13. The answer isn't 7. In fact there are a whole lot of numbers that the answer isn't.

{ The answer is 3}

Powers of numbers, such as 2 to the tenth, are easily obtained.

2 TOTHE 10 [RETURN]

1024

And to get a square root, you could write

2 TOTHE .5 [RETURN]

1.41

Notice that the answer comes out to two decimal places. This is the standard, or default number of decimal places. You can get almost any number of decimal places you want. Up to a limit of {say, 18}. For example, to get seven places, you would type

7: PLACES [RETURN]

2 TOTHE .5 [RETURN]

1.4142136

The answer is rounded to seven places. This only affects what the computer shows: inside it knows the truth and remembers as many decimal places as it can. It will continue to show answers to seven places until you give it some other number of places. Here is another example:

10: PLACES [RETURN]

22/7 [RETURN]

3.1428571428

1: PLACES [RETURN]

22/7 + .6 [RETURN]

3.7

0: PLACES [RETURN]

22/7 + .6 [RETURN]

4

{There might be a WIDTH specification as well. Together with the PLACES specification this controls precision.}

Chapter 2, Clumps of Numbers

Here is an easy one to figure out

17 [RETURN]

17

The simplest expression is just a number. It is not much more complicated to have a clump of numbers, separated by spaces.

34 5 67 [RETURN]

34 5 67

A clump of numbers acts pretty much like a number in an expression. When you add a number to a clump, you add it to each number in the clump. For example

34 5 67 + 3 [RETURN]

37 8 70

The way to figure out how to handle a clump is to start from the left (as always). First you find the 34, then a space, then the 5. Since there was no operation between them, you know that they must be part of a clump. Then you find another space, followed by the 67. Since you have encountered no operation, the 67 is also part of the clump. The next thing you find is a space followed by a plus sign, indicating an operation. This is not a number, so the clump is finished. The operation symbol you just found tells you what to do to the entire clump, in this case you add three to each member of the clump.

Here is an example with multiplication.

1 2 3 4 5 *6 [RETURN]

6 12 18 24 30

Just one more example of using a clump.

2 5 1 -2 [RETURN]

0 3 _1

Remember how negative numbers are indicated. There is a very good reason for distinguishing the operation of subtraction from negative numbers. For one thing, it is never good to use one symbol to represent two different concepts. Furthermore, if we didn't distinguish these ideas, how would you put a negative number into a clump?

Now let's evaluate

7 + 2 .5 1 * 6

Starting at the left you find a 7. The next thing you find is a plus sign, so a clump isn't being formed. Continue to the right and you find a 2. Now you can perform the addition and add 7 to 2 to make 9. The expression is now equivalent to

9 .5 1 * 6

Clearly 9, .5 and 1 form a clump, and then you find a multiplication sign, so the clump is done. Now multiply each element in the clump to get the answer

54 3 6

Parentheses are quite useful. For example you can use parentheses to write

7 + (2 .5 1) * 6

The seven is added to the entire clump, to give

9 7.5 8 * 6

which evaluates to

54 45 48

All this makes the calculator much more convenient for calculations involving a whole bunch of numbers. For example, to convert 32, 50, 100 and 212 degrees Fahrenheit to degrees Celsius, you could write

1: PLACES [RETURN]

32 50 100 212 -32*5/9 [RETURN]

0 10 32.8 100

(We didn't have to limit it to one decimal place, but we did, for appearances sake.) To see how this works inside the computer (and how you can figure out the answer yourself), the first part of this expression is equivalent to (32 50 100 212)-32, or 0 18 68 180. This new clump is then multiplied by five, yielding 0 90 340 900. Lastly, it is divided by 9 (remember, just work from left to right) to yield 0 10 32.8 100.

Chapter 3, Automatic Clumps

Some of the most useful clumps of numbers are just consecutive integers, for example the thirteens multiplication table can be obtained by

1 2 3 4 5 6 7 8 9 *13 [RETURN]

13 26 39 52 65 78 91 104 117

You can abbreviate a clump of consecutive integers by use of what is called, in English, the ellipsis. The ellipsis is a kind of punctuation in a class with such things as periods, commas, semicolons...

Those three dots are the ellipsis. To save you a bit of typing, the computer uses two dots. The thirteen's table can be produced by the expression

1..9 *13 [RETURN]

13 26 39 52 65 78 91 104 117

Of course, you can count backward

5..2 +3 [RETURN]

8 7 6 5

{Interestingly,

5..7..2 [RETURN]

5 4 3 2 6 5 4 3 2 7 6 5 4 3 2

Why is this? Because 5..7 is 5 6 7, so the expression is equivalent to

(5 6 7)..2

which is 5..2 6..2 7..2

Just remember to do things strictly from left to right. Also notice that if real numbers are used where integers are expected, as in 3.6..7.2, they are truncated to integers 3..7}

So far we have done arithmetic between a single number and a clump. When clumps are the same length, we can easily do arithmetic between whole clumps at a time. It is done element by element.

(1 2 3 4)+(4 3 2 1) [RETURN]

5 5 5 5

But remember, without parentheses, you have to work things through from left to right, element by element.

1 2 3 4+4 3 2 1 [RETURN]

5 6 7 8 3 2 1

This can be checked by starting to form a clump 1 2 3 4. Then you find an operation, which applies to the whole clump. The operation is to add four to each element of the clump. That gives you 5 6 7 8. There is no operation before the next number, so you must still be clumping. This explains the given answer.

{This also shows that juxtaposition indicates concatenation of output.

Another example is

2..6 3..1 [RETURN]

2 3 4 5 6 3 2 1

You might like to try

1..4+4..1, which is equivalent to

(1 2 3 4)+4..1, but this is

(5 6 7 8)..1 or

5 4 3 2 1 6 5 4 3 2 1 7 6 5 4 3 2 1 8 7 6 5 4 3 2 1

Now consider

(1..2)+(1..3) [RETURN]

2 4 3

These two clumps are of different lengths. The shorter clump is always "padded" to make it equal in length to the longer. In this case it is padded with zeros. {The identity element is always used as padding. For addition and subtraction it is 0, for multiplication and division it is 1. A more complete list of padding elements is presented later.}

One last thing to try

3/0 [RETURN]

YOU MUSTN'T DIVIDE BY ZERO

This is an example of a "error message" which tells you that you have done something beyond the pale.

Chapter 4, Some Other Operations

It is sometimes convenient to be able to get just the remainder of a division. In accord with common practice, this is indicated by MOD

3 MOD 2 [RETURN]

1

If you divide 3 by 2 you do, indeed, get one left over. This next example is educational

1..16 MOD 7 [RETURN]

1 2 3 4 5 6 0 1 2 3 4 5 6 0 1 2

You can get the greater or lesser of a pair of numbers.

3 MAX 38 [RETURN]

38

3 MIN 38 [RETURN]

3

38 MAX 3.09 [RETURN]

38

17..21 MAX 19 [RETURN]

19 19 19 20 21

With clumps of equal length you can easily do this

1 2 4 8 16 MIN (1 3 6 9 12)

1 2 4 8 12

And, similarly, you can compare numbers. In this language the number 0 is used to indicate that an answer is false, and 1 indicates that an answer is true. While this may seem a bit strange, we will be able to use these values in some rather neat ways later.

The sign ">" means greater than.

1642 > 31.008 [RETURN]

1

5 > 7 [RETURN]

0

The equal sign (=) we use unblushingly to mean equals.

3 = 4 [RETURN]

0

6.4 = 6.4 [RETURN]

1

We use "<" for less than, but won't bother with any examples, but go on to use "<=" for less than or equal to and ">=" greater than or equal to.

18 <= 3 [RETURN]

0

7 >= 7 [RETURN]

1

Lastly, in this group, we use "<>" for not equal to, since it has the meaning "greater than or less than" which is the same idea.

5 <> 5 [RETURN]

0

Observe that you can compare to a clump

1 2 3 4 5 6 > 3 [RETURN]

0 0 0 1 1 1

For those who need them, we have the functions AND, OR and XOR.

0 AND 0 [RETURN]

0

1 OR 0 [RETURN]

1

1 AND 0 [RETURN]

0

in all the familiar combinations. For example

0 1 0 1 OR (0 0 1 1) [RETURN]

0 0 0 1 Why didn't we write 0 1 0 1 OR 0 0 1 1?

{Because that would be 0 0 0 0 0 1 1 and not show all the combinations.}

Why didn't we have to write (0 1 0 1) OR (0 0 1 1)?

{Because we evaluate from left to right, but it might not be a bad idea to sometimes use redundant parentheses in a situation like this to make the expression clearer.}

1 XOR 1 [RETURN]

0

 

.pn 12

.fo ' ' M 14B.7 Page %

Chapter 5, Some Scientific Calculator Abilities

For those of you that like your calculators scientific, we have sines and cosines and the like. On the typical calculator, if you have a number in the display, and want to find its sine, you press the button marked "SIN" (no religious implications intended). Similarly, in our left-to-right scheme, after you have a number you just type "SIN" and the result is calculated. For example

3.141592654 SIN [RETURN]

0

Here, we are working in radians. If you'd rather work in degrees, you have an option, the way you did with the number of decimal places. You can set the option "RADIANS" to true or false. If it is true, you are working in radians; if it is false, you are working in degrees.

From the sine value above you can conclude that you were working in radians. If you want to work in degrees, you make RADIANS false. It works very much like PLACES did.

0: RADIANS [RETURN]

.5 ARCSIN [RETURN]

30

To get back to working with radians, you would type

1: RADIANS [RETURN]

Incidentally, if, at any time you want to find out to how many decimal places the computer will display, you can just type

PLACES [RETURN]

4

Or, to find out if you are working in radians or degrees, you can type

RADIANS [RETURN]

0

The trigonometric functions you have available are

SIN COS TAN ARCSIN ARCCOS ARCTAN

Also you have LOG (which is base 10) and LN (which is base e).

There is even a constant

PI

with the usual value. You can say

PLACES: 3 [RETURN]

1..4 * PI [RETURN]

3.142 6.283 9.425 12.566

Incidentally, what would you get from PI * 1..4?

{3 4}

{The base of the natural logarithms is available. Its name is "E".}

We also have two simple functions, FLOOR and CEILING. FLOOR gives you the greatest integer less than or equal to the given number; CEILING gives you the least integer greater than or equal to a given number.

5.1 17 -5.1 FLOOR [RETURN]

5 15 -6

5.1 17 -5.1 CEILING [RETURN]

6 17 -5

In the same vein we have

22 22.1 22.5 22.51 22.8 ROUND [RETURN]

22 22 22 23 23

and we can truncate

22 22.335 22.8 -5.43 -4.9 TRUNCATE [RETURN]

22 22 22 -5 -4

And here is a strange, but enjoyable function. You'll have to puzzle it out from these examples.

3 PICK [RETURN]

3

4..8 PICK [RETURN]

5

4..8 PICK [RETURN]

4

4..8 PICK [RETURN]

4

4..8 PICK [RETURN]

7

It gives a random choice among the clump presented to it.

There is also one logical operator among these functions

0 NOT [RETURN]

1

1 NOT [RETURN]

0

If you apply NOT to numbers other than 0 and 1, the results may seem strange, so it is not recommended. {The logical operators applied to integers result in bit-wise operations. If the numbers are not integers, they are first truncated.}

Here are some puzzles. Fill in the computer's part.

0 NOT 3 [RETURN]

{1 3}

0 1 NOT [RETURN]

{1 0}

3.1 -5.6 -5.2 3.8 +.5 CEILING [RETURN]

{This evaluates as follows 3.6 -5.1 -4.7 4.3 CEILING which is 4 -5 -4 5}

Chapter 6, Saving for a Rainy Day and with Words we Learn to Play

Many calculators have a way of storing a number, then later recalling it. This is usually called "memory". In this Apple Calculator, there is also memory. For example, to save the value 5 you merely give it a name, in this case we'll call it "fingers".

5: fingers [RETURN]

Notice that the computer types nothing back to you (except the prompt, which we never show in this manual. It now sits there awaiting your command. And it remembers that the value of fingers is 5.

You have seen that

5 [RETURN]

5

Well, now that you have defined fingers you can type

fingers [RETURN]

5

Of course

13 84 56 72: hike [RETURN]

hike [RETURN]

13 84 56 72

hike -20 [RETURN]

-7 64 36 52

 

So you see that you can store numbers and clumps of numbers into cubbyholes that have names. Names can be as long as you like; just remember that you will have to type them so you might not want to make them too long. The rest of the rules for names are simple: they must begin with one of the twenty six letters of the alphabet in upper or lower case, they may contain letters of the alphabet, digits, and periods. Blanks are forbidden. It is recommended that names be all lower case. For example

flavor.number.58

is a legal name. It is customary to write names in lower case characters so that they are easily distinguished from keywords, such as SIN or TRUNCATE. You may not use any keywords (which are always upper case) as names.

This flexibility to use names that we devise ourselves makes this calculator a little bit easier to use than most pocket calculators. It sure is easier to remember that you've put the checkbook balance into a cubbyhole named "balance" than to remember that it is in "register 4".

Our calculator doesn't only deal with numbers, but with letters as well. As you know a cat has four legs, but the word "cat" has no legs at all. It has three letters. We distinguish, in English (and most other phonetic tongues) between the way the word is written and its meaning by using quotes. This is true of the Apple language as well. Here are some examples.

"cat" [RETURN]

cat

It should be clear that

fingers [RETURN]

5

"fingers" [RETURN]

fingers

One very useful ability is to be able to find the number of characters in a string.

"fingers" LENGTH [RETURN]

7

Incidentally, this function also works with clumps of numbers

1 2 3 LENGTH [RETURN]

3

3..9 LENGTH [RETURN]

7

Is this answer correct?

{Sure is, even though 9-3 is 6.}

As we have seen, just writing two clumps one after the other gives a longer clump

2..6 7..5 [RETURN]

2 3 4 5 6 7 6 5

the same thing happens with letters

"had" "dock" " smells" [RETURN]

haddock smells

This is called "concatenation", the bringing together of two or more objects side by side. Notice that the space between the quote and the word "smells" is not accidental.

Letters between quotes are called strings. You can concatenate strings even if they have been given names.

"abcd":alpha [RETURN]

"efghij":bet [RETURN]

alpha bet [RETURN]

abcdefghij

Every name, whether you use it or not, has a value.

elephant [RETURN]

0

That is because any name that you haven't given a value to is zero. If the name is used as part of an expression involving strings, and it hasn't been given a value, then its value is a string with no characters. This is called the "null string" in the jargon. In this example the name "alphabet" has not been given a value, so it is the null string and has no effect when concatenated to the string named "alpha".

alphabet alpha [RETURN]

abcd

Chapter 7, An Interlude: A Summary and Re-presentation

The prompt character is "!", and it is overridden by the first typed character. User input is terminated by [RETURN].

The dyadic operators (those that come between two quantities and do something involving both of them to result in another qantity) are

+ - * / TOTHE .. MOD MIN MAX < = > >= <= <> AND OR XOR INSERT

0 0 1 1 1 1 0 0 0 0 0 0 0 0 1 0 0

The numbers under each operator is the padding value in case the operation is attempted between clumps of different lengths. Strings are padded with nulls.

The special variables (names that have a meaning to the system) are

PLACES RADIANS PI E

The monadic operators (those that come after a quantity and do something involving it) are

SIN COS TAN ARCSIN ARCCOS ARCTAN NOT LOG LN FLOOR CEILING ROUND TRUNCATE PICK LENGTH

Names may begin with any letter, and may have letters, digits and underscores. The assignment operator, which should be a right-pointing arrow, is the colon because ASCII doesn't have a right-pointing arrow. Expressions are evaluated strictly from left to right, but the order may be modified with parentheses. Any printing characters, space, and return may occur in strings. Much more is to come.}

Chapter 8, A Few More String Operations

Strings can be converted to clumps of numbers and vice versa. A table {the standard ASCII codes} shows what numbers go with what characters. For example

"ABC" NUMBER [RETURN]

65 66 67

68 69 70 LETTER [RETURN]

DEF

If you give the LETTER function a number too high to represent any letter in the clump, then it gives back the null character.

{It is nice if

"" NUMBER [RETURN]

0

and vice versa}.

You can compare two letters

"a" > "b" [RETURN]

0

You can compare strings for alphabetic order

"jello" <= "hello" [RETURN]

0 1 1 1 1

"jello" > "hello" [RETURN]

1 0 0 0 0

just as you could for clumps of numbers.

It is sometimes useful to deliberately change the value of a numerical quantity into a string, for example

34 STRING "b" [RETURN]

34b

And to go the other way, there is the VALUE function

"2" VALUE +1.1 [RETURN}

3.1

Single quotes are used when the string has double quotes in it

'He said, "Do not shoot, I have a cold".' : line.from.movie [RETURN]

line.from.movie [RETURN]

He said, "Do not shoot, I have a cold".

Chapter 8, Inserting Operations into Clumps

Let's say you wanted the odd numbers between 1 and 19 inclusive. It is easy to get the even numbers between 2 and 20

1..10 * 2 [RETURN]

2 4 6 8 10 12 14 16 18 20

if you then subtract 1, you get the odds (in this example they are first stored under the name "odds" and then displayed.)

1..10 * 2 - 1: odds [RETURN]

odds [RETURN]

1 3 5 7 9 11 13 15 17 19

Now, say you wanted to find the sum of all the odds in this range. You could write the expression

1 + 3 + 5 + 7 + 9 + 11 + 13 + 15 + 17 + 19

which does the trick. But there is an easier way. You can automatically insert any operator that works on two entities (called a "dyadic" operator) between all the elements of a clump. The operation is called "INSERT". After the word "INSERT" you place the operation you want inserted into the clump. For example, the sum of all the odd numbers above can be easily obtained by

odds INSERT + [RETURN]

100

You can get the largest of a clump of numbers by using INSERT MAX

34.667 92 3 _45.09 INSERT MAX [RETURN]

92

The smallest of a clump?

odds INSERT MIN [RETURN]

1

To demonstrate another application of INSERT, we introduce the monadic function ODD.

11 ODD [RETURN]

1

34 ODD [RETURN]

0

ODD determines if a number is odd. Here is a clump

12 34 55 18 67 31 24 : bunch [RETURN]

For convenience, we have given the clump a name. It is simple to find how many odd numbers there are in the clump.

bunch ODD INSERT + [RETURN]

3

This tells us that there are three odd numbers in the bunch. Step by step, it works like this: bunch ODD

evaluates to

0 0 1 0 1 1 0

and then

0 0 1 0 1 1 0 INSERT +

evaluates to

0 + 0 + 0 + 1 + 0 + 1 + 1 + 0

which is

3

How many even numbers in the clump?

bunch LEN - bunch ODD INSERT +

Or, you can use the handy EVEN operator

bunch EVEN INSERT +

We can ask, for example, how many examples of the letter "e" occur in a text.

"The quality of mercy is not strained." = "e" INSERT + [RETURN]

3

Chapter 9, Selecting Elements from a Clump

By this time, you are quite experienced, so a few examples should suffice.

"abcde" [1] [RETURN]

a

"abcde" [2] [RETURN]

b

"abcde" [5] [RETURN]

e

"abcde" [2 5 1 4] [RETURN]

bead

12.5 99 63 [2] [RETURN]

99

12.5 99 63 [5] [RETURN]

0

"abcde" [_3] [RETURN]

This last example evaluates to the null string.

About Clumps

1. Etymology and Phylogeny of Clumps

Clumps are a data structure. I searched about for a while to find this name. The best English word for them is probably "lists". A shopping list is an excellent model:

One Useless

Three boxes of Dreadful

Two packages of a dozen Expensives each

A pound and a half of Unobtainium

A Gimcrack

A dozen Shoddies, or a bag of Overpriced, whichever is cheaper

However, the word "list" has been pre-empted by computer science to mean a clump with pointers between the items in the clump. A clump is something like a vector, but the word "vector" is scary to many beginners, besides, the terms "vector" and "array" in most technical parlance usually imply elements of like kind. The same problem applies to "matrix". A clump is not a set, since it's elements are ordered: it is an ordered set, but that name is too clumsy. I can't use many other English words, such as "group" or "conglomeration" or "accretion" on the grounds of overuse, lack of euphony, or excess length. Thus, "clump". This word also has the feeling of "sticking together", which is how clumps behave in expressions. (The verb "to clump" means to put things together in generally irregular ways.)

The word "clump" has a certain informality about it. This corresponds nicely to the way they are used. Clumps are not declared, they just happen as they are needed. Clumps are not fixed in size or composition. However, they are ordered; each clump has, at any moment in a program's execution, a fixed number of elements, each associated with an ordinal number that gives its position. Clumps are linear.

A clump may have an element that is, itself, a clump. There is no null clump. If you create a clump, it is assumed to be something, depending on context. The smallest clumps are things like the null string, a single numerical value (possibly zero), or just one other clump. Clumps are the only named objects in this language. Programs are clumps.

I fear a strong abreaction from structured programming devotees. I wish to say to them: live and let live. Programming languages and structures are tools, and each tool has its rightful place. Computers are not only to be used by carefully disciplined coders in phalanx. They are also to be used by undisciplined non-programmers who care to solve a problem in the quickest, most haphazard way they can. You cannot argue with human happiness, and a formal, structured, declared approach is not always appropriate. If you think that it is, then you have a bit of the martinet or despot in you, and would have everybody toe the line and write magnificent, portable, durable code. If you are true to form, you probably won't let anybody write a quick note in pencil to a friend, but require them to have it typeset, on 100% rag paper, and sent by liveried messenger.

Apple is an informal communication between a user and his or her computer, it is quick, impermanent, friendly, and useful. Do not fret, my structured friend, you will not be put out of business, nor threatened by this any more than I, a professional writer by trade, am threatened by universal literacy. Such literacy just means a wider audience for my professional talents. So will it be for programmers. The more people know how to program and use computers (the two are not synonymous) the more customers there will be for good programs. The more a person knows about programming, the more he or she realizes the quality of a fine program. Apple is no impediment to the writing of fine software.

2. The Elements of Clumps

The elements of clumps are of two kinds

A. Numbers

A number is a sequence of digits and, optionally, a decimal point. There is no notation for powers of 10 such as 34.2E14. Such numbers can be represented externally using the usual notation for powers. The output routines will do this when necessary. There is no problem on input, since expressions can be used wherever a constant may be. The internal representation of numbers is not a really a concern of the language design, except that it is expected that there will be at least 18 decimal digits of precision. Numbers will generally be stored as integers unless a real representation is required. The precision of the representation may also change.

B. Characters

Characters are those codes that can be generated by the computer. Some of them (at least the usual set of 96 ASCII/ISO characters) can be shown on a display or printed. They are:

ABCDEFGHIJKLMNOPQRSTUVWXYZ (26 uppercase letters)

abcdefghijklmnopqrstuvwxyz (26 lowercase letters)

12345678890 (10 digits)

\:-@^[;],./|!"#$%&'()0*=`~{+}<>?_ (33 special characters)

(1 space)

Strings are no part of the language. There are just clumps of characters.

3. A Formal, Been Eff, Definition of Clumps

A formal item in braces means that it may appear zero or more times.

digit := 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

decimal point := .

integer := <digit>{<digit>}

number := <integer> | <integer><decimal point> | <decimal point><integer>

| <integer><decimal point><integer>

character1 := <any of the 96 characters shown above except the single quote>

character2 := <any of the 96 characters shown above except the double quote>

letter := <any uppercase or lowercase letter>

name := <letter>{<letter> | <digit> | <decimal point>}h space :=

string := "{<character2}" | '{<character1>}'

element := <string> | <number> | <name>

clump := <element><space><clump>

Note that integers and strings per se do not appear as separate concepts in the user's view of the language, and that exactly one space is specified between clumps.

4. Expressions Involving Clumps

We first define the assignment operator which has the form

<clump> : <name>

Thereafter the name stands for the clump. The value includes type and structure information. This is different than most languages where this information is associated with the name, rather than the value.

Every clump has a length L. L >= 1. This length is the number of elements that comprise it.

There are two kinds of operators in this language, monadic and dyadic. Operators may be distributing, expanding or reducing. A distributing operator operates on each element of a clump and leaves a different clump of the same length. A reducing operator reduces a clump to a smaller clump, usually an element. For example, the LEN operator reduces a clump to a number, the assignment operator (:) reduces a clump and a name to a name. The sequence operator (..) takes two numbers A and B and expands them into a clump of (B- A+1) elements.

A monadic operator occurs after the clump on which it operates. A dyadic operator occurs between two clumps.

monadic operator := LEN | (to be filled in)

dyadic operator := + | - | * | / | TOTHE | MOD | : | .. | (to be filled in)

expression := <clump> | <clump><monadic operator> |

<clump><dyadic operator><expression>

Postscript and Diatribe

To the Reader:

To those of us not familiar with APL, this language may seem a bit odd. To those of us who know APL, this language may seem a bit odd too, but in a different way. One of the major aims of the designer of general purpose computer languages should have is to improve the quality of life of the programmers who will use it. The important item here is the programmer or user, not the system. The whole idea of a higher level language is this: programming time is very dear, let's use the computer to minimize it. As computers become cheaper, this strategy becomes ever more valuable. Computers are now very cheap. In the room in my house where I am writing these words (on a computer system) are no less than three computers. The most expensive piece of equipment, on an hourly basis, is me.

It is with the utmost trepidation that I dare to attempt to design a new computer language. New computer languages are plentiful and easy to come by, many old language are adequate and well entrenched. My motivations are simple, and relatively pure. The advent of personal computers gives me sufficient excuse, and a new potential audience. None of the major languages was designed for use by untutored individuals using computers in their personal lives. And, as I shall attempt to show, none of them is truly suitable to this arena.

My main motive is to give people as much power for as little effort as I can conceive. I have been programming computers for most of my life, and of the many languages I have used, one stood out as permitting me to accomplish, in a given amount of programming time, more than any of the others. Subsequent studies by others have shown that I was not unique in my appreciation of this language. But before going on, perhaps a brief examination of the broad characteristics of computer languages, from the point of view of programmer effort, and why each language is popular is in order.

A View of Existing Languages

One language is "higher" than another if its primitives are constructs in the other. Sometimes "higher" depends on the task. For many processes involving lists and grammars, LISP is a very high level language. It is not quite so high level a language for some engineering applications. The major directions in higher level languages might well be summed up in these words: ALGOL, BASIC, COBOL, SNOBOL, LISP, APL.

FORTRAN and PL/1 are derivatives or fellow travelers of ALGOL, as is Pascal. As declared languages they are inherently poor at simulating human trains of thought. I am well aware of the advantages of declarations, and take joy at the improvement in control structures of, say Pascal over FORTRAN. But these are all improvements of a detailed, nit-picking sort. What languages should do is remove the nits, and minimize the detail you must think about when solving problems. What Pascal's data structures, declarations, and control structures have done is to make those details more explicit, and thus cleaner. It is a real improvement, but unfortunately leans in the direction of discipline and rigidity.

BASIC derives from the same tradition as FORTRAN, standing out only because of its interactive environment. BASIC is a very weak language, and is being shored up in many ad hoc ways. Any student of programming languages can easily poke holes in it. Nonetheless, it will continue to be used for many years, which is a tribute to its environment, not its internal design. BASICs well- deserved popularity demonstrates that minimizing programmer effort and time is often more important, when it comes to purchasing a language, than the language's features as described in the spirit of traditional computer science.

COBOL, with regard to general problem solving, is weak and inefficient of programmer time. Its widespread use is proof that money and marketing strategy can be as important as rigor and technical perfection. I have never, in any study of the design of computer languages, seen a chapter (or even a paragraph) devoted to the importance of marketing to the general adoption and use of a language. When COBOL was introduced, computers were "IBM machines", and IBM pushed COBOL for business applications. It actually has features that are advantageous in some business applications, but it never would have succeeded on pure merit. It is not the only product in the world that owes its success to PR.

SNOBOL, which has some novel features, was first designed for string processing, at which it is a very high level language. Like many other languages, it will retain a small and devoted following. Besides the string processing features, SNOBOL is rather consistent in design, and its program structuring technique is interesting. I mention it only because it exemplifies a language that was designed for a special, limited purpose which later (because of its excellent design) became more widely used than one would have expected given its intended audience.

LISP has been given lisp service above. It is an interesting corner of the programming universe, and is relatively efficient of programmer time. It suffers from an overdose of recursion and a lack of approachableness for common, everyday activities.

Why APL is Singled Out

Most of my praise and commentary must be reserved for APL. In terms of stating many algorithms, APL is a much higher level language than the ALGOL group. For example, APL builds most loops into its expressions, whereas the ALGOL group of languages (as well as most others) require the programmer to pay attention to the details of each loop. APL was designed with an interactive human environment as part of its specification. It was years ahead in this regard.

Pascal is often pointed out as a modern, well designed language. It is, to be sure, tolerably efficient. Its efficiency is due to many design choices aimed at making life easier for the compiler writer and system programmer. The user is often ignored. The programming environment is not even the least part of the design (although the assumed environment had a subtle influence). This brands Pascal as practically reactionary rather than forward looking. Wirth, Pascal's designer, invented it (in his words) to foster a "systematic discipline" of programming that would be implemented so as to be "reliable and efficient on presently available computers". Do we want to impose a "systematic discipline" on the purchasers of personal computers? The very opposite is true. Are we really concerned with saving the computer occasional microseconds? No, we are concerned with saving the human hours of thought and work.

APL, from its very inception, was interactive as far as a Selectric terminal would allow. The human being was treated as supreme, the machine as his or her servant. I, being a human and not a machine rather prefer this orientation.

In a number of ways, such as consistency, elegance, and power at handling array and matrix structures (of numbers or strings) APL is unmatched. On the other hand, APL uses a eccentric notation replete with Greek characters and a hodge-podge of unique symbols that make it look very strange indeed. Iverson was trying to invent a new notation for mathematics, and mathematicians never quail at creating obscure symbols. This notation has been a millstone about APL's neck. There is also a feeling that APL works from right to left, which people find strange. This accusation is true, but Iverson was only being consistent where most of us (and most of our programming languages) are inconsistent. For example, look at expressions such as

SIN (TAN (COS (3 * (PI/2))))

To evaluate this, you start nearly at the right, evaluate PI/2, then multiply it by 3, then take the cosine, then the tangent and finally we get to the left and take the sine. See! you do work from right to left.

Iverson, realizing how troublesome the rules of precedence are (he is so right, as anybody who has taught programming knows), and being consistent, has everything evaluated from right to left in expressions. And APL is almost all expressions. As a consequence, APL is easy to teach, easy to learn, easy to parse, and looks most peculiar to people brought up on other computer languages. APL is also notoriously slow to execute, and until Abram's work, it seemed impossible to make it efficient.

With these black marks against it, it is only APL's extreme learnability, interactive environment, great power, and human programming speed that have kept it alive at all.

Another comment that one often hears is that an APL program is unreadable, undocumentable, and only can be used by the person who wrote it. All this is usually true. Of course, if the main use of a personal computer is for "throw- away" programs that are used but once, or perhaps only a few times (and this is often the case) then these objections have little force.

These problems are not inherent to the idea of using expressions as does APL. They are partly due to the style in which APL is taught, and mostly due to the particular embodiment of the language, not to its concepts. Most APL programmers take little trouble to make programs readable, as there is a temptation to do as much as possible in as few symbols as possible. The mechanism for introducing comments is extremely difficult to type, and its use is not encouraged by any books on the subject. Most of Iverson's pamphlets don't even mention comments.

Given the good and bad of APL, Apple is an attempt to keep the good, and ameliorate the bad. Apple uses the common subset of the ASCII and ISO character sets rather than Iverson's special character set. Many unique symbols are replaced by readable keywords. A typical example is that Apple uses SIN and ARCTAN rather than 1o and -3o to represent the sine and arctangent functions respectively.

I must admit that English keywords diminish a languages international appeal to a slight degree--BASIC, FORTRAN and Pascal usually keep their English keywords in most non-English speaking countries.

Out of context, some of Iverson's conventions may seem counterproductive or even stupid. This is not the case. If you had to sit in front of a 15 character per second terminal, you would welcome shortening a function name by even a single letter. The personal computer's fast screen gives the present design much freedom that Iverson did not have. Even the comments made above about Pascal should be seen charitably: Wirth was countering languages that did not aid in teaching rigourous, professional programming practices and that included the concept of structured data types. His primary environment was a large, card-entry, batch processed computer center. Pascal, too, is a work of considerable brilliance. In the kinds of world Wirth was considering for Pascal, where hours separate runs and computer time is precious, Pascal is superior to its predecessors (including APL). Just observe that even when it isn't explicitly mentioned, the programmer's environment conditions the design of a language to a great degree.

Some Details of Apple, Justified

Jean Sammet, in her book "Programming Languages", after some quite positive comments, said of APL, "I cannot become enthusiastic about a language that has this notational complexity." James Martin, in his book "Design of Man-Machine Dialogues" observed that "It was easy for a person who was not a professional programmer to become hooked on APL." These statements are in contradiction. If the notation of APL is truly complex, then why is it so easy for non- programmers? Because they have no prejudices to work against. Apple is an attempt to cure the disease of notational complexity that Sammet complains about, while retaining and enhancing the features that make APL so addictive to novices.

One of the easiest things to do with APL to make it more useable is to reverse the order of evaluation. As this document attempts to show, this should make Apple especially easy for the millions of people who have used pocket calculators. The next thing that was done was to change the peculiar symbols into keywords, which had the beneficial side-effect of totally eliminating the tedious requirement in APL for backspacing and overstriking to create new symbols.

Iverson's confusing use of a single symbol to represent two related (sometimes very ingeniously related) functions, one of which is monadic and the other dyadic has been eliminated in favor of simply having two separate function names. A bit of mathematical insight is lost in favor of much mnemonic convenience.

A Rosetta Stone

A number of ideas from other languages have been adopted. The alternating use of single and double quotes from SNOBOL, the range notation from Pascal, and others that the knowledgeable reader will notice. It might be interesting to extend the example on page 64 of Martin's "Design of Man-Machine Dialogues" for inclusion here. The same simple program is presented in a number of different languages. In each case the program produces the average of a list of real numbers. In all but Apple and APL, the list has an limit of 100 items. In Apple and APL there is no limit beyond the amount of available memory.

I have taken the liberty of modernizing the BASIC example, and have written examples in Pascal and Apple.

FORTRAN

DIMENSION X (100) READ (5,10) N, (X(I), I= 1,N) 10 FORMAT (I5, (E15.2)) S = 0.0 DO 9 I=1,N 9 S = S + X(I) A = S/N WRITE (6,20)A 20 FORMAT (E15.2) END .ul BASIC

20 S = 0 30 READ N 40 FOR I = 1 TO N 50 READ X 60 S = S + X 70 NEXT I 80 A = S/N 90 PRINT A 100 DATA {the data on which the program would operate goes here, 110 and perhaps on the next few lines.} 120 END

Pascal

PROGRAM AVERAGE; VAR ITEM,N,SUM: REAL; SUM := 0.0; READ (N); FOR I := 1 TO N DO BEGIN READ (ITEM); SUM := SUM + ITEM END; WRITELN (SUM/N); END.

PL\I

DCL X (100) INITIAL (0); GET LIST (N, (X(I) DO I = 1 TO N)); PUT LIST (SUM (X)/N);

APL

+/X- X < []

(Using p for rho, : for the division sign, <- for the left arrow, and [] for the box we could write it +/Xp:X<-[]. This is done just in case the program segment above has not been filled in by hand with the actual APL symbols.)

APPLE

INPUT: many.numbers many.numbers INSERT + / (many.numbers LENGTH)

Commentary on the Languages

Which ones are immediately readable to you depends on what you are used to. I remember being told that a Pascal program was really easy to read, even if you didn't know Pascal. At the time, I didn't know Pascal, and I couldn't read it, or even figure out much about it. Now it looks as clear as good English to me. So do all the other examples.

One obvious difference in the examples is their lengths. For the purposes of these counts, I have not counted extraneous spaces introduced for the purpose of clarity, and all variable names are counted as one character in length. The DATA statements in BASIC have also not been counted. Taking a BASIC program as being of length 1, then FORTRAN is 1.5, Pascal 1.2, PL\I .85, Apple .3 and APL an amazing .08. These relative lengths depend very strongly on the algorithm being represented. Pascal and PL\I improve strongly as things get more complex. FORTRAN, APL and Apple (again, relative to BASIC) improve slightly with increasing complexity.

Some Additional Features of Apple (a potpourri of notes to myself)

Compared to APL, string operations are given more prominence in Apple. Graphics are an integral part of the language, although they do not appear at all in APL. Some notations from other languages have been substituted for Iverson's, especially notable is the use of Pascal's abbreviated ellipsis for the iota. This also allows expressions to be more readable when the range does not begin with 1. (Suggestion of R. Kelly). The PROGRAM function is based on APL's evaluate. Apple makes decisive use of upper and lower case.


Document created on 6 June 2000;