home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / j / jtxt.zip / EXTERNAL.TXT < prev    next >
Text File  |  1992-12-07  |  28KB  |  919 lines

  1.  
  2.  
  3.  
  4.  
  5.                 Using J with External Data:  two examples
  6.  
  7.                            Donald B. McIntyre
  8.                          Luachmhor, Church Road
  9.                         Kinfauns, Perth PH2  7LD
  10.                              Scotland - U.K.
  11.                          Telephone:  0738-86-726
  12.  
  13.     Introduction:
  14.  
  15.     J is a powerful dialect of APL created by Kenneth Iverson and
  16.     Roger Hui [1].   At the APL91 Conference at Stanford, California,
  17.     I gave an account of my experience with the language [2].   Some
  18.     of the difficulties I met when first trying to use J were due to
  19.     features that have been modified or dropped from the language;
  20.     for example, the manner in which one function inherited the rank
  21.     of another.   Although there was ample theoretical justification
  22.     for the original way rank was inherited (and I gave an example of
  23.     this in [2]), my experience helped to persuade the designers to
  24.     change the rules.   Because J is developing fast, it is essential
  25.     to specify the version used.   The files  Status.Doc and
  26.     Xenos.Doc, provided with the system, document changes from
  27.     earlier versions and should be examined closely.  The examples
  28.     given here were executed with Version 4.1x2
  29.  
  30.     The special issue of the IBM Systems Journal, commemorating 25
  31.     years of implemented APL, contains several examples of the same
  32.     function, or verb, written in conventional APL, Direct
  33.     Definition, and J [3].   These may be helpful to those already
  34.     familiar with APL.   In an earlier paper in Vector I have
  35.     provided an introduction to J with examples from elementary
  36.     arithmetic [4].   The standard references written by Iverson are,
  37.     of course, essential reading [5-9].   References to some of the
  38.     more technical papers will be found in reference [4].
  39.  
  40.     Dictionaries like The Oxford English Dictionary and Lewis and
  41.     Short's Latin Dictionary not only define words but include
  42.     phrases illustrating their use by standard authors.   It would be
  43.     impractical to attempt to learn a language from such sources
  44.     alone.   It is necessary to read literature written in the
  45.     language at an appropriate level, and preferably dealing with a
  46.     topic already understood by the reader.   This paper is intended
  47.     as a further contribution to the literature for beginning users
  48.     of J.
  49.  
  50.  
  51.  
  52.                                    -1-
  53.  
  54.  
  55.  
  56.  
  57.  
  58.     I always find that, like my students, I benefit most from
  59.     examples in a context to which I can relate.   In the context of
  60.     two practical examples, I give here examples of features of J,
  61.     including hooks and forks, rank, cut, raze, ravel items, format,
  62.     do (execute), copy (compress), box, open, under (dual), amend,
  63.     and the reading and writing of ASCII files.   I hope that others
  64.     will find these helpful as they learn J.
  65.  
  66.     In every definition only necessary parentheses are used.   It is
  67.     helpful to experiment by starting with fully parenthesised
  68.     expressions and gradually reducing the number of parentheses
  69.     included.   The successive definitions should be checked to see
  70.     whether they give the same result as before, and when they do not
  71.     they should be displayed in boxed and tree form to see how they
  72.     have been interpreted by the J system [4].
  73.  
  74.     The First Problem Stated:
  75.  
  76.     A friend, who was starting to investigate J, had monthly total
  77.     rainfall measurements for a period of eight years.   He had used
  78.     a word processor to put the values into an ASCII file and he
  79.     wondered how he could use J to compute various statistics.
  80.     Missing observations were indicated by a letter.   This is how
  81.     typical data appear in a file named data.in:
  82.  
  83.       3.02    0.88    6.69    1.78    3.48    3.37    3.81    1.57
  84.       4.33    1.59    2.72    1.74    0.86    0.65    X       0.87
  85.       0.22    2.77    2.66    2.08    1.65    2.48    X       3.41
  86.       1.74    5.33    2.44    1.89    2.91    1.93    0.48    3.72
  87.       0.25    0.09    2.33    1.67    1.40    1.54    2.37    4.18
  88.       2.28    2.23    0.77    4.01    1.48    2.88    1.47    0.13
  89.       0.94    X       2.72    5.11    X       2.46    1.54    0.56
  90.       2.03    0.99    3.27    2.35    3.29    3.55    0.98    0.78
  91.       1.26    2.07    4.02    1.09    1.84    0.37    2.30    1.32
  92.       3.82    2.06    2.33    7.00    3.10    0.66    4.28    2.14
  93.       3.08    1.54    0.88    2.60    4.20    2.52    3.82    1.22
  94.       2.28    4.09    1.19    0.76    2.39    4.94    2.23    3.06
  95.  
  96.  
  97.  
  98.  
  99.  
  100.  
  101.  
  102.  
  103.  
  104.  
  105.  
  106.                                    -2-
  107.  
  108.  
  109.  
  110.  
  111.     Input from ASCII to J:
  112.  
  113.     J has been criticised for having too few system functions, but
  114.     this is a misunderstanding.   APL's system functions are not
  115.     really part of the language;  in J they are implemented with the
  116.     "foreign" conjunction (!:).   As the name suggests, conjunctions
  117.     are dyadic;  they join together two arguments producing verbs
  118.     (functions) or adverbs (monadic operators).   Thus 1!:1 is file
  119.     read, and the argument of the resulting verb is the boxed
  120.     specification of the file.   Similarly 1!:2 is file write, a
  121.     dyadic verb, whose left argument is the character string to be
  122.     written, and right argument the boxed file specification.   It is
  123.     convenient to name these as follows:
  124.  
  125.        read=. 1!:1 @ <     NB.  x=. read 'input.fil'
  126.  
  127.        write=. [ 1!:2 <@]  NB.  'string' write 'output.fil'
  128.  
  129.     In my experience it is rather easy, even for a beginner, to think
  130.     in terms of a fork, and the verb write is defined here as a fork.
  131.     When I began to work with J I thought that both forks and hooks
  132.     were abstruse concepts unlikely to be useful to someone at my
  133.     level.   Very quickly, however, I found forks everywhere.   For a
  134.     long time I thought that hooks were much rarer.   The reason is
  135.     that every hook can be written as a fork, and it easier for the
  136.     novice to use the fork form;  as indeed I have done here.
  137.  
  138.     When a fork consists of the composition of a dyadic verb, a
  139.     monadic verb, and either a left ([) or a right (]) verb, then we
  140.     can use the hook form.   In the dyadic case (as in the verb
  141.     write):
  142.             x (g h) y   is the same as   x g (h y)
  143.  
  144.     which implies that g is dyadic and h is monadic.   Thus:
  145.  
  146.        write=. 1!:2 <        NB.  Write to a file.   Hook
  147.  
  148.     I shall draw attention to similar examples as they occur.
  149.  
  150.     Execution of the following sentence causes the data to be read as
  151.     a character string named y.
  152.  
  153.        y=. read 'data.in'
  154.  
  155.  
  156.  
  157.  
  158.  
  159.  
  160.                                    -3-
  161.  
  162.  
  163.  
  164.  
  165.     y is the name of a character string containing line-feed, new-
  166.     line, and end-of-file codes which are as follows (where a. is the
  167.     Atomic Vector, or list of the 256 ASCII codes, and { is the verb
  168.     from used by J instead of a[13] for indexing):
  169.  
  170.        nl=. 13 { a. [ lf=. 10 { a. [ eof=. 26 { a.
  171.  
  172.  
  173.     Replacement of the Character X to Characters _1:
  174.  
  175.     The indexes of the character X in the string are given by:
  176.        ]i=. u # i. # u=. y = 'X'
  177.     130 202 450 474
  178.  
  179.     Note that where # is preceded by i. it is the monadic tally;
  180.     where it is preceded by u it is the dyadic copy (equivalent to
  181.     compress or replicate in older APL).
  182.  
  183.     Because rainfall is never negative, we can replace the letter X
  184.     with the pair of characters _1 as a step in converting the
  185.     character string into numbers amenable to arithmetic.   The
  186.     indexes of all positions to be changed are found by using the
  187.     table adverb (/) to produce the outer product.
  188.        ,i +/0 1
  189.     130 131 202 203 450 451 474 475
  190.  
  191.     The information to be entered at these positions is:
  192.        (+:#i)$'_1'
  193.     _1_1_1_1
  194.     Substitution is then made by amend.  For further examples see [2,
  195.     p.270], but note that amend was changed in Version 4 [10].
  196.        z=. ((+:#i)$'_1') (,i +/0 1)}y
  197.  
  198.     Defining verbs to accomplish this, we can proceed as follows:
  199.        h=. 'X'&=@] # i.@#     NB.  Fork
  200.        h y
  201.     130 202 450 474
  202.  
  203.        g=. ,@(+/&0 1)@h
  204.        g y
  205.     130 131 202 203 450 451 474 475
  206.  
  207.        f=. $&'_1' @ (+:@#@h)
  208.  
  209.  
  210.  
  211.  
  212.  
  213.  
  214.                                    -4-
  215.  
  216.  
  217.  
  218.  
  219.        f y
  220.     _1_1_1_1
  221.  
  222.     Then:
  223.        z=. (f y) (g y)} y
  224.  
  225.     The explicit form is straightforward:
  226.        amend=. '(f y.) (g y.)} y.' : ''
  227.        z-: amend y
  228.     1
  229.  
  230.     It was simple to amend a matrix with earlier versions of J using
  231.     desk calculator mode [2, p.270].   The syntax was x i} m, where i
  232.     gave boxed indexes.   But a definition in tacit form cannot be
  233.     written easily.   Four hours after discussing this case with Ken
  234.     Iverson and Roger Hui, they telephoned back to say that they had
  235.     extended J (Version 4) to permit definition of the following
  236.     fork:
  237.       amend=. f g@]} ]
  238.        z-: amend y
  239.     1
  240.  
  241.     This is dramatic testimony to the superior design of the
  242.     language, the flexibility of the implementation, and the response
  243.     and skill of both designer and implementer!
  244.  
  245.  
  246.     Conversion from Character String to Numeric Table:
  247.  
  248.     z is a string of numbers, represented in character form and
  249.     containing printer-control characters.   Reshape it into a 12 by
  250.     8 table after converting from character representation to
  251.     numeric, and after printer-control characters have been removed:
  252.        d=. 12 8 $ ". z #~ -. z e. lf,nl,eof
  253.  
  254.     We can, however, make this table without explicitly specifying
  255.     its shape.   Take a simple example to illustrate the procedure:
  256.        s=. '1 2 3',lf,'4 5 6',lf,'7 8 9',lf
  257.  
  258.        cut=. <;._2
  259.     The conjunction cut will box items delimited by the last item (2)
  260.     -- in this case lf -- and exclude (_2) the delimiters from the
  261.     intervals:
  262.  
  263.  
  264.  
  265.  
  266.  
  267.  
  268.                                    -5-
  269.  
  270.  
  271.  
  272.  
  273.        cut s
  274.     ┌─────┬─────┬─────┐
  275.     │1 2 3│4 5 6│7 8 9│
  276.     └─────┴─────┴─────┘
  277.  
  278.     Raze the result:
  279.        ; cut s
  280.     1 2 34 5 67 8 9
  281.  
  282.     Ravel Items:
  283.        ,. cut s
  284.     ┌─────┐
  285.     │1 2 3│
  286.     ├─────┤
  287.     │4 5 6│
  288.     ├─────┤
  289.     │7 8 9│
  290.     └─────┘
  291.  
  292.     Open:
  293.        > cut s
  294.     1 2 3
  295.     4 5 6
  296.     7 8 9
  297.  
  298.     Do, or execute (".)  under (&.) open (>) ;  i.e., open each box,
  299.     convert to numeric, and then close each box again:
  300.        $ ".&.> cut s
  301.     3
  302.     Open the result of this operation and show that we have produced
  303.     the required numeric table:
  304.        execute=. > @ (".&.> @ <;._2)
  305.        1 + execute s
  306.     2 3  4
  307.     5 6  7
  308.     8 9 10
  309.  
  310.     To apply execute to our data, begin by eliminating the new-line
  311.     and end-of-file characters while leaving the line-feeds as
  312.     delimiters:
  313.  
  314.        d -: data=. execute z#~ -. z e. nl,eof
  315.     1
  316.  
  317.  
  318.  
  319.  
  320.  
  321.  
  322.                                    -6-
  323.  
  324.  
  325.  
  326.  
  327.        data
  328.     3.02 0.88 6.69 1.78 3.48 3.37 3.81 1.57
  329.     4.33 1.59 2.72 1.74 0.86 0.65   _1 0.87
  330.     0.22 2.77 2.66 2.08 1.65 2.48   _1 3.41
  331.     1.74 5.33 2.44 1.89 2.91 1.93 0.48 3.72
  332.     0.25 0.09 2.33 1.67  1.4 1.54 2.37 4.18
  333.     2.28 2.23 0.77 4.01 1.48 2.88 1.47 0.13
  334.     0.94   _1 2.72 5.11   _1 2.46 1.54 0.56
  335.     2.03 0.99 3.27 2.35 3.29 3.55 0.98 0.78
  336.     1.26 2.07 4.02 1.09 1.84 0.37  2.3 1.32
  337.     3.82 2.06 2.33    7  3.1 0.66 4.28 2.14
  338.     3.08 1.54 0.88  2.6  4.2 2.52 3.82 1.22
  339.     2.28 4.09 1.19 0.76 2.39 4.94 2.23 3.06
  340.  
  341.  
  342.     Replace Negative Values by Row Means:
  343.  
  344.     Substituting the most reasonable values for missing data is a
  345.     matter that requires knowledge of the subject matter.   In this
  346.     case the columns are years (8) and the rows, or items, are months
  347.     (12).   We can replace missing values by the means for the row
  348.     (month) over all years for which we have data.
  349.  
  350.     We need the indexes of missing values (represented by _1).  First
  351.     write a directly executable expression and then define a verb to
  352.     give the same result:
  353.        (,u)#i.#,u=. 0>data
  354.     14 22 49 52
  355.  
  356.        h=. 0&>@,
  357.        g=. (] # i.@#)@h    NB.  A fork that can be written as a hook
  358.  
  359.     Because g consists of a dyadic verb (#), a monadic verb (i.), and
  360.     the verb right (]), it can be written as a hook.
  361.        g=. (# i.@#)@ h     NB.  Hook
  362.     Fix g as ir (Indexes in Ravel) so that the names g and h can be
  363.     reused.
  364.        ir=. g f.
  365.        ir data    NB.  Index in Ravel of matrix
  366.     14 22 49 52
  367.  
  368.     The row indexes are:
  369.        <.8%~ir data
  370.     1 2 6 6
  371.  
  372.  
  373.  
  374.  
  375.  
  376.                                    -7-
  377.  
  378.  
  379.  
  380.  
  381.        (<.@(%&8)) ir data
  382.     1 2 6 6
  383.  
  384.     The column indexes are:
  385.        8|ir data
  386.     6 6 1 4
  387.  
  388.     To find the indexes we made explicit use of the number of columns
  389.     (8), but this number is given by:
  390.        {:$ data
  391.     8
  392.  
  393.     Define verbs row and column depending solely on the data:
  394.        row=. <. @ (ir % {:@$)      NB.  Fork
  395.        row data
  396.     1 2 6 6
  397.  
  398.        column=. {:@$ | ir          NB.  Fork
  399.        column data
  400.     6 6 1 4
  401.  
  402.        f=. row ,. column           NB.  Fork
  403.        f data
  404.     1 6
  405.     2 6
  406.     6 1
  407.     6 4
  408.  
  409.     Note that row, column, and f are forks.   Now box the items
  410.     (rows):
  411.        ix=. <"1 @(row ,. column)
  412.        ]i=. ix data
  413.     ┌───┬───┬───┬───┐
  414.     │1 6│2 6│6 1│6 4│
  415.     └───┴───┴───┴───┘
  416.        ]z=. i{data
  417.     _1 _1 _1 _1
  418.        z-: ({~ ix) data     NB.  Hook
  419.     1
  420.        z-: (ir data){,data
  421.     1
  422.        z-: (ir { ,) data    NB.  Fork
  423.     1
  424.  
  425.  
  426.  
  427.  
  428.  
  429.  
  430.                                    -8-
  431.  
  432.  
  433.  
  434.  
  435.     Compute the means of the rows with negative values.
  436.        mean=. +/%#                            NB.   Fork
  437.        ]m=. mean"1 (row data){data
  438.     1.47 1.78375 1.41625 1.41625
  439.  
  440.     Note that (row data){ data is a candidate for a monadic hook:
  441.        m-: mean"1 ({~ row) data
  442.     1
  443.  
  444.     But these means were computed over the eight values in the rows,
  445.     and these include the _1, which is only a flag indicating a
  446.     missing observation.
  447.  
  448.     We need a special mean that will be based only on positive or
  449.     zero values:
  450.  
  451.        mean n=. 1 _9 2 3 _1 4 0 5
  452.     0.625
  453.        (>:&0 # ]) n           NB.  Fork
  454.     1 2 3 4 0 5
  455.  
  456.     Every hook can be written as a fork, and the fork is often easier
  457.     to grasp than the hook that could replace it.   Remember that in
  458.     the hook (g h), h is always monadic and g is dyadic [4].
  459.     Arrange the two verbs in the order, from left to right, Dyadic,
  460.     Monadic.   If the dyadic function is not commutative, it may be
  461.     necessary, as in this case, to use the cross adverb (~).
  462.  
  463.        h=. >:&0               NB.  Monadic
  464.        h n
  465.     1 0 1 1 0 1 1 1
  466.        g=. #~                 NB.  Dyadic
  467.        n g (h n)
  468.     1 2 3 4 0 5
  469.        (g h) n                NB.  Hook
  470.     1 2 3 4 0 5
  471.  
  472.        (#~ >:&0) n            NB.  Hook
  473.     1 2 3 4 0 5
  474.  
  475.     Mean over positive and zero values:
  476.        pzmean=. mean @ (#~ >:&0)      NB.  Hook
  477.        pzmean n
  478.     2.5
  479.  
  480.  
  481.  
  482.  
  483.  
  484.                                    -9-
  485.  
  486.  
  487.  
  488.  
  489.  
  490.        ]m=. pzmean"1 ({~ row) data
  491.     1.82286 2.18143 2.22167 2.22167
  492.  
  493.     Amend the data by inserting these values.   Note that the indexes
  494.     (i) are with respect to the ravel of the matrix (data).
  495.        ]x=. m i}data
  496.     3.02    0.88 6.69 1.78    3.48 3.37    3.81 1.57
  497.     4.33    1.59 2.72 1.74    0.86 0.65 1.82286 0.87
  498.     0.22    2.77 2.66 2.08    1.65 2.48 2.18143 3.41
  499.     1.74    5.33 2.44 1.89    2.91 1.93    0.48 3.72
  500.     0.25    0.09 2.33 1.67     1.4 1.54    2.37 4.18
  501.     2.28    2.23 0.77 4.01    1.48 2.88    1.47 0.13
  502.     0.94 2.22167 2.72 5.11 2.22167 2.46    1.54 0.56
  503.     2.03    0.99 3.27 2.35    3.29 3.55    0.98 0.78
  504.     1.26    2.07 4.02 1.09    1.84 0.37     2.3 1.32
  505.     3.82    2.06 2.33    7     3.1 0.66    4.28 2.14
  506.     3.08    1.54 0.88  2.6     4.2 2.52    3.82 1.22
  507.     2.28    4.09 1.19 0.76    2.39 4.94    2.23 3.06
  508.  
  509.        amend=. ir@]}
  510.        x-: m amend data
  511.     1
  512.  
  513.  
  514.     Catenate Month and Year Means:
  515.  
  516.     The verb ymean is a hook that catenates yearly means to the foot
  517.     of the columns:
  518.        ymean=. ,"2 1 mean
  519.        ymean x
  520.  
  521.     Catenate the means of rows (months), the means of columns
  522.     (years), and the grand mean (at bottom right corner):
  523.  
  524.  
  525.  
  526.  
  527.  
  528.  
  529.  
  530.  
  531.  
  532.  
  533.  
  534.  
  535.  
  536.  
  537.  
  538.                                   -10-
  539.  
  540.  
  541.  
  542.  
  543.        ]s=. 6.2":((,"2 1 mean) x),"1 0 (mean"1 x),mean ,x
  544.       3.02  0.88  6.69  1.78  3.48  3.37  3.81  1.57  3.07
  545.       4.33  1.59  2.72  1.74  0.86  0.65  1.82  0.87  1.82
  546.       0.22  2.77  2.66  2.08  1.65  2.48  2.18  3.41  2.18
  547.       1.74  5.33  2.44  1.89  2.91  1.93  0.48  3.72  2.55
  548.       0.25  0.09  2.33  1.67  1.40  1.54  2.37  4.18  1.73
  549.       2.28  2.23  0.77  4.01  1.48  2.88  1.47  0.13  1.91
  550.       0.94  2.22  2.72  5.11  2.22  2.46  1.54  0.56  2.22
  551.       2.03  0.99  3.27  2.35  3.29  3.55  0.98  0.78  2.15
  552.       1.26  2.07  4.02  1.09  1.84  0.37  2.30  1.32  1.78
  553.       3.82  2.06  2.33  7.00  3.10  0.66  4.28  2.14  3.17
  554.       3.08  1.54  0.88  2.60  4.20  2.52  3.82  1.22  2.48
  555.       2.28  4.09  1.19  0.76  2.39  4.94  2.23  3.06  2.62
  556.       2.10  2.16  2.67  2.67  2.40  2.28  2.27  1.91  2.31
  557.  
  558.     This illustrates the verb format (":), the conjunction rank (")
  559.     applied to catenation (,), and the hook (,"2 1 mean)
  560.  
  561.     We now have a character array.   Catenate to it the new-line and
  562.     line-feed codes, and ravel to produce an ASCII string that can be
  563.     sent to DOS:
  564.        (,s,"1 nl,lf) write 'data.out'
  565.  
  566.     The file Data.Out is the required ASCII file.
  567.  
  568.  
  569.     Using Box (<) for further Formatting:
  570.  
  571.        f=. <@(6.2&":)
  572.        g=. f&:(,:@ mean"1) ,: f@ mean @ ,     NB.   Fork
  573.        h=. f , f@ mean                        NB.   Fork
  574.        table =. h ,"0 1 g                     NB.   Fork
  575.  
  576.  
  577.  
  578.  
  579.  
  580.  
  581.  
  582.  
  583.  
  584.  
  585.  
  586.  
  587.  
  588.  
  589.  
  590.  
  591.  
  592.                                   -11-
  593.  
  594.  
  595.  
  596.  
  597.        ]t=. table x
  598.     ┌────────────────────────────────────────────────┬──────┐
  599.     │  3.02  0.88  6.69  1.78  3.48  3.37  3.81  1.57│  3.07│
  600.     │  4.33  1.59  2.72  1.74  0.86  0.65  1.82  0.87│  1.82│
  601.     │  0.22  2.77  2.66  2.08  1.65  2.48  2.18  3.41│  2.18│
  602.     │  1.74  5.33  2.44  1.89  2.91  1.93  0.48  3.72│  2.55│
  603.     │  0.25  0.09  2.33  1.67  1.40  1.54  2.37  4.18│  1.73│
  604.     │  2.28  2.23  0.77  4.01  1.48  2.88  1.47  0.13│  1.91│
  605.     │  0.94  2.22  2.72  5.11  2.22  2.46  1.54  0.56│  2.22│
  606.     │  2.03  0.99  3.27  2.35  3.29  3.55  0.98  0.78│  2.15│
  607.     │  1.26  2.07  4.02  1.09  1.84  0.37  2.30  1.32│  1.78│
  608.     │  3.82  2.06  2.33  7.00  3.10  0.66  4.28  2.14│  3.17│
  609.     │  3.08  1.54  0.88  2.60  4.20  2.52  3.82  1.22│  2.48│
  610.     │  2.28  4.09  1.19  0.76  2.39  4.94  2.23  3.06│  2.62│
  611.     ├────────────────────────────────────────────────┼──────┤
  612.     │  2.10  2.16  2.67  2.67  2.40  2.28  2.27  1.91│  2.31│
  613.     └────────────────────────────────────────────────┴──────┘
  614.  
  615.     t is a table with 2 rows and 2 columns:
  616.        $t
  617.     2 2
  618.  
  619.  
  620.     The Second Problem Stated:
  621.  
  622.     Early versions of J were supplied with tutorial files that could
  623.     be displayed while in J.   In Version 4 of the Dictionary the
  624.     tutorials are provided in an appendix [5].   In the files of one
  625.     preliminary version each new-line code stood alone instead of
  626.     being followed by a line-feed.   Consequently, when these files
  627.     were read lines of text were superposed.   If the last line was
  628.     the longest in the file, then that line was the only one
  629.     displayed.
  630.  
  631.     To create such a file for yourself, first use your word processor
  632.     prepare a text file (let us call it junk) with half a dozen short
  633.     lines without wordwrap;  i.e. press the Enter key at the end of
  634.     each line.   Next use a hex-editor, such as provided by PCTOOLS
  635.     or NORTON, to see the sequence 0D 0A marking new-line and line-
  636.     feed commands.   Now change all occurrences of 0A to 20 in order
  637.     to replace line-feeds by blanks.   The problem then is how to use
  638.     J to reverse the process by inserting a line-feed after every
  639.     occurrence of new-line.   Try reading this file from J by
  640.           ]x=. read 'junk'
  641.  
  642.  
  643.  
  644.  
  645.  
  646.                                   -12-
  647.  
  648.  
  649.  
  650.  
  651.  
  652.     Observe that each line is overlaid on the previous lines.   Count
  653.     the number of new-lines and line-feeds, verifying that the line-
  654.     feeds have been eliminated:
  655.           +/ x =/ 13 10 {a.
  656.  
  657.     The verb h cuts the string using the new-line codes as
  658.     terminating delimiters.   We can compose it from 3 verbs as a
  659.     fork;  a monadic verb, a dyadic verb, and the verb right (]).
  660.     Or we can compose it from 2 verbs as a hook.
  661.           h=. =&nl <;.2 ]       NB.  Fork
  662.           h=. <;.2~ =&nl        NB.  Hook
  663.  
  664.     As in all hooks, the right-hand verb is monadic and the left-hand
  665.     verb is dyadic.   A hook combines one noun with the result of a
  666.     verb that has been applied to a noun, either the same noun as the
  667.     first (in the monadic case) or a different one (in the dyadic
  668.     case).   Use a hook whenever this situation occurs.
  669.  
  670.     The boolean string produced by equals (=) points to the positions
  671.     of new-line codes.   This is the left argument for cut (< ;. 2).
  672.     The 2 indicates that the delimiters mark the ends of the
  673.     intervals and are to be included in the result [5, p.10-11].
  674.           each=. &.>
  675.           g=. ,&lf each
  676.           edit=. ; @ (g @ h)
  677.           input=. edit @ read
  678.  
  679.     The definition should be fixed so that input will not be changed
  680.     if the names g and h are reused.
  681.           input=. input f.
  682.  
  683.     The adverb each opens the boxes produced by h, applies the verb
  684.     (which is here catenate lf to the tail), and then closes the
  685.     boxes again.   After reading the file, input edits it by putting
  686.     in the required line-feed codes.  The file can now be displayed
  687.     without superposed lines:
  688.           ]x=. input 'junk'
  689.  
  690.     To create a new file with the corrections:
  691.           x 1!:2 <'junk.out'
  692.  
  693.     The character string x is written to the new file (which must be
  694.     designated by a boxed string).   This file can now be read
  695.     correctly (remember that our read verb boxes the name before
  696.     using it):
  697.  
  698.  
  699.  
  700.                                   -13-
  701.  
  702.  
  703.  
  704.  
  705.           read 'junk.out'
  706.  
  707.     Leave J and use your hex-editor to see that line-feeds (0A) have
  708.     been inserted between the new-line (0D) and space (20) codes.
  709.  
  710.     We have modified a single file, but I had several files to edit.
  711.     Let infiles and outfiles be the lists of boxed names of files for
  712.     input and output:
  713.  
  714.        infiles=. 'tut10.in';'tut11.in';'tut12.in';'tut13.in'
  715.        outfiles=. 'tut10.out';'tut11.out';'tut12.out';'tut13.out'
  716.  
  717.     With the power of J we can create all the new files in one step.
  718.     Switching arguments to avoid parentheses, my first successful
  719.     solution was this:
  720.  
  721.        output=. >@[ 1!:2 ]           NB.  Fork
  722.        outfiles output~"0 input each infiles
  723.  
  724.     The logic is as follows.  The file names are already boxed.   Use
  725.     each to apply input (edit after read) and give the boxed strings
  726.     ready for the output files.  Let the boxed names of the output
  727.     files be the right argument, and let the left argument be the
  728.     boxed strings that are to go into these files.   Then the rank
  729.     conjunction ("0) can make output handle each file in turn.  The
  730.     syntax would be like this:
  731.  
  732.     For one file:
  733.                 'string'  1!:2  (boxed file name)
  734.  
  735.     Note the asymmetry:  the right argument must be boxed, but the
  736.     left argument must not be boxed.
  737.  
  738.     For several files one might try:
  739.            (boxed edited strings) 1!:2"0 (boxed output file names)
  740.  
  741.     The rank conjunction takes 1 box on the left along with one box
  742.     on the right.   However after the box on the left has been taken
  743.     it must be opened before output begins.   If we open the left
  744.     argument too soon then we defeat the purpose of the rank
  745.     conjunction!   Consequently open (>) must be part of output.
  746.     The other part is, of course,  1!:2
  747.  
  748.     A fork is then obvious:  open the left argument and don't open
  749.     the right argument of 1!:2
  750.  
  751.  
  752.  
  753.  
  754.                                   -14-
  755.  
  756.  
  757.  
  758.  
  759.  
  760.            output=. >@[ 1!:2 ]           NB.  Fork
  761.  
  762.     Because this fork (like many others I have written!) consists of
  763.     a monadic verb (open), a dyadic verb (1!:2), and the verb right,
  764.     it can be recast as a hook.   Because there are two distinct
  765.     arguments, the hook is dyadic:
  766.  
  767.            x (g h) y     is the same as     x g (h y)
  768.  
  769.     h is the monadic function, therefore we must switch arguments;
  770.     it is the boxed string that is to be opened -- not the boxed file
  771.     name.   The right argument must be the result produced by input
  772.     each infiles -- which is boxed;  the rank conjunction sees to it
  773.     that only one box is taken at a time, and the phrase denoted (h
  774.     y) opens that box.   Along with the rank conjunction, this
  775.     provides the right argument for (1!:2), and the left argument is
  776.     a single boxed file-name.
  777.  
  778.     In using the hook (instead of the fork) we have no choice about
  779.     which argument is to be on the left and which on the right.
  780.     Because this conflicts with the positions of the arguments
  781.     required for (1!:2), we must cross them (~).   The result is
  782.     therefore:
  783.  
  784.        (boxed output file names) (g~ h) (boxed edited strings)
  785.  
  786.     That is, we need the following hook:
  787.  
  788.         output=. 1!:2~ >               NB.  Hook
  789.         outfiles output"0 input each infiles
  790.  
  791.     After this line is executed, all files named in outfiles can be
  792.     read correctly.
  793.  
  794.  
  795.     Acknowledgements:
  796.  
  797.     Kenneth Iverson and Roger Hui (Iverson Software Inc.) created the
  798.     system a small facet of which I have described here.   They have
  799.     given unfailing assistance, coaching me by long-distance
  800.     telephone and patiently answering my more naive questions.  In
  801.     response to my reported experience, in a few cases they modified
  802.     the language.   They are, of course, in no way responsible for
  803.  
  804.  
  805.  
  806.  
  807.  
  808.                                   -15-
  809.  
  810.  
  811.  
  812.  
  813.     infelicities in my use and exposition of their language.   I
  814.     claim only that the expressions given here work in the current
  815.     version of the system (J4.1x2, 13 Jan 1992).
  816.  
  817.     By asking for a solution to the first problem, Dr. Richard
  818.     Fulford directed me into the realm of external communication.
  819.     Graham Woyka and Anthony Camacho were always encouraging when the
  820.     going was rough.
  821.  
  822.  
  823.     References
  824.  
  825.  
  826.         [1]    J is available from Iverson Software Inc., 33 Major
  827.               Street, Toronto, Ontario, Canada M5S  2K9.   Phone
  828.               (416) 925-6096; Fax (416) 488-7559.
  829.  
  830.         [2]    Donald B. McIntyre, Mastering J, APL91 Conference
  831.               Proceedings, Stanford, California, August 1991.   APL
  832.               Quote Quad Vol. 21 Number 4 (August 1991), p.264-273.
  833.  
  834.         [3]    Donald B. McIntyre, Language as an Intellectual Tool:
  835.               From hieroglyphics to APL, IBM Systems Journal, Vol.
  836.               30, Number 4 (1991) p.554-581.
  837.  
  838.         [4]    Donald B. McIntyre, Hooks and Forks and the Teaching of
  839.               Elementary Arithmetic, Vector, Vol. 8 Number 3 (January
  840.               1992) 101-123.
  841.  
  842.         [5]    Kenneth E. Iverson, The ISI Dictionary of J, Version 4
  843.               with Tutorials, Iverson Software Inc., Toronto (1991)
  844.               29pp.
  845.  
  846.         [6]    Kenneth E. Iverson, Programming in J, Iverson Software
  847.               Inc., Toronto (1991) 72pp.
  848.  
  849.         [7]    Kenneth E. Iverson, Tangible Math, Iverson Software
  850.               Inc., Toronto (1991) 33pp.
  851.  
  852.         [8]    Kenneth E. Iverson, Arithmetic, Iverson Software Inc.,
  853.               Toronto (1991) 119pp.
  854.  
  855.         [9]    Kenneth E. Iverson, An Introduction to J, Iverson
  856.               Software Inc., Toronto (1992) 46pp.
  857.  
  858.  
  859.  
  860.  
  861.  
  862.                                   -16-
  863.  
  864.  
  865.  
  866.  
  867.  
  868.         [10]    Donald B. McIntyre, Using J's Boxed Arrays, Vector,
  869.               Vol. 9 (1992) In Press.
  870.  
  871.  
  872.  
  873.  
  874.  
  875.  
  876.  
  877.  
  878.  
  879.  
  880.  
  881.  
  882.  
  883.  
  884.  
  885.  
  886.  
  887.  
  888.  
  889.  
  890.  
  891.  
  892.  
  893.  
  894.  
  895.  
  896.  
  897.  
  898.  
  899.  
  900.  
  901.  
  902.  
  903.  
  904.  
  905.  
  906.  
  907.  
  908.  
  909.  
  910.  
  911.  
  912.  
  913.  
  914.  
  915.  
  916.                                   -17-
  917.  
  918.  
  919.