Help / JforC / Preliminaries

From J Wiki
< Help(Redirected from Help/JforC/Preliminaries)
Jump to navigation Jump to search


>> << Pri JfC LJ Phr Dic Voc !: Rel NuVoc wd Help J for C Programmers


                                                                                                                               3.     Preliminaries

Notation Used in This Book

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

(#define macro)

conjunction

(#define macro)

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.  The closest thing C has to a modifier is a preprocessor macro which can accept function names as data and produce code sequences including the name.  J modifiers perform their actions during execution rather than compilation, providing opportunities unknown to C.

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.

Comments

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

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

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.  We will discuss complex numbers and exponential forms in the chapters on mathematics; the more usual forms are:

2

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

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

1e3 (the same as 1000)

16b1f (equivalent to 0x1f; the 16b indicates a base-16 number)

_ (infinity, which is a perfectly valid number in J)

__ (negative infinity, represented by two underscores)

_.  (indeterminate, the result you get from something like _-_ .  Don't get the idea that it would be clever to use _. to indicate a special data value: _. is hard to test for and gives wildly unpredictable results.  Treat _. as an indication that you have a bug you'd better fix)

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.

Adjacent Numbers Form a Single Word

Numbers separated by whitespace are treated as a single word whose value is the list of the numbers (we will learn all about lists soon--they're like arrays).  Remember, word formation is the first step in processing a sentence, so the numbers are welded into a list before anything else can be done with them.  This may cause you a problem if you have adjacent numbers that should not be made into a list.  In that case, put parentheses around any number you want to keep separate.

You will quickly learn that lists of numbers are so common in J that creating them automatically from adjacent numbers saves you a lot of typing.

Adjacent Named Nouns Do NOT Form a Single Word

Because the adjacent numbers 4 5 are turned into a list, you might think that a b, when a and b have the values 4 and 5, would also be turned into a list.  Not so.  4 5 becomes a list before any of the names are examined; at that point the interpreter does not even know the part of speech of the names.  a and b remain as separate words, to be operated on as execution proceeds.

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 cant'.  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).  J verbs also come in unary and binary versions, with the addition that this applies to all verbs, both primitive and user-defined verbs.

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).

There is no ambiguity over which kind of invocation is used in any particular case.  If dyadic invocation is possible, dyadic is used.  So, in 5 - 2, the dyadic form of - is used; in 5 + - 2, the monadic form of - is used.

Each verb-name really stands for two verbs, one that handles monadic invocations and one that handles dyadic.  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.

Note: private and public names exist in different namespaces.  Referencing a variable checks for the private name first, followed by the public one.  Assignment to a public name when the same name is defined in the private namespace is almost always a blunder, so it is flagged as an error.

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 * 1 + 4

consists of execution of the following fragments: 1 + 4 with result 5; 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.

If a verb has a noun on its left, it is executed as a dyadic verb with a left and right operand.  If the verb does not have a noun on its left, it is executed as monadic with just a right operand.  You must know the part of speech of the names in a sentence to understand the execution order.  In the sentence

   result =. name1 verb2 5

you must know whether name1 is a verb, in which case verb2 is executed monadically and the result is name1(verb2(5)), or name1 is a noun, in which case verb2 is dyadic and the result is (name1 verb2 5) .

How Names Are Substituted

When a sentence contains names, the sentence is executed as if each name were enclosed in parentheses and then replaced by its value.  If a has the value 4 and b has the value 5,

   a + b

is equivalent to

(4) + (5)

Enclosing the value in parentheses is a necessary step to get the order of evaluation right, just as in ordinary arithmetic, where if a is x+2 and b is y, ab is not x+2y, but (x+2)y.

If you read the Dictionary you will soon encounter the example

   mean=: +/ % #
   mean 2 3 4 5 6
4

and you will probably follow in the footsteps of countless J neophytes, typing into your J session

   +/ % # 2 3 4 5 6
0.2

and be baffled by the result.  Why 0.2 instead of 4?  Because you left out the parentheses:

   (+/ % #) 2 3 4 5 6
4

In this book, the discussion of what (+/ % #) means will be deferred until we discuss modifiers.  Later, when we discuss Tacit Programming, it will be revealed that our notion of replacing a name with its parenthesized value is a simplification of the actual process of execution.  Forget that for now--you are highly unlikely to encounter a situation where the simplification leads you into error.

Using the parenthesized-substitution rule, we can justify the difference between

4 5

and

a b

when a is 4 and b is 5 .  4 5 is two adjacent numbers, which are always treated as a single word.  a b is equivalent to (4) (5), which is not two adjacent numbers but rather a syntax error.

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'--after the most rudimentary syntax checking, 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.

Note on special names

J uses the names x, y, u, v, m, and n to represent arguments to verbs and other entities.  You should avoid using these names for other purposes.

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'

In early versions of J, the operands of a verb were named x. and y. rather than x and y .  Some old verbs use these forms.  If you want to use it you must execute 9!:49 (1) to enable recognition of the old forms.

Running a J program

No compiling.  No linking.  No makefiles.  No debugger required.  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++(tm) 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, signal it to stop by running the Jbreak program that is supplied as part of the J installation.  Control will return 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, and 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, nothing will be executed until you press ENTER, and then only the line containing the cursor will be executed.

It is important to remember that the script windows exist only for your convenience in editing and are not used during execution.  If you make a change to a script window, you need to Run that window to cause the lines in the script to be executed.

If you are debugging a script and you remove a definition from the script and Run it, the definition will not be removed from the J session.  Running the script is like entering the sentences one by one from the keyboard, and not-defining the name does nothing to expunge an established definition.  To remove the old definition, use 4!:55 <'expiredname' or start a fresh session of J.

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.ijsboot.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.

For more information, including how to add your own initial definitions, see the section on Startup under "Odds and Ends".

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 for C Programmers (this book);

Learning J, by Roger Stokes, a book comparable in scope to this book;

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).

Reference Card

A Reference Card with a terse description of most of the primitives of J can be found in the J Wiki at http://code.jsoftware.com/wiki/HenryRich .  It looks best when printed in color.

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.


>> << Pri JfC LJ Phr Dic Voc !: Rel NuVoc wd Help J for C Programmers