[comp.lang.apl] APL utilities for conversion to/from Iverson keywords

Pesch@cup.portal.com (Roland Henry Pesch) (04/16/89)

Here are some functions for translating APL characters to Iverson keywords
and back.  They are short enough that keying them in may not be too onerous;
alternately, your APL system may include or support or coexist with an editor
capable of turning the form shown here (using the keywords) into the 
corresponding characters.

The functions are written for compactness rather than efficiency.  Alternative
formulations avoiding things like massive outer products are likely to be
faster (how about it, Zeke?).

The first two versions should work in any APL; I originally wrote them
on my home Atari ST, using APL.68000, then moved them to SHARP APL at
work.

char2key translates APL characters to keywords:

       @@D char2key[@[] ]@@D 
[0]   z@<- char2key z;@[] io;c;m;i;a;p
[1]  @no  ASSUMES GLOBALS 'ALENGS', 'ACHARS', 'AKEYS' describe keyword
[2]  @no                   lengths,  targets,  text;
[3]  @no  ALSO THAT FIRST ELEMENT IS ERROR REPRESENTATION OF ESCAPE-- i.e.,
[4]  @no                         1,      '@ ',   '@ '.  Correct representation
[5]  @no  of escape should also be present, elsewhere in the globals.
[6]   @[] io@<- 0
[7]   @-> (0@e @r a@<- (c@<- z@e 1@Iv ACHARS)/z)@I^ 0
[8]   z@<- (1@@L c@x m@<- @@L /ALENGS)/z
[9]   z[i@<- ((1@@L c@x m)/c)/@i @r z]@<- ,AKEYS[p@<- 1+(1@Iv ACHARS)@i a;]
[10]  z@<- (~(@i @r z)@e (,ALENGS[p]@o .@<_ @i m)/i)/z

key2char is the inverse, translating keywords to APL characters:
      
      @@D key2char[@[] ]@@D 
[0]   z@<- key2char z;r;i;m;c;mm;@[] io;t
[1]  @no  ASSUMES GLOBALS 'ALENGS', 'ACHARS', 'AKEYS' describe keyword
[2]  @no                   lengths,  targets,  text;
[3]  @no  ALSO THAT FIRST ELEMENT IS ERROR REPRESENTATION OF ESCAPE-- i.e.,
[4]  @no                         1,      '@ ',   '@ '.  Correct representation
[5]  @no  of escape should also be present, elsewhere in the globals.
[6]  @no Note that, if this algorithm is to be a proper inverse to
[7]  @no that in "char2key" (notably wrt the escape character itself), it
[8]  @no is important that the "fill" used in the matrix AKEYS should differ
[9]  @no from blank; it is probably helpful to use an "unlikely" character,
[10] @no such as ctl-A or NUL.  (If blanks are used, the only known problem
[11] @no is that char2key translates '@ ' to '@  ', but key2char leaves '@  '
[12] @no untranslated).  Note that *one* blank is part of the keys for all
[13] @no except the error-representation first row, which is just @ , fill.
[14]  @[] io@<- 0
[15]  i@<- (z='@ ')/@i @r z
[16]  i@<- (~i@e i+1)/i
[17]  m@<- z[(@- 1+@r z)@L i@o .+c@<- @i @@L /ALENGS]
[18]  r@<- +/~((@r ACHARS)/mm@<- t[;@- 1+@r ACHARS])=t@<- @@L \+/^\0 2 1 2@O\ m@o .=AKEYS
[19]  z[i]@<- ACHARS[r@<- r@x ALENGS[r]@<_ ,mm]
[20]  z@<- (~(@i @r z)@e (,ALENGS[r]@o .>1@Iv c)/,i@o .+1@Iv c)/z

To make this all work, you'll need to define the supporting globals.
They are displayed below, though of course they are themselves keyword-ized.
      
      @no APL characters:  (here inevitably keywords; they should be
      @no the actual glyphs for execution, of course)
      @r @[] @<- ACHARS
@ @[-:] @@To @@DI @@D~ @['] @I^ @-> @Iv @<- @-I @@T @I- @@c @>_ @<_ @@L @=/ @=_ @- @<> @-: @[] @@D @no @o" @"O @OI @O- @O\ @O* @v~ @^~ @To @DI @\- @,- @/- @T @u @c @n @v @L @I @x @" @o @O @a @D @e @i @r @w @ 
56
      
      @no Keyword lengths (including blank):
      @r @[] @<- ALENGS
1 6 5 5 5 5 4 4 4 4 4 4 4 4 4 4 4 4 4 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3
       3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2
56
      
The display below doesn't show the ctl-A's used for fill (for clarity's
sake).  The word "fill" as used here means those elements of each row
that are not meant to be part of the keyword (i.e.  elements past the
corresponding length from ALENGS). 

      @no The keyword matrix itself
      @r AKEYS
56 6
      AKEYS
@      
@ [-:]
@ @ To  
@ @ DI  
@ @ D~  
@ [']  
@ I^   
@ ->   
@ Iv   
@ <-   
@ -I   
@ @ T   
@ I-   
@ @ c   
@ >_   
@ <_   
@ @ L   
@ =/   
@ =_   
@ -    
@ <>   
@ -:   
@ []   
@ @ D   
@ no   
@ o"   
@ "O   
@ OI   
@ O-   
@ O\   
@ O*   
@ v~   
@ ^~   
@ To   
@ DI   
@ \-   
@ ,-   
@ /-   
@ T    
@ u    
@ c    
@ n    
@ v    
@ L    
@ I    
@ x    
@ "    
@ o    
@ O    
@ a    
@ D    
@ e    
@ i    
@ r    
@ w    
@      
      
For your entertainment, the following equivalent definitions are in SAX,
an APL including many of the extensions in Iverson's Dictionary of APL. 
They use the same ACHARS but a vector of boxed (enclosed) keywords AKeys
instead of the matrix AKEYS and vector ALENGS.  With this
representation, the issue of "fill" does not arise.  Equivalent
formulations are sure to be straightforward in APL2 as well. 

      @r AKeys
56
      AKeys
@  @ [-:]  @ @ To  @ @ DI  @ @ D~  @ [']  @ I^  @ ->  @ Iv  @ <-  @ -I  @ @ T  @ I-  @ @ c  @ >_
       @ <_  @ @ L  @ =/  @ =_  @ -  @ <>  @ -:  @ []  @ @ D  @ no  @ o"  @ "O  @ OI  @ O-  @ O\
       @ O*  @ v~  @ ^~  @ To  @ DI  @ \-  @ ,-  @ /-  @ T  @ u  @ c  @ n  @ v  @ L  @ I  @ x
       @ "  @ o  @ O  @ a  @ D  @ e  @ i  @ r  @ w  @ 
      @r @" >AKeys
      @r @" >AKeys
1 6 5 5 5 5 4 4 4 4 4 4 4 4 4 4 4 4 4 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3
       3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2
      
      @@D c2k[@[] ]@@D 
[0]   z@<- c2k z;a;c
[1]  @no  SAX vn.  Assumes default @[] io (0).
[2]   @-> (0@e @r a@<- (c@<- z@e 1@Iv ACHARS)/z)@I^ 0
[3]   z@<- (1,c) @- 1@o" < (@- 1@I^ @[] av),z
[4]   z@<- >@Iv ,z,@,- (@r z)@I^ ( (1@Iv ACHARS)@i a ){1@Iv AKeys
      
      @@D k2c[@[] ]@@D 
[0]   z@<- k2c t;s;k;zl
[1]   s@<- @v @/- k@<- 0@,- (1@Iv AKeys)  @o" > <t @no  1@Iv  because 0{AKeys is not real keyword
[2]   s@<- s>0,@- 1@Iv s @no  overlap-removal heuristic: due to leading @ , trailing ' ',
[3]              @no  only possible overlaps are on leading @ @ 
[4]   k@<- s/+@/- ^@\- ~k @no  AKey index per match
[5]   z@<- s/@i @r t @no  hit indices in source
[6]   z@<- ,@o" 0 zl,@,- (z,@r t)-zl@<- 0,z+k{ALENGS
[7]   z@<- >@Iv , (@,- z 0@o" < t,' '),(1@I^ @r z)@I^ <@o" 0 k{ACHARS @no  <@o" 0 saves space (avoiding het)
[8]                                        @no  and avoids trailing blank if over@I^ 




                        /Roland Pesch
    pesch@pa.reuter.com      *or*        pesch@cup.portal.com