Studio/Iterating with Class Verbs

From J Wiki
Jump to navigation Jump to search
Lab Iterating with Class Verbs
Author Oleg Kobchenko <olegyk@yahoo.com>, December 1998
Download {{tick|File:LabIterate.ijt    }}{{tick|File:LabIterate j401.ijt
}

|}


Introduciton

There have been discussions in JForum on iterating over a group of objects with verbs common to their classes.

In many OOP languages there are such groups for storing objects are called collections'. Hence, a method is applied to an indexed item rather than to an object directly.


Typically these uniform objects are nameless, and are accessed through indices. In C++ we would have something like:

dump (Item x) {out << x.value;}
main () {
  Collection c = new Collection();
  c.append(new Item(10)); c.append(new Item(20));
  out << c.item(0).add(c.item(1));
  for (i = 0 ; i <= c.count ; i++) {out << i.value}
  c.foreach(dump);
}

In J the official means of class verb application to objects is in named style:

  obj=. ''conew'myclass'
  myverb__obj ''

This is interpreted by the system as application of verb myverb, defined in class 'myclass' in the locale obj.


The second form of the same invocation is using the number of the object locale:

  >obj
21
  myverb_21_ ''

Both these forms are hardwired to the syntax. Such form of call syntactically produces a single entry

   ;:'myverb__obj'
+-----------+
|myverb__obj|
+-----------+
   ;:'myverb_21_'
+----------+
|myverb_21_|
+----------+

Purpose

Any interference with this syntax fails:

   myverb__(obj) ''        NB. this is reference to base
|value error: myverb__     NB. locale
|       myverb__(obj)''
   myverb_(obj)_ ''        NB. and this is a syntax error
|ill-formed name: myverb_

Our target is to be able to indicate the object indirectly, which symbolically can be expressed as:

  myverb__(obj) ''

Or iterate over a collection of objects:

  myverb__(obj1,obj2,obj3) ''

A special interest would be the ability to iterate also over a collection of class verbs in a single call, which is usually absent in traditional OOP, but makes sense in J:

  (meth1`meth2`meth3)__obj

Example with J locales

As a subject area we will chose the namespace model of J, which is familiar and always available. There are typical uses of locale switching technique:

   aa=: i.3
   nl''     NB. names in current locale
+--+
|aa|
+--+
   nl_j_ 0  NB. nouns in j locale
+-----+-------+--------+-----------+---------+------+---------
|BOXES|BROWSER|DIRTREEX|DISPLAYLOAD|EPSREADER|FORMAT|FORMSIZES...
+-----+-------+--------+-----------+---------+------+---------
   nl_z_ 1  NB. adverbs in z locale
+------+----+-----+-----------+---+-------+-----+----+----+---
|define|each|every|fapplylines|inv|inverse|items|leaf|rows|rxa...
+------+----+-----+-----------+---+-------+-----+----+----+---

But how can we get, say, all adverbs from several locales at once? Something like:

  nl__(z,j) 1

or we have a list of locales and want to study the ith element

  nl__(i{list)

Object dereferencing in J

There are several ways of indirect object reference in J.

1. Emulate the behavior of the system

a. switch to object's locale a. invoke the verb a. switch to current locale a. return the result

From Henry Rich (adapted by Oleg Kobchenko for j50x+):

   inlocalesx_z_=: 1 : '(u@] [ 18!:4@[)"0 _ ([ 18!:4) (18!:5)@(''''"_)'

   (nl 6) #@nl inlocalesx ''        NB. count of names
1 89 14 45 287 185 35 1 1 1 247
   (nl 6) <@$@:>@nl inlocalesx ''   NB. names matrix shapes
+---+-----+----+-----+------+------+-----+----+----+----+------+
|1 2|89 18|14 9|45 11|287 26|185 23|35 15|1 14|1 15|1 16|247 14|
+---+-----+----+-----+------+------+-----+----+----+----+------+

2. Use ". execute after building the full object name in a string

   loc=: (,&'_'@[ ,&'_'@, ":@>@])
   from=: ".@loc

   'PATHSEP' from 'j'
\
   PATHSEP_j_
\

3. Use ~ invoke or `: invoke gerund, also building the full object name in a string

This last one we will discuss in more detail.

Implementation

The unwritten laws of J style prescribe to chose tacit definitions. Some people believe that brevity also matters. Execute' is frowned upon.

We will define two short tacit conjunctions. One will simply construct a full object name, the other will use evoke over this name.

   in_z_=: 2 : 'm ,&(,&''_'') n'  NB. build a name
   fr_z_=: 2 : 'm in n~'          NB. evoke a name

   'nameA' in 'locA'
nameA_locA_

One of the reasons to reserve a separate name for the constructing conjunction is for making assignment:

   ('nameA' in 'locA')=. i.3 4
   $'nameA' fr 'locA'

Here are the examples how our conjunctions are used with nouns.

   $'nameA' in 'locA'~
3 4
   +/'nameA' fr 'locA'
12 15 18 21
   +/nameA_locA_
12 15 18 21

Verbs can be produced in a similar manner. Same for adverbs and conjunctions.

Notice how fr is applied over itself: 'fr' from the locale 'base'.

   ('verbA' in 'locA')=. +/ % #
   'verbA' fr 'locA' 'nameA' fr 'locA'
4 5 6 7
   verbA_locA_ nameA_locA_
4 5 6 7
   'verbA' 'fr' fr '' 'locA'  NB. fr over 'fr'
+/ % #

Now we will try to build an application of these conjunctions for examining J namespaces.

We will define another noun in locale 'locA' for demonstration purposes.

   [('bb' in 'locA')=. 1;<<"0 i.3
+-+-------+
|1|+-+-+-+|
| ||0|1|2||
| |+-+-+-+|
+-+-------+

We will need a group of verbs that will retrieve useful information about J names: class, type of noun, shape, level of boxing, size.

   cls_z_=: <@({&'nacv?u')@nc
   typ_z_=: 3 : '''blifc<xr''{~2^.3!:0 y~'&.>`(a:"_)@.(*@nc)
   shp_z_=: 3 : '$y~'&.>`(a:"_)@.(*@nc)
   lev_z_=: 3 : 'L.y~'&.>`(a:"_)@.(*@nc)
   siz_z_=: <@#@(3!:1`(5!:5)@.(*@nc))

   (],cls,typ,shp,lev,siz) <'bb_locA_'
+--------+-+-+-+-+--+
|bb_locA_|n|<|2|2|52|
+--------+-+-+-+-+--+

This is a verb that lists all this information for each name in a given locale.

Notice the use of fr', which iterates over a collection of names in a given locale, returned from nl loc'.

Also defined are two auxiliary verbs for restructuring the result and adding the header.

   lspack=: |:`(,:@:(<@:>"1)@:(,@":&.>))@.(*@(*/)@$)
   lshead=: (;:'name c t shape L size')&,^:(*@(*/)@$)

   ls=: ''&$: : (4 : 0)      NB. y unboxed locale name
r=. ,:n=. 'nl' fr y x     NB. x same as y for nl
r=. r, 'cls' fr y n
r=. r, 'typ' fr y n
r=. r, 'shp' fr y n
r=. r, 'lev' fr y n
r=. r, 'siz' fr y n
lshead lspack r
)

This is how it works. A clone of Unix shell command, suggested by Bjorn Helgason.

   ls 'locA'
+-----+-+-+-----+-+----+
|name |c|t|shape|L|size|
+-----+-+-+-----+-+----+
|bb   |n|<|2    |2|44  |
|nameA|n|i|3 4  |0|48  |
|verbA|v| |     | |6   |
+-----+-+-+-----+-+----+

This is a generalization of ls to list name classes in all locales, with a tail cutting argument x.

   lsall=: 20&$: : (4 : 0)
|:>(; <@({.~ x <. #)@":@(y&ls)) &.> nl 6
)

   15 lsall 0   NB. try this one, too
+-----------------------+-------------------------------------+----------
|base                   |j                                    |jcompare  ...
+-----------------------+-------------------------------------+----------
|+----+-+-+-----+-+----+|+------------------+-+-+-----+-+----+|+------+-+
||name|c|t|shape|L|size|||name              |c|t|shape|L|size|||name  |c|
|+----+-+-+-----+-+----+|+------------------+-+-+-----+-+----+|+------+-+
||aa  |n|i|3    |0|44  |||BOXES             |n|l|3 11 |0|48  |||MAXLCS|n|
|+----+-+-+-----+-+----+||BROWSER           |n|l|47   |0|48  |||MAXPFX|n|
|                       ||DIRTREEX          |n|l|0    |0|52  ||+------+-+
|                       ||DISPLAYLOAD       |n|b|     |0|52  ||
|                       ||EPSREADER         |n|l|49   |0|52  ||
|                       ||FORMAT            |n|i|6    |0|48  ||
|                       ||FORMSIZES         |n|i|5    |0|52  ||
|                       ||HTTPCMD           |n|l|36   |0|48  ||
|                       ||IFJIJX            |n|b|     |0|48  ||
|                       ||INPUTLOG          |n|<|2    |1|52  ||
|                       ||INPUTLOGFILE      |n|l|34   |0|56  ||
|                       ||LOADED            |n|<|4    |1|48  ||
+-----------------------+-------------------------------------+-----------

Iterating over verbs

You must have noticed the repetition in the body of ls':

r=. r, 'cls' fr y. n
r=. r, 'typ' fr y. n
r=. r, 'shp' fr y. n
r=. r, 'lev' fr y. n
r=. r, 'siz' fr y. n

Here comes the issue of iterating over a group of verbs.


The each adverb: &.> allows for its u. verb to iterate over the lists of boxed arguments (y. or x., y.). But there is no such entity that can modify a conjunction to iterate over its arguments (u. and v.).

Since in' is a conjunction already, we turn it into a verb, and modify fr' to include &.> and become a super each'.

Also, since we iterate over verbs, evoke (~) becomes evoke gerund (:).

   inV=: 4 : 'x in y'
   frV=: 2 : '(m inV &.> n)`:0'

And finally, the collection version of the lister shows mapping of a verbs collection over an object argument.

In this simplest case the shape of resulting gerund is linear. However more complex structures are possible and may be justified.

   lsc=: ''&$: : (4 : 0)
lshead lspack (, cls`typ`shp`lev`siz frV (<y)) 'nl' fr y x
)

Here we shall check that everything is still fine, comparing results of the two listers.

   0 (ls (;<) lsc)'j'
+---------------------------------------------------------------------------+
|+------------------+-+-+-----+-+----+|+------------------+-+-+-----+-+----+|
||name              |c|t|shape|L|size|||name              |c|t|shape|L|size||
|+------------------+-+-+-----+-+----+|+------------------+-+-+-----+-+----+|
||BOXES             |n|l|3 11 |0|48  |||BOXES             |n|l|3 11 |0|48  ||
||BROWSER           |n|l|47   |0|48  |||BROWSER           |n|l|47   |0|48  ||
||DIRTREEX          |n|l|0    |0|52  |||DIRTREEX          |n|l|0    |0|52  ||
||DISPLAYLOAD       |n|b|     |0|52  |||DISPLAYLOAD       |n|b|     |0|52  ||
||EPSREADER         |n|l|49   |0|52  |||EPSREADER         |n|l|49   |0|52  ||
||FORMAT            |n|i|6    |0|48  |||FORMAT            |n|i|6    |0|48  ||
||FORMSIZES         |n|i|5    |0|52  |||FORMSIZES         |n|i|5    |0|52  ||
||HTTPCMD           |n|l|36   |0|48  |||HTTPCMD           |n|l|36   |0|48  ||
||IFJIJX            |n|b|     |0|48  |||IFJIJX            |n|b|     |0|48  ||
||INPUTLOG          |n|<|2    |1|52  |||INPUTLOG          |n|<|2    |1|52  ||
||INPUTLOGFILE      |n|l|34   |0|56  |||INPUTLOGFILE      |n|l|34   |0|56  ||
||LOADED            |n|<|4    |1|48  |||LOADED            |n|<|4    |1|48  ||
||P2UPFONT          |n|l|22   |0|52  |||P2UPFONT          |n|l|22   |0|52  ||
||PATHSEP           |n|l|     |0|48  |||PATHSEP           |n|l|     |0|48  ||
||PDFREADER         |n|l|54   |0|52  |||PDFREADER         |n|l|54   |0|52  ||
||PRINTERFONT       |n|l|16   |0|52  |||PRINTERFONT       |n|l|16   |0|52  ||
||PRINTOPT          |n|l|0    |0|52  |||PRINTOPT          |n|l|0    |0|52  ||
||PUBLIC            |n|<|97 2 |1|48  |||PUBLIC            |n|<|97 2 |1|48  ||
||SCRIPTS           |n|l|45   |0|48  |||SCRIPTS           |n|l|45   |0|48  ||
||SHOWSIP           |n|b|     |0|48  |||SHOWSIP           |n|b|     |0|48  ||
||SMPRINT           |n|l|5    |0|48  |||SMPRINT           |n|l|5    |0|48  ||
||SM_CMONITORS      |n|i|     |0|56  |||SM_CMONITORS      |n|i|     |0|56  ||
||SM_CXVIRTUALSCREEN|n|i|     |0|60  |||SM_CXVIRTUALSCREEN|n|i|     |0|60  ||
||SM_CYVIRTUALSCREEN|n|i|     |0|60  |||SM_CYVIRTUALSCREEN|n|i|     |0|60  ||
||SM_XVIRTUALSCREEN |n|i|     |0|60  |||SM_XVIRTUALSCREEN |n|i|     |0|60  ||
||SM_YVIRTUALSCREEN |n|i|     |0|60  |||SM_YVIRTUALSCREEN |n|i|     |0|60  ||
||SYSTEMFOLDERS     |n|<|9 2  |1|56  |||SYSTEMFOLDERS     |n|<|9 2  |1|56  ||
||TARGET            |n|i|0 2  |0|48  |||TARGET            |n|i|0 2  |0|48  ||
||UNZIP             |n|l|34   |0|48  |||UNZIP             |n|l|34   |0|48  ||
||USERFOLDERS       |n|<|11 3 |1|52  |||USERFOLDERS       |n|<|11 3 |1|52  ||
||WINPOS            |n|<|8 2  |1|48  |||WINPOS            |n|<|8 2  |1|48  ||
||XDIFF             |n|l|0    |0|48  |||XDIFF             |n|l|0    |0|48  ||
|+------------------+-+-+-----+-+----+|+------------------+-+-+-----+-+----+|
+---------------------------------------------------------------------------+

   (ls -: lsc) &> nl 6
1 1 1 1 1 1 1 1 1 1 1 1

And provide another bulk lister in a slightly different scent.

   la=: 1 :'>,&.>/(,&":&>/)&.>(<y) (] ,&< u) &.>nl 6'

   ls la 1
base
+----+-+-+-----+-+----+
|name|c|t|shape|L|size|
+----+-+-+-----+-+----+
|la  |a| |     | |46  |
+----+-+-+-----+-+----+
j
jcompare
jfiles
jijs
jlab
jregex
+-------+-+-+-----+-+----+
|name   |c|t|shape|L|size|
+-------+-+-+-----+-+----+
|rxapply|a| |     | |171 |
|rxcdm  |a| |     | |23  |
|rxmerge|a| |     | |55  |
+-------+-+-+-----+-+----+
jviewmat
jwplot
jzgraph
locA
z
+-----------+-+-+-----+-+----+
|name       |c|t|shape|L|size|
+-----------+-+-+-----+-+----+
|define     |a| |     | |3   |
|each       |a| |     | |3   |
|every      |a| |     | |2   |
|fapplylines|a| |     | |409 |
|inlocalesx |a| |     | |52  |
|inv        |a| |     | |4   |
|inverse    |a| |     | |4   |
|items      |a| |     | |3   |
|leaf       |a| |     | |3   |
|rows       |a| |     | |2   |
|rxapply    |a| |     | |15  |
|rxmerge    |a| |     | |15  |
|table      |a| |     | |62  |
+-----------+-+-+-----+-+----+

It is defined as an adverb and allows us to choose the listing verb.

   lsc la 2
base
+----+-+-+-----+-+----+
|name|c|t|shape|L|size|
+----+-+-+-----+-+----+
|frV |c| |     | |22  |
+----+-+-+-----+-+----+
j
jcompare
jfiles
jijs
jlab
jregex
jviewmat
jwplot
jzgraph
locA
z
+----+-+-+-----+-+----+
|name|c|t|shape|L|size|
+----+-+-+-----+-+----+
|bind|c| |     | |13  |
|cuts|c| |     | |168 |
|def |c| |     | |2   |
|fr  |c| |     | |13  |
|in  |c| |     | |21  |
|on  |c| |     | |2   |
+----+-+-+-----+-+----+