|
Chapter 1: Basics
1.1 Interactive Use
The user types a line at the keyboard. This input line may be an expression, such as
2+2. When the line is entered (by pressing the "enter" or "carriage return" key), the
value of the expression is computed and displayed on the next line.
2+2
4
The user is then prompted for another line of input.
The prompt is seen by the cursor being positioned a few spaces from the left margin.
Thus in this book, a line indented by a few spaces represents input typed by a user,
and a following line, not indented, represents the corresponding output.
1.2 Arithmetic
The symbol for multiplication is * (asterisk).
2*3
6
If we try this again, this time typing 2 space * space 3
2 * 3
6
the result is the same as before, showing that the spaces here are optional.
Spaces can make an expression more readable.
The symbol for division is % (percent).
3 % 4
0.75
For subtraction, we have the familiar - symbol:
3 - 2
1
The next example shows how a negative number is represented. The negative sign is a leading _ (underscore) symbol, with no space between the sign and the digits of the number. This sign is not an arithmetic function: it
is part of the notation for writing numbers, in the same way that a decimal point is part of the notation.
2 - 3
_1
The symbol for negation is -, the same symbol as for subtraction:
- 3
_3
The symbol for the power function is ^ (caret). 2 cubed is 8:
2 ^ 3
8
The arithmetic function to compute the square of a number has the symbol *: (asterisk colon).
*: 4
16
1.3 Some Terminology: Function, Argument, Application, Value
Consider an expression such as 2 * 3.
We say that the multiplication function * is applied to its arguments.
The left argument is 2 and the right argument is 3. Also,
2 and 3 are said to be the values of the arguments.
1.4 List Values
Sometimes we may wish to repeat the same computation several times
for several different numbers.
A list of numbers can be given as 1 2 3 4, for example, written with a space between
each number and the next.
To find the square of each number in this list we could say:
*: 1 2 3 4
1 4 9 16
Here we see that the "Square" function (*:) applies separately to each item in the list.
If a function such as + is given two list arguments, the function applies separately to
pairs of corresponding items:
1 2 3 + 10 20 30
11 22 33
If one argument is a list and the other a single item, the single item is replicated as needed:
1 + 10 20 30
11 21 31
1 2 3 + 10
11 12 13
Sometimes it is helpful, when we are looking at a new function, to see how a pattern
in a list of arguments gives rise to a pattern in the list of results.
For example, when 7 is divided by 2 we can say that the quotient is 3
and the remainder is 1. A built-in J function to compute remainders is | (vertical bar),
called the "Residue" function. Patterns in arguments and results are shown by:
2 | 0 1 2 3 4 5 6 7
0 1 0 1 0 1 0 1
3 | 0 1 2 3 4 5 6 7
0 1 2 0 1 2 0 1
The Residue function is like the familiar "mod" or "modulo" function, except that we
write (2 | 7) rather than (7 mod 2)
1.5 Parentheses
An expression can contain parentheses, with the usual meaning; what is inside
parentheses is, in effect, a separate little computation.
(2+1)*(2+2)
12
Parentheses are not always needed, however.
Consider the J expression: 3*2+1. Does it mean (3*2)+1, that is,
7, or does it mean 3*(2+1) that is, 9 ?
3 * 2 + 1
9
In school mathematics we learn a convention, or rule, for writing expressions:
multiplication is to be done before addition. The point
of this rule is that it reduces the number of parentheses we need to write.
There is in J no rule such as multiplication before addition. We can always write
parentheses if we need to. However, there is in J a parenthesis-saving rule,
as the example
of 3*2+1 above shows. The rule, is that, in the absence of parentheses,
the right argument of an arithmetic function is everything to the right.
Thus in the case of 3*2+1, the right argument of * is 2+1.
Here is another example:
1 + 3 % 4
1.75
We can see that % is applied before +, that is, the rightmost function
is applied first.
This "rightmost first" rule is different from, but plays the same role as,
the common convention of
"multiplication before addition". It is merely a convenience:
you can ignore it and write parentheses instead.
Its advantage is that there are, in J, many (something like 100)
functions for computation with numbers and it would be out of the question
to try to remember which function should be applied before which.
In this book, I will on occasion show you an expression having some parentheses
which, by the
"rightmost first" rule, would not be needed.
The aim in doing this is to emphasize the structure
of the expression, by setting off parts of it, so as to make it more readable.
1.6 Variables and Assignments
The English-language expression:
let x be 100
can be rendered in J as:
x =: 100
This expression, called an assignment, causes the value 100 to be assigned to the name x.
We say that a variable called x is created and takes on the value 100.
When a line of input containing only an assignment is entered at the computer, then
nothing is displayed in response.
A name with an assigned value can be used wherever the value is wanted in
following computations.
x - 1
99
The value in an assignment can itself be computed by an expression:
y =: x - 1
Thus the variable y is used to remember the results of the computation x-1 .
To see what value has been assigned to a variable, enter just the name of the
variable.
This is an expression like any other, of a particularly simple form:
y
99
Assignments can be made repeatedly to the same variable; the new value supersedes the current value:
z =: 6
z =: 8
z
8
The value of a variable can be used in computing a new value for the same variable:
z =: z + 1
z
9
It was said above that a value is not displayed when a line consisting of an
assignment is entered.
Nevertheless, an assignment is an expression: it does have a value which can take part in a larger
expression.
1 + (u =: 99)
100
u
99
Here are some examples of assignments to show
how we may choose names for variables:
x =: 0
X =: 1
K9 =: 2
finaltotal =: 3
FinalTotal =: 4
average_annual_rainfall =: 5
Each name must begin with a letter. It may
contain only letters (upper-case or lower-case),
numeric digits (0-9) or the underscore character
(_). Note that upper-case and lower-case letters
are distinct;
x and X are the names of distinct variables:
x
0
X
1
1.7 Terminology: Monads and Dyads
A function taking a single argument on the right is called a monadic function, or a monad for short.
An example is "Square", (*:). A function taking two arguments, one on the left and one on the right,
is called a dyadic function or dyad. An example is + .
Subtraction and negation provide an example of the same symbol (-) denoting two different functions.
In other words, we can say that - has a monadic case (negation)
and a dyadic case (subtraction).
Nearly all the built-in functions of J have both a monadic and a dyadic case.
For another example, recall that the division function is %, or as we now say, the dyadic
case of % . The monadic case of % is the reciprocal function.
% 4
0.25
1.8 More Built-In Functions
The aim in this section is convey a little of the flavour of
programming in J by looking at a small further selection of
the many built-in functions which J offers.
Consider the English-language expression:
add together the numbers 2, 3, and 4, or more briefly:
add together 2 3 4
We expect a result of 9. This expression is rendered in J as:
+ / 2 3 4
9
Comparing the English and the J, "add" is conveyed by the + and "together" is
conveyed by the / . Similarly, the expression:
multiply together 2 3 4
should give a result of 24. This expression is rendered in J as
* / 2 3 4
24
We see that +/2 3 4 means 2+3+4 and */2 3 4 means 2*3*4.
The symbol / is called "Insert",
because in effect it inserts whatever function is on its left
between each item of the list on its right.
The general scheme is that if F is any dyadic function
and L is a list of numbers a, b, c, .... y, z
then:
F / L means a F b F .... F y F z
Moving on to further functions, consider these three propositions:
2 is larger than 1 | (which is clearly true) |
2 is equal to 1 | (which is false) |
2 is less than 1 | (which is false) |
In J, "true" is represented by the number 1 and and "false" by the number 0.
The three propositions are rendered in J as:
2 > 1
1
2 = 1
0
2 < 1
0
If x is a list of numbers, for example:
x =: 5 4 1 9
we can ask: which numbers in x are greater than 2?
x > 2
1 1 0 1
Evidently, the first, second and last, as reported by the 1's in the result
of x > 2.
Is it the case that all numbers in x are greater than 2?
* / x > 2
0
No, because we saw that x>2 is 1 1 0 1.
The presence of any zero ("false") means the the multiplication
(here 1*1*0*1) cannot produce 1.
How many items of x are greater than 2? We add together the 1's in x>2:
+ / x > 2
3
How many numbers are there altogether in x? We could add together the 1's in x=x.
x
5 4 1 9
x = x
1 1 1 1
+/ x = x
4
but there is a built-in function # (called "Tally")
which gives the length of a list:
# x
4
1.9 Side By Side Displays
When we are typing J expressions into the computer, expressions and results follow each other
down the screen.
Let me show you the last few lines again:
x
5 4 1 9
x = x
1 1 1 1
+/ x = x
4
# x
4
Now, sometimes in this book I would like to show you a few lines such as these,
not one below the other but side by side across the page, like this:
x |
x = x |
+/ x = x |
# x |
5 4 1 9 |
1 1 1 1 |
4 |
4 |
This means: at this stage of the proceedings,
if you type in the expression x you
should see the response 5 4 1 9. If you now type in x = x you should see 1 1 1 1, and so on.
Side-by-side displays
are not a feature of the J system, but merely figures, or illustrations, in this book. They show
expressions in the first row, and corresponding values below them in the second row.
When you type in an assignment (x=:something), the J system does not show
the value. Nevertheless, an assignment is an expression and has a value.
Now and again it might be helpful to see, or to be reminded of,
the values of our assignments, so
I will often show them in these side-by-side displays. To illustrate:
x =: 1 + 2 3 4 |
x = x |
+/ x = x |
# x |
3 4 5 |
1 1 1 |
3 |
3 |
Returning now to the built-in functions, suppose we have a list.
Then we can choose items
from it by taking them in turn and saying
"yes, yes, no, yes, no" for example.
Our sequence of choices can be represented as
1 1 0 1 0.
Such a list of 0's and 1's is called a bit-string
(or sometimes bit-list or bit-vector).
There is a function, dyadic #, which can take a bit-string (a sequence of choices)
as left argument to select chosen items from the right argument.
y =: 6 7 8 9 10 |
1 1 0 1 0 # y |
6 7 8 9 10 |
6 7 9 |
We can select from y just those items which
satisfy some condition, such as: those which are
greater than 7
y |
y > 7 |
(y > 7) # y |
6 7 8 9 10 |
0 0 1 1 1 |
8 9 10 |
1.10 Comments
In a line of J, the symbol NB. (capital N, capital B dot) introduces a comment.
Anything following NB. to the end of the line is not evaluated.
For example
NB. this is a whole line of annotation
6 + 6 NB. ought to produce 12
12
1.11 Naming Scheme for Built-In Functions
Each built-in function of J has an informal and a formal name.
For example, the function with the formal name + has the informal name
of "Plus". Further, we have seen that there may be monadic and dyadic cases
, so that the formal name - corresponds to the informal names
"Negate" and "Minus".
The informal names are, in effect, short descriptions, usually
one word. They are not recognised by the J software, that is,
expressions in J use always the formal names. In this book, the informal
names will be quoted, thus: "Minus".
Nearly all the built-in functions of J have formal names with one character or
two characters.
Examples are the * and *: functions.
The second character is always either : (colon) or .
(dot, full stop, or period).
A two-character name is meant to suggest some relationship to a basic one-character
function.
Thus "Square" (*:) is related to "Times" (*).
Hence the built-in J functions tend to come in families of up to 6 related
functions.
There are the monadic and dyadic cases, and for each case there are the basic,
the colon and dot variants.
This will be illustrated for the > family.
Dyadic > we have already met as "Larger Than".
Monadic > we will come back to later.
Monadic >. rounds its argument up to an integer.
Note that rounding is always upwards as opposed to rounding to the nearest integer.
Hence the name: "Ceiling"
>. _1.7 1 1.7
_1 1 2
Dyadic >. selects the larger of its two arguments
3 >. 1 3 5
3 3 5
We can find the largest number in a list by inserting "Larger Of" between
the items, using /.
For example, the largest number in the list 1 6 5 is found
by evaluating (>. / 1 6 5). The next few lines are meant to convince you
that this should give 6. The comments show why each line should give
the same result as the previous.
>. / 1 6 5
6
1 >. 6 >. 5 NB. by the meaning of /
6
1 >. (6 >. 5) NB. by rightmost-first rule
6
1 >. (6) NB. by the meaning of >.
6
1 >. 6 NB. by the meaning of ()
6
6 NB. by the meaning of >.
6
Monadic >: is informally called "Increment". It adds 1 to its argument:
>: _2 3 5 6.3
_1 4 6 7.3
Dyadic >: is "Larger or Equal"
3 >: 1 3 5
1 1 0
This is the end of Chapter 1.
|