<<     >>     Contents     Help    

                                                                                                                               2.     Preliminaries

Notation

C code is set in Arial font, like this: for(I = 0;I<10;I++)p[I] = q;

J code is set in Courier New font, like this: p =. 10 $ q

When J and C use different words for the same idea, the J word is used.  The first few times, the C word may be given in parentheses, in Arial font: verb (function).  When a word is given a formal definition, it is set in bold italics: verb.

Terminology

To describe the elements of programming, J uses a vocabulary that will be familiar, though possibly frightening: the vocabulary of English grammar.  We will speak of nouns, verbs, and the like.  Don't worry, you're not going to have to write a book report!

Use of this terminology is not as strange as it may seem.  Take 'verb', for example, an idea that corresponds to the C 'function' or 'operator'.  Why not just say 'operator'?  Well, that word is also used in mathematics and physics, with a meaning quite different from C's.  Even a C 'function' is not a true mathematical function—it can return different values after invocations with the same arguments.

J avoids imprecise usage by choosing a familiar set of words and giving them entirely new meanings.  Since J is a language, the vocabulary chosen is that of English grammar.  It is hoped that the familiarity of the words will provide some mnemonic value, but as long as you learn the J meanings you are free to forget the grammatical ones.  The following table may help:

J word C word

verb

function or operator

noun

object

copula

assignment

punctuation

separator

adverb

(untranslatable)

conjunction

(untranslatable)

In keeping with the grammatical flavor of the vocabulary, we say that every word (token) in a J program has a part of speech (name type) which is one of the following: noun, verb, adverb, adjective, copula, or punctuation.

The primary parts of speech are noun, verb, adverb, and conjunction.  Every name we can create, and every word defined by J except for the copulas (=. and =:) and punctuation, will be a definite one of the primary parts of speech.  In this book, the term entity is used to mean something that can be any of the primary parts of speech.  An entity can be assigned to a name, but most entities are anonymous, appearing and disappearing during the execution of a single sentence (just like intermediate results in the evaluation of C expressions).

A noun holds data; a verb operates on one or two nouns to produce a result which is a noun; an adverb operates on one noun or verb to produce a derived entity; a conjunction operates on two nouns or verbs to produce a derived entity.  Adverbs and conjunctions are called modifiers.

A word on punctuation under J's definition: it consists of the characters ( ) ' and end-of-line (written LF but representing either a single LF character or the CRLF combination), along with the comment delimiter NB. and a few other special words like if. and case. .  There are a lot of other characters that you think of as punctuation, namely [ ] , . " ; { }, that J uses to do work.  You will be especially surprised to find that [ ] and { } are independent rather than matched pairs, but you'll get used to it.

Sentences (statements)

The executable unit in J is called the sentence, corresponding to the C statement.  The sentence delimiters in J (corresponding to the semicolon in C) are the linefeed LF and the control words like if. that we will learn about later.  A sentence comprises all the characters between sentence delimiters; since LF is a sentence delimiter, it follows that a J sentence must all fit on one line.  There is nothing corresponding to \<CR> in C that allows you to split a sentence across lines.

All comments start with NB. and run to the next LF .  The comment is ignored when the sentence is executed.

Word Formation (tokenizing rules)

J's names (identifiers) are formed much as in C.  Names must begin with an alphabetic, underscore is allowed, and upper- and lowercase letters are distinguished.  Names that end with an underscore or contain two consecutive underscores are special, and you should avoid them until you know what a locale is.

The ASCII graphic characters ('+', for example) are called primitives (operators) in J.  You will learn their meanings as we go on.

Any name or primitive (identifier or operator) can be made into a new primitive by adding '.' or ':' at the end.  Since all primitives are system-defined (i. e. they are reserved words), you may not put '.' or ':' in your names.  No space is required after a primitive.  The part of speech for each primitive is fixed.  Example primitives are:

+ +. +: { {: {:: i. i: for. select. case. end.

The first step in processing a sentence is to split it into words.  The words correspond roughly to C tokens, after making allowance for the special status of the '.' and ':' characters.  The space and TAB characters are treated as whitespace.  One big surprise will be that a sequence of numbers separated by spaces is treated as a single word which denotes the entire list of numbers.

We will be careful to distinguish periods used for English punctuation from the dot that may be at the end of a primitive.  When a J word comes at the end of an English sentence, we will be sure to leave a space before the period.  For example, the verb for Boolean Or is +., while the verb for addition is .

Numbers

You do not need to trouble yourself with the distinction between integers, floats, and complex numbers.  If it's a number, J will handle it properly.  There are a great many ways to specify numbers; consult the Dictionary to learn details, including, among other things, complex numbers, extended-precision integers, and exponential forms.  Example numbers are:

2

_2 (underscore, not -, is the negative sign)

0.5 (since '.' is special, it must not be the first character of a number)

1e2

16b1f (equivalent to 0x1f)

_ (infinity)

__ (negative infinity, represented by two underscores)

A noun whose value is one of the numbers 0 and 1 is said to be Boolean.  Many verbs in J are designed to use or produce Boolean values, with 0 meaning false and 1 meaning true, but there is no Boolean data type: any noun can be used as a Boolean if its values are 0 or 1.

A word is in order in defense of the underscore as the negative sign.  -x means 'take the negative of the number x'; likewise -5 means 'take the negative of the number 5'.  In J, the number 'negative 5' is no cloistered companion, accessible only by reference to the number 5: it is a number in its own right and it deserves its own symbol: _5.

Characters

An ASCII string enclosed in single quotes is a constant of character type (examples: 'a', 'abc').  There is no notation to make the distinction between C's single-quoted character constants and double-quoted character strings.

There are no special escape sequences such as '\n'.  If you need a quote character inside a string, double the quote: 'cannot can be shortened to can''t'.  Character constants do not include a trailing NUL (\0) character, and NUL is a legal character within a string.

Valence of Verbs (Binary and Unary Operators)

C operators can be unary or binary depending on whether they have one or two operands; for example, the unary * operator means pointer dereferencing (*p), while the binary * operator means multiplication (x*y).

Similarly, when a J verb (function or operator) is executed with only one operand (i. e. without a noun or phrase that evaluates to a noun on its left) we say its invocation is monadic (unary); if there is a noun or noun-phrase on its left, that noun becomes a second operand to the verb and we say that the invocation is dyadic (binary).  In the case of programmer-defined verbs (functions), the versions handling the two cases are defined independently.  We use the term valence to describe the number of operands expected by a verb-definition: a verb-definition has monadic valence if it can be applied only monadically, dyadic valence if it can be applied only dyadically, and dual valence if it can be applied either way.  Since the definitions of the monadic and dyadic forms of a verb can be wildly different, when we name a verb we will be careful to indicate which version we are talking about: 'monad $', 'dyad i.'.

Note that it is impossible to invoke a verb with no operands.  In C we can write func(), but in J we always must give an operand.

Note also that the syntax of J limits verbs (functions) to at most two operands.  When you need a verb with more than two operands, you will represent it as a monad or dyad in which one of the verb's syntactic operands is an aggregate of the actual operands the verb will use during its execution.  The first thing the verb will do is to split its operand into the individual pieces.  J has primitives to make this process easy.

The value produced by any entity when it is applied to its operand(s) is called its result (returned value).

How Names (Identifiers) Get Assigned

Assignment in J is performed by expressions of the form

name =. entity  NB. private

and

name =: entity  NB. public

Names assigned by public assignment are visible outside the entity in which they are defined; names assigned by private assignment usually are not; we will learn the details when we discuss modular code.  The difference between the two forms of assignment is in the character following the = .  Just as in C, the assignment expression is considered to produce as its result the value that was assigned, so expressions like

a =. 1 + b =. 5

are legal.  J calls =. and =: copulas.  Just as in C, the entity that is assigned to the name can be the result of evaluating an expression.

There are a number of additional capabilities of J assignment that you can read about in the Dictionary.  One that has no counterpart in C is that the name being assigned can itself be a variable, i. e. you can calculate the name that you want to assign the value to.

The value assigned can be a noun (object), verb (function), adverb, or conjunction; the name then becomes whatever part of speech was assigned to it (even if it was previously defined as a different part of speech!).  For example,

n =: 5

creates a noun, and

v =: verb define

x. + y.

)

creates a verb (more below).

 Note: the J Dictionary uses the terms 'local' and 'global' instead of 'private' and 'public'.  I think 'private' and 'public' are more accurate terms, because there is another dimension to name scope in J, using the J notions locale and path, that causes public variables to be visible only in certain entities.  It will be a long time before we learn about locales; until then, public names will be global.

Order of Evaluation

Forget the table of operator precedence!  All J verbs (functions and operators) have the same priority and associate right-to-left.  For example, a * b + c is equivalent to a * (b + c), not (a * b) + c.  Use care when copying mathematical formulas.  Note that the negative sign _ is a part of the number, not a verb.  _5 + _4 is _9, while -5 + -4 is _1.

The executable bits of a sentence (statement) are called fragments (subexpressions).  A verb with its operand(s) is a fragment, as is a copula with its name and value.  We will meet other types of fragment later.  Execution of a sentence consists of the right-to-left execution of its fragments, with the result of each fragment's execution replacing the fragment and being passed as an operand into the next fragment.  The result of the last execution becomes the result of the sentence.  This result is usually a noun but it can be any of the primary parts of speech.  As an example, execution of the sentence

   a =. 3 + b =. 4 * 5

consists of execution of the following fragments: 4 * 5 with result 20; b =. 20 with result 20; 3 + 20 with result 23; a =. 23 with result 23 .  The names a and b are assigned when the assignment fragments are executed.

What a verb (function) looks like

As we saw, a J verb (function) is defined by lines that look like:

name =: verb define

J sentences here

)

The result of the verb define is a verb, and normally you will assign the result to a name so you can execute the verb by name when you need it.  Subsequent lines, starting with the one after verb define and ending before the next line containing only the word ')', are read and saved as the text of the verb (heaven help you if you leave out the )!).  The verb is not 'compiled'—only the most rudimentary syntax checking is performed; the text is saved and will be interpreted when the verb is executed.

Each line of the verb is a sentence (statement).  The result of the last sentence executed becomes the result of the whole verb (this is not precisely true but it's close enough for now—details will be revealed in 'Control Structures').

Since a J verb has only one or two operands, there is no need for you to provide a list of parameter names as you do in a function definition in C; instead, J names them for you.  At the start of a verb's execution, the private name y. is initialized with the value of the right operand of the verb.  If the verb is dyadic, the private name x. is initialized with the value of the left operand.  Many programmers like to start their verbs by assigning these values to more descriptive names.

If your verb is going to define only a monadic or dyadic form, you should use monad define or dyad define instead of verb define .  If you are going to define both valences, the way to do so is:

name =: verb define

monadic case here

:

dyadic case here

)

where a line with the single word : separates the two cases.  If you use verb define and don't have the :, the verb will be monadic.

If your verb is only one line long (not at all unusual in J!) you can define it all in one line by using the appropriate one of the forms

name =: monad : 'text of verb'

name =: dyad : 'text of verb'

Running a J program

No compiling.  No linking.  No makefiles.  No debugger.  You simply type J sentences and the interpreter executes them and displays any result.  At the very simplest, you can use it as a desk calculator:

   22 + 55

77

J prints 3 spaces as a prompt, so when you scroll through the log of a session, your input will be indented 3 spaces while J's typeout will be unindented.  The result of a sentence typed on the keyboard is displayed, except that to avoid excessive typeout nothing is displayed if the last fragment executed in the sentence is an assignment.  If you are at the keyboard while you are reading this book, you can type the examples and see the responses, or experiment on your own.

Here is a simple program to add twice the left argument to three times the right argument:

   add2x3y =: dyad : '(2 * x.) + 3 * y.'

We can run this program by giving it operands:

   1 2 3 add2x3y 4 5 6

14 19 24

Instead of simply displaying the result, we can assign it to a noun:

   a =: 1 2 3 add2x3y 4 5 6

We can inspect the value assigned to the noun by typing the name of the noun:

   a

14 19 24

We can use the noun in an expression:

   2 * a

28 38 48

We can create a new verb that operates on the noun:

   twicea =: monad : '2 * a'

   twicea ''

28 38 48

Notice the '' after the invocation of twicea.  Remember, to invoke a verb you must give it an operand, even if the verb doesn't use an operand.  '' is just an empty string; 0 or any other value would work too.  If you leave out the operand, J will show you the value of the name; since twicea is a verb, its value is the definition of the verb:

   twicea

3 : '2*a'

Of course, in any practical application you will need to have most of your programs in a library so you can quickly make them all available to J.  J calls these libraries scripts (filename extension  '.ijs') and runs them with the load verb, for example:

load 'system\packages\misc\jforc.ijs'

load reads lines from the script and executes them.  These lines will normally be all the verb and noun definitions your application needs, possibly including load commands for other scripts.  A script may end with a line executing one of the verbs it defined, thereby launching the application; or, it may end after defining names, leaving you in control at the keyboard to type sentences for J to execute.

Note: Names defined by private assignment (using =.) when a script is loaded are not available outside the script.  If you want to define names for use elsewhere, make sure you use =: for your assignments within a script.

If you are used to debugging with Visual C++™ or the like, you will find the environment less glitzy and more friendly.  If you want to change a verb (function), you simply edit the script, using the editor of your choice (I use the built-in editor provided with J), and rerun it.  The verb will be updated, but all defined nouns (objects) will be unchanged.  Even if you are running a large application—yea, even if the application is in the middle of reading from an asynchronous socket—you can change the program, without recompiling, relinking, or reinitializing.  If you'd like to add some debugging code while the system is running, go right ahead.  This easy interaction with an executing program is one of the great benefits of programming in J.

Interrupting Execution

If a J verb is taking too long to run, press the BREAK key (Ctrl+BREAK, in Windows) to return control to the keyboard.

Errors

When a sentence contains an error, J stops and displays the sentence along with a terse error message.  Refer to the chapter on Error Messages for explanation of the error.

The Execution Window; Script Windows

When J starts it displays its execution window.  The title of the execution window ends with the characters '.ijx'.  The only way to have a sentence executed is to have the sentence sent to the execution window.  The simplest way to do that is by typing the sentence into the execution window, as we have been doing in the examples so far.

The execution window is an edit window and a session log as well as a place to type sentences for execution.  If you put the cursor on some line other than the last and press ENTER, the line you were on will be copied to the bottom of the session log as if you had typed it for execution.  You can then edit the line before pressing ENTER again to execute it.

For convenience in editing, you may create other windows which will be script windows.  Usually these windows will contain J scripts that you are working on: the editor that manages the script windows is familiar with the syntax of J.  You create a script window by clicking File on the Menu Bar and then selecting New ijs, Open, or Recent.

Sentences that you type into a script window are not automatically executed by J; you must copy them into the execution window to have them executed.  You can use the script-window editor to send lines from a script to the execution window: click Run on the Menu Bar and then File, Selection, or Window as appropriate.

To run a selection of lines from a script window, be sure to use Run|Selection rather than cut-and-paste.  If you paste a number of lines into the execution window, only the last one will be executed.

Names Defined at Startup

When J starts, a number of useful names are defined.  Rather than discuss them all, I will show you how they come to be defined so you can study them when you need to.

When J starts, it executes the script J-directory\system\extras\config\profile.ijs which then executes the script J-directory\system\extras\util\boot.ijs .  boot.ijs in turn executes a series of scripts in J-directory\system\main which define the starting environment.  Look at these scripts to see what they define.

If you want to add your own initial definitions, do so either by adding commands at the end of profile.ijs or by creating your own startup script in J-directory\system\extras\config\startup.ijs .

Step-By-Step Learning: Labs

The Labs are interactive demos describing various topics in J.  To run the lab for printf, start a J session, on the menu bar select Studio|Labs…, then select the lab you are interested in, then press 'Run'.  The lab provides explanatory text interspersed with examples executed in your J session which you are free to experiment with as you step through the lab.

I recommend that every now and again you tarry a while among the labs, running whichever ones seem interesting.  Much of the description of the J system can be found only there.

J Documentation

The J documentation is available online.  Pressing F1 brings up the Vocabulary page, from which you can quickly go to the Dictionary's description of each J primitive.  At the top of each page of documentation are links to the manuals distributed with J: these are:

The Index to all documentation;

The User Manual which describes components of J that are not in the language itself, including system libraries and external interfaces;

The J Primer, an introduction to J;

J Phrases, a collection of useful fragments of J (you will need to finish this book before trying to use J Phrases);

The J Dictionary, the official definition of the language;

Release Notes for all releases of J;

A description of foreign conjunctions (!:);

A description of the operands to the wd verb (Windows interface).

Getting Help

Your first step in learning J should be to sign up for the J Forum at www.jsoftware.com.  A great many experienced J users monitor messages sent to the Forum and are willing to answer your questions on J, from the trivial to the profound.


<<     >>     Contents     Help