[comp.lang.apl] A preliminary review of J

news@usc.edu (09/20/90)

J is a fairly recent dialect of APL, greatly simplified in several
respects, and significantly enhanced in some others.  It includes
improvements slated for inclusion in APL dating, in some cases, all
the way back to the 60's.

I've been playing with version 2, which is not quite complete, and has
a clunky user interface, but I've been quite impressed.

If you're not interested, hit 'N' now.



J as a functional language (e.g. along the lines of scheme):

J has 0 keywords, and will take arguments from both sides of a
function, but if you don't mind the restriction, you can make it look
remarkably like scheme:

   o    =. 0 0$''                  }:' "nothing" -- very useful :-)'

   read =. 1!:1                    }:' associate name with system call'

   set  =. (read 1)::''            }:' scheme-like set'
(y. , '=: y.')::''                 }:' function which assigns data to name'

   indirect =. (read 1)::''        }:' converts 2 arg fns into a 1 arg form'
(y. , '&  y.')::''

   plus =. indirect '+'
   first=. indirect '{.'
   rest =. indirect '}.'

   o}:'     use of the above definitions:'

   ((set 'foo') 1 2 3 4 5)
1 2 3 4 5

   (first foo)
1

   (rest foo)
2 3 4 5

   ((plus 8) foo)
9 10 11 12 13



Their are, of course, a number of differences between J and scheme.
For example, if you wanted a structure more complicated than a simple
list of numbers or list of characters, you would need to use one of
J's structure building functions:

   (rest 'foo';'bar';'bletch')
.---.------.
|bar|bletch|
'---'------'

The boxes indicate that the enclosed lists (of characters) are being
treated as scalars.  The semicolons indicated that I wanted the
strings boxed and linked together in a list.



The parser is, well, very minimalist--roughly equivalent to LL(4)--and
available as a primitive function.  Evaluation and parsing are
synonymous.  (The lexical analyzer is also extremely simple, and
available as a primitive function.)  Also, for those of you not
familiar with apl, the parser runs right to left instead of left to
right.

J words fall into one of 6 syntactic classes:

Punctuation (left and right parenthesis)
Copulae (local assignment and global assignment)
Adverbs and Conjunctions (roughly equivalent to declarations)
[imperative] Verbs (functions)
Nouns (data)

Adverbs are distinct from conjunctions because they have different
syntax.  Primitive adverbs and conjunctions all appear to yield
verbs as their result.  Primitive functions all yield nouns.

Names can be assigned any type of word, except punctuation.  For example:

   test =. /
   a    =. +
   is   =. =.
   this is a test
   this 1 2
3

'test' became an adverb, 'a' became a verb, and 'is' became a copula.
'this is a test' assigned to 'this' the derived verb '+/' which has
the effect of placing the function '+' between each of the array cells
of its argument.



J differs from most other dialects of APL in a number of ways.  J is,
for example, statically scoped.

Also, it has 'phrasal forms' where several functions can be combined
to form a single function.  For example:

   3 (+,-,*,%) 2
5 1 6 1.5

Note that '*' means multiplication, and '%' means division.  If you
ask J to evaluate something which evaluates to a function, it will
show you the tree structure it uses to represent that function:

   +,-,*,%
.-.-.-------------.
| | |.-.-.-------.|
| | || | |.-.-.-.||
|+|,||-|,||*|,|%|||
| | || | |'-'-'-'||
| | |'-'-'-------'|
'-'-'-------------'

(That looks a lot better if you use the pc's line drawing
characters... oh well..)

Basically, in a phrasal form, like the above, the left and right
arguments to the derived function go to each the 'odd' functions, and
the results of those functions go to the 'even' functions.  So the
above example is equivalent to:

   (3+2),(3-2),(3*2),(3%2)
and yields the same result:
5 1 6 1.5

I haven't seen anything like this in any other computer language, so
it should look quite foreign to most of you.  I suppose the point I'm
trying to get across is that J allows an extremely wide range of
expressiveness.  Enough that style becomes MUCH more important than
substance...



J is supposed to be available in a freely redistributable form for
PCs, Macs, NeXT machines, MIPS, VAX, and a handful of others (e.g.
sun3 and sun4.. but that particular version is still vapor).

Check with the comp.lang.apl newsgroup for specifics of what versions
are available, and from where.  I know the pc and mac versions are
available for anonymous ftp from watserv1.waterloo.edu.

Documentation, at present, is pretty skimpy.  There is supposed to be
a book available, but I haven't received my copy yet.  The best I can
recomend is print out all the text files that come with the
distribution, and try the examples.  Documentation on APL, and past
issues of ACM's SIGAPL journal (Quote Quad -- look for anything
written by Ken Iverson.  I think volume 18, No. 1 is probably the best
mine of information) can give you some hints.

If there is enough interest, and if I can access the net, I'll post
more, later.



Oh yeah, by the way, if you use the 'read' function I defined towards
the begining of this post, and you want to read multiple lines, the
notation is:
   read 1 1 1
to read 3 lines.  You can make this more stylistic by defining a sort
of a bastardized adverb ('bastardized', because it is meant to return
a noun, not a verb) as follows:

   lines =. 1::(read 1)
x. $ 1

This allows you to say:
   read 3 lines
instead of (read 1 1 1)

-- 
I'm posting from raulmill@usc.edu, but this account is slated to be
disconnected within about a week.

news@usc.edu (09/21/90)

Shortly after I made the earlier posting <12061@chaph.usc.edu>, I
realized I had made several mistakes, including a couple program bugs.

First off, I should have said
   first =. {.
and
   rest  =. }.

as each of these functions take only one argument, and giving them two
arguments only confuses the matter.

Secondly, I should have explained my notation a little better.
Explanation follows (long)



Lines that were indented three spaces, such as

   o =. 0 0$''

were lines intended to be typed into the J command line interface.
Unindented lines which immediately followed were usually the function
results (except where I was using the 'read' function.. there they
indicated input to be read.  Also, I mixed in free text, but I hope
that was obvious).

Second, the J lexical analyzer would parse o =. 0 0$'' like this:
.-.--.---.-.--.
|o|=.|0 0|$|''|
'-'--'---'-'--'

Generally, anything followed by a . forms a two character token.  Non
alphabetics followed by a : also form two character tokens.  After
than, numeric lists (where each element begins with a digit, such as
2e or 4j) formed into tokens, as are ' delimited character strings,
and fairly typical alphanumeric symbols.

   =.       indicates local assignment

   $ y      gives the shape (dimensions) of y
 x $ y      returns a new array containing array cells from y,
            arranged with the dimensions given in x

   !:       is the 'system call' interface (and is syntactically a conjunction)

I forget whether I mentioned that adverbs only take their arguments
from their left, and conjunctions take an argument on both the left
and right side.  Also, because of priority, adverbs and conjunctions
can take either verbs or nouns as arguments, while verbs can only take
nouns as arguments.

  x }: y    returns x

   ::       is the generic definition conjunction

  x , y     catenates x and y to form a longer list

    &       is a conjunction that sticks two verbs together to form a
            single verb, or sticks a noun and a verb together to form
            a verb.  e.g.  (-&3) 4   would return 1

    {. y    returns the first array cell in y

    }. y    returns all array cels but the first in y

    y.      is the right argument passed to something defined by ::

    x.      is the left argument

    incidentally, in a definition like string1::string2, the string1
    definition is used when there is only one argument available, and
    the string2 definition is used where their are two nouns
    available.  (and a character matrix or a list of strings would
    work here just as well as a simple string).

    =:     is for global assignment.  I used this for 'set', because
           local assignment is trickier (you have to evaluate it in
           the right context), and the feature that I would have used
           to make this work is not implemented in version 2.

   x ; y   will 'box' y, if it is not already boxed, and it will box
           x, and then it catenates the boxed version of x onto the
           front of y.

           Although I didn't mention it, if you just want to box a
           single object, you can do it with (< y).  Boxing is roughly
           equivalent to C's & operator--you are effectively taking a
           pointer to the object.  Unboxing, which may be done with
           (> y) is roughly equivalent to C's * operator, except that
           if y is an array of boxed objects, the newly unboxed
           elements are padded to make them all the same size, and the
           result is a new array with extra dimensions on the end, to
           hold these new elements.

I could go on, but I ought to stop somewhere...