Primitives to Mnemonics
Upgraded for J6 and Support for idioms improved
Support for displaying idioms etc. in unicode.
New users of J might find the number of primitives a little overwhelming given how cryptic they may be. J provides an excellent tool to explain a primitive. Simply put the cursor on the primitive and press Ctrl-F1 to go directly to the primitive definition in the dictionary.
This script provides a way for users to convert a statement to one with primitives replaced with mnemonic equivalents. Many times seeing the mnemonic equivalents of the primitives is enough to remind one as to what the primitives do.
This tool accepts a statement and returns the statement with primitives replaced with their mnemonic equivalents. It attempts to give the monadic or dyadic mnemonic as appropriate for the use of the primitive in the statement.
Once the mnemonics script is loaded, run the script by entering in the ijx window. For example:
mn '+/&.>(i.2 3);i.5' Plus Insert Under Open ( Integers 2 3 ) Link Integers 5
The statement is displayed with the primitives replaced with mnemonic names.
This result is executable as the mnemonics for the primitives are defined in the ~+"z"+~ locale.
Plus Insert Under Open ( Integers 2 3 ) Link Integers 5 +-----+--+ |3 5 7|10| +-----+--+
Options for left argument of mn - one to three numbers:
- First number
- 1 - Assume tacit expressions are monadic (default).
- 2 - Assume tacit expressions are dyadic.
- Second number
- 0 - Replace named tokens and constants with dummies and execute the statement in dummy mode (default).
- 1 - Only replace defined primitives and execute the statement fully.
- 2 - Just convert primitives found in symbols to ambivalent names and return that result.
- Third number
- 0 - Do not expand idioms (default).
- 1 - Expand idioms.
There are two other ways to convert primitives. Entering ~+"mn ''"+~ opens a form for easy entry of primitive expressions. This gives
Controls on the form change the defaults for the left argument of mn.
The third way is to select a line or part of a line in an ijs or ijx window and press F4. The result is displayed in the ijx window.
The mnemonics for primitives are defined in the script ~+'~system\packages\misc\primitiv.ijs'+~ which is included in the J install.
Notice the ~+"idioms"+~ option. There is support for idioms like ~+"&.>"+~ means "Each". But the J supplied "primitiv.ijs" has none defined. You may add idioms to the primitives definitions yourself. Simply add a noun "IDIOMS" to the script with the desired idioms. See the sample script "primitiv.ijs" below. Assuming that you have added some idioms, pressing F4 on the same expression gives something like
+/&.>(i.2 3);i.5 Sum Each ( Integers 2 3 ) Link Integers 5
In the example primitiv.ijs which can be downloaded below. It will convert an expression like "+/" to the mnemonic "Sum".
The mnemonics defined at this time are not comprehensive. They are only for testing.
There has been much discussion lately about displaying J expressions using special symbols similar to the way APL looks. This script has been extended to replace the mnemonics with unicode strings you can assign. Those scripts are available below. This documentation will be improved for this; however, just making them available for discussion.
Download mn script: File:Mncode.ijs
Optional primitiv.ijs with sample idioms: File:Primitiv.ijs
If you put the primitiv.ijs in the same folder that mncode.ijs is placed it will be automatically loaded instead of loading the J supplied script.
Download mn unicode script: File:Mncodeu.ijs
primitiv.ijs script with unicode: File:Primitivu.ijs
Rename the primitivu.ijs to primitiv.ijs after you download it.
These unicode scripts will replace the scripts non-unicode versions as soon as I can figure out how to do it.
How this is done
Primitives are converted to mnemonics by replacing the primitives with temporary names which execute the same as the primitive but also report if they are used monadically or dyadically.
Using the shorter statement
mn '++/1j2 3j4' Conjugate Plus Insert 1j2 3j4
Convert the statement into tokens.
;:'++/1j2 3j4' +-+-+-+-------+ |+|+|/|1j2 3j4| +-+-+-+-------+
Replace the primitives with the mnemonic names. All the possible names are included.
+---------------------+---------------------+--------------------+-------+ |+----+---------+----+|+----+---------+----+|+-----+------+-----+|1j2 3j4| ||Plus|Conjugate|Plus|||Plus|Conjugate|Plus|||Table|Insert|Table|| | |+----+---------+----+|+----+---------+----+|+-----+------+-----+| | +---------------------+---------------------+--------------------+-------+
Build a test statement by replacing each item shown above with a test name.
The statement for the first ~+"+"+~ is
Plus_0 =: 3 : 0 :.(3 : 0) 0 replace__mnlocale < 'Conjugate' if. runtest__mnlocale do. Plus ^: _1 y. else. ] y. end. : 0 replace__mnlocale < 'Plus' if. runtest__mnlocale do. x. Plus &. _1 y. else. x. ] y. end. ) 0 replace__mnlocale < 'Conjugate' if. runtest__mnlocale do. Plus y. else. ] y. end. : 0 replace__mnlocale < 'Plus' if. runtest__mnlocale do. x. Plus y. else. x. ] y. end. )
The name of the verb is the primitive's ambivalent name followed by an underscore and the index of the primitive in the tokenized list for uniqueness. It has definitions for both the verb and its obverse. Both the verb and its obverse have a monadic and a dyadic part, each part reports how it is used and then runs the original verb or a dummy verb.
The generated test statement is ~+"Plus_0 Plus_1 Table_2 _1 2,.3 4"+~
In this case dummy data is used and the verb ] is used instead of the mnemonic for the primitive. It usually doesn't matter what the verb is and ] will work with almost any data.
Run this statement.
The temporary names select the appropriate mnemonic as each one executes resulting in
+---------+------+-------+---------+ |Conjugate|Plus |Insert |1j2 3j4 | +---------+------+-------+---------+
After restoring tokens not converted it is easy to build the returned result.
Want your own mnemonics?
Rather than building a script from scratch, you might want to copy "primitiv.ijs" and only change the mnemonic names you want different. Then change the file name that "mncode.ijs" loads to build the translation tables. The file name it loads is near the bottom of "mncode.ijs".
While you're at it, you can add some idioms for the fun of it.
The format for both is ~+"monadname=:dyadname=:ambivalentname=:<primitive or idiom>"+~
If less than three names are given then they are expanded to three. More than three names are kept but ignored for now. They may be used for special handling.
Basic Information on Internals
This defines two names in the "z" locale - "mn" and "mnlocale". It uses three locales:
- mnemonics - main work area
- mncode - the code, separated from the work area for possible extentions later
- mntemp - where test statements are executed to avoid any name conflicts
Idioms are handled by a simple search for the idiom patterns then replacing them with the idiom name. Idioms can be ambiguous if all parentheses are not inserted. This is done using "paren" in "trace.ijs". The added parentheses are removed before displaying the result.
You may notice that the "replace idioms" control is disabled if you run this under J5. This is because trace.ijs is new to j6 and not available in j5. It is also disabled if no idioms are defined.
The verb "paren" does not put in all the parentheses that are possible. For instance, ~+paren '+/&.>'+~ returns ~+((+ /) &. >)+~ instead of ~+((+ /) (&. >))+~. To avoid this problem the first parenthesis of each idiom is dropped.
Where to next?
Maybe better mnemonics. Those in primitiv.ijs were not intended for this use but they work pretty well.
Several idioms already in the ~+"z"+~ locale could be added. Like ~+"each=:&.>"+~. You simply need to put them in your own primitives file.
Maybe mnemonics in languages other than English.
There is a check box for special processing which is not supported yet. This is intended to allow the addition of special processing for specific primitives. This could handle primitives like "@." to handle gerunds possibly by forcing the execution of all items in the gerund.
Should scripts be processed? First it needs to handle copulas. Right now everything before a copula gives an erroneous warning message. As for coupulas, one needs to know the part of speech the copula assigns to the name before anything before the copula can be converted.
Why did I pick F-4 for converting primitives? I don't have that key defined on my system. You can change it easily by replacing the name ~+"jijs_f4_fkey_jijs_"+~ with the name you prefer. Or you can define the key in ~+"Edit/Configure"+~. Just specify "output" to "quiet" or selections from the ijx window will not work.
I wish I had seen the script "trace.ijs" before I started this. It may be that the tools behind paren and trace could give a much simpler solution to this problem.
I have not included my own primitives file yet. It's really only for testing. Picking good mnemonics is not easy. That may be the hardest part.
Don Guinn email@example.com