David Ness
Mind / Matter

An Experiment in J and K

By David Ness
Thursday, December 7, 2000

Data Base

For reasons that are too boring and complex to go into, I keep my phone/address data in a format that is (indirectly) compatible with a large number of different systems that I regularly use that need to have this information. This format consists of lines that are of the form `Label: Value', where items are separated from one another by `---------' lines used as a separator. The first item in the data base is a dummy, and contains all possible item labels. All of the real items in the data base only have the labels needed for each particular item (i.e. if an item doesn't have an `address', we simply leave out the address related labels).

The worst of the  programs that process this data is clearly, in my experience, Microsoft Outlook, so the format chosen works particularly nicely with that system. Various perl and other programs re-map the data into forms appropriate for all of the uses. All of the other programs are much easier to manage, so handling the data in a form for these programs is an easy task compared to Outlook.

Data kept in the form given here is easy to manage, I generally create new entries and modify old entries with any old ASCII editor that happens to be available.


The code, as written, assumes the phone list is in C:\PHONE.LNG, Each piece of this code refers to this file only in one place, so it would be easy to put it elsewhere. The code is designed to be called from a command line in a DOS window under any version of Windows that I know. I would imagine that it also would work under Linux, but I haven't tested that yet. There are three files that need to be downloaded, the `test' data base, the J code and the K code. Due to obscurities with how files are passed (I can't do FTP from my site), these files have to be `browsed' and saved under appropriate names in appropriate places. Given that there are only three files (the test data + 2 code snippets), I hope this isn't an arduous task. As an alternative, and depending on your browser, the appropriate information could be snipped from the file that is downloaded to produce the display you are now reading.


Both of the programs expect to be called in essentially the same way. To execute the J code, open a DOS box and execute `J JCODE Name' (where JCODE is the name of the J program). Similarly, to execute the K code, execute K KCODE Name.


As will be clear from looking at the code, I am not a good J or K programmer. What is interesting to me, however, is that I can program in both J and K and get useful things done, without being a good programmer. That's consoling news for those of us who aren't profoundly good at this stuff.

Accessing the Data

Rather than boring anyone with my real phone list, I make available a very small data base that can be used to test the programs and experiment with the software.


All of the code runs sufficiently fast that it doesn't seem to me to be worth trying to do any timing comparisons. I was somewhat surprised I found coding in K to be easier, for this problem, than with J. I have substantially more experience with J, so I expected it to be the other way. 

Code Commentary

I now present the J and K code that was used to solve this problem.

It is not obvious how much we should assume the reader knows about J and K in this note. What is obvious, however, is that there is no particular amount of discussion that will be right for everyone.

In addition, some lines are too long to be displayed as a single line. Here I have broken them at a blank and then indented the continuation on the next line with five extra spaces of indentation. I hope that this will not cause confusion.

J Code

The J code is reasonably daunting. And being forced to break lines for display purposes doesn't help much. But perhaps with a few words, the general drift can be understood.

The a array gets a copy of the input file, with the EOF and CR trimmed (if they were present), and then the lines are boxed, and the separator lines are replaced with lines that look like

End: End

so that they will conform to the format of all of the rest of the lines in the file. Once this is done we create tab to contain all of the values of the name fields. This information is then used to re-code all of the items in the data base to convert the text values in the name field into index values.

NB. <$Load Phone DB
     - Ver DN-1A(2) - [HRU-WHEP]$>
NB. called by JPHONE.BAT containing:
NB. `e:\j406\j.exe e:\j406\user\dnn\phone.ijs %*'
Toss =: 26 13{a.	NB. characters to throw away
s =: ' '"_    NB. space and separator constants
c =: ': '"_
NB. load the phone db, toss EOF/CR and cut into lines
a =: ([: (< ;. _2) (] (#~) ([: -. 
     (Toss"_ (e.~) ])))) 1!:1 <'c:\phone.lng'
NB. find the lines that are separators 
     and replace them with `End: End'
v =: (# i.@#) > ([: +./ '-----'"_ E. ]) each a
a =: (<'End: End') v}a
NB. build thd data base and a list of column titles
tab =: 0{|:(>:0{v){.db =: (1&}.) 
     each"0 >(sl=:(c E. s,],c)
     (<;._2)(s,(],c))) each a
NB. replace labels with index numbers
db =: |: (<"0 (tab i. 0{|:db)) 0} |: db

This pretty much takes care of the set-up. Then there are some functions that are useful.

NB. `r n' displays the nth entry
r =: 3 : '>,,.sl each a{~([ (+i.) -~)/ 
     1 0 + (y. + 0 1){_1,v'
NB. `l n' gives item number that contains line n
l =: 3 : '0{(# i.@#) (_1}.y.>_1,v) *. y. <: v'
NB. get the (last) command argument
cmd =: >_1{< ;. _2 (11!:0 'qcmdline'),' '
NB. `sh n' is a lot like `r n', but I 
     think it's prettier
sh =: 3 : 0
   xx =: >0{zz =: |:(1&}.) each r y.
   (<>(-+/*./ \|.' '=|:xx)|. 
        each <"1 xx),.<>1{zz
NB. `fn text' yields the column of data named `text'
fn =: 3 : 0
   tt =: ~. > l each <"0 xx =: (# i.@#) 
        (tab i. 0{"1 db
   (1{"1 xx{db) tt} (#v)$<''
NB. build a base of what we want to display
Data =: |:>fn each ('Last Name';
     'First Name';'Home Phone';'Business Phone')
NB. find the items that have elements that 
     match the argument
m =: 3 : '~.>l each (# i.@#)> +/ 
     each y.&E. each a'
NB. display it
((0,m cmd){Data) 1!:2 (2)

This creates a program which can act to display the given information from the data base.

K Code

The K code is even more terse.

/ <$Load Phone DB 
     - Ver DN-1A(3) - [GKR-UHKM]$>
/ Called from PHONE.BAT with `k phone %*'
c:_i	/ save command args
a:0:"phone.lng" / get the data base
v:a _sm\: "----------*"  / find lines that end entries
a[v]:(#v:&v)#,"End: End"  / make them `End: End'
/ `r n' dumps nth entry
r:{ x:,/x; a[b+!v[x[0]]-b:1+(-1,v)[x[0]]]}   
/ `l n' finds entry # that contains line n
l:{-1 # &(x>-1 _ -1,v)&x<1 _ v,1+#a} 
/ prepare to cut up lines
cl: 0,/: cp ,' 2 + cp: a _ss \ ": "   
db: (+cl _' a)[0 2;]  / cut them and toss `: '
tab: db[0;!v[0]]	/ get keys from 1st item
db[0;]: tab ?/: db[0;] / `key' the items
/ fn["Field Name"] crates a 
     `column' of that particular field
fn: { p: &db[0;] = (tab ?/: ,x)[0]; 
     h: (#v)#,""; h[,/l'p]: db[1;p]; h}
/ pickup the fields of interest in this example
Data: fn'("Last Name";"First Name";
     "Home Phone";"Business Phone")
/ find the items that match command 
     arg, doing a `nub' in the process
m: & (!#v) _in\: ,/ l'&a _sm\: "*",c[0],"*"
/ display them
`show $ +(-15;-15;-15;-15) $/: +Data[;0,m]

This highlights both the differences and the similarities of J and K.

Sample Data

This is only a `shadow' of the real data base, but it is enough to test the concepts and the code that has been presented.

Title: Title
First Name: First Name
Middle Name: Middle Name
Last Name: Last Name
Suffix: Suffix
Company: Company
Department: Department
Job Title: Job Title
Business Street: Business Street
Business Street 2: Business Street 2
Business Street 3: Business Street 3
Business City: Business City
Business State: Business State
Business Postal Code: Business Postal Code
Business Country: Business Country
Home Street: Home Street
Home Street 2: Home Street 2
Home Street 3: Home Street 3
Home City: Home City
Home State: Home State
Home Postal Code: Home Postal Code
Home Country: Home Country
Other Street: Other Street
Other Street 2: Other Street 2
Other Street 3: Other Street 3
Other City: Other City
Other State: Other State
Other Postal Code: Other Postal Code
Other Country: Other Country
Assistant's Phone: Assistant's Phone
Business Fax: Business Fax
Business Phone: Business Phone
Business Phone 2: Business Phone 2
Callback: Callback
Car Phone: Car Phone
Company Main Phone: Company Main Phone
Home Fax: Home Fax
Home Phone: Home Phone
Home Phone 2: Home Phone 2
Mobile Phone: Mobile Phone
Other Fax: Other Fax
Other Phone: Other Phone
Pager: Pager
Primary Phone: Primary Phone
Radio Phone: Radio Phone
TTY/TDD Phone: TTY/TDD Phone
Telex: Telex
Account: Account
Anniversary: Anniversary
Assistant's Name: Assistant's Name
Billing Information: Billing Information
Birthday: Birthday
Categories: Categories
Children: Children
Directory Server: Directory Server
E-mail Address: E-mail Address
E-mail Display Name: E-mail Display Name
E-mail 2 Address: E-mail 2 Address
E-mail 2 Display Name: E-mail 2 Display Name
E-mail 3 Address: E-mail 3 Address
E-mail 3 Display Name: E-mail 3 Display Name
Gender: Gender
Government ID Number: Government ID Number
Hobby: Hobby
Initials: Initials
Internet Free Busy: Internet Free Busy
Keywords: Keywords
Language: Language
Location: Location
Manager's Name: Manager's Name
Mileage: Mileage
Notes: Notes
Office Location: Office Location
Organizational ID Number: Organizational ID Number
PO Box: PO Box
Priority: Priority
Private: Private
Profession: Profession
Referred By: Referred By
Sensitivity: Sensitivity
Spouse: Spouse
User 1: User 1
User 2: User 2
User 3: User 3
User 4: User 4
Web Page: Web Page
Last Name: Zabar's
Business Street: 2245 Broadway (at 80th St)
Business City: New York
Business State: NY
Business Postal Code: 10024
Business Country: USA
Business Phone: 212/496-1234
Business Phone 2: 800/697-6301
Business Fax: 212/580-4477
Web Page: www.zabars.com
User 1: Zabars
Last Name: Cedar Inn
Business Street: 6th and Main
Business City: Starbuck
Business State: MN
Business Country: USA
Business Phone: 320/239-4300
User 1: Cedar
First Name: Alexander
Last Name: Pushkin
Business Street: 1234 Harvard Yard Mail Center
Business City: Cambridge
Business State: MA
Business Postal Code: 02138-7501
Business Country: USA
Business Phone: 555/121-1212
User 1: Alexander
First Name: Nancy
Last Name: Everfast
Business Street: Brown Systems Inc.
Business Street 2: 1212 Chattanooga
Business City: Mountain View
Business State: CA
Business Postal Code: 94040
Business Country: USA
Business Phone: 800/555-1212
User 1: Brown
First Name: Carol
Last Name: Edgeworth
Home Street: 211 W 49st St.
Home Street 2: #4
Home City: New York
Home State: NY
Home Postal Code: 10023
Home Country: USA
Home Phone: 555/112-2121
Business Phone: 555/312-1234
User 1: Edgeworth
First Name: Irene
Spouse: Paul
Last Name: Pushkin
Home Street: 101 Valley View Drive
Home City: Tampa
Home State: FL
Home Postal Code: 33606--1111
Home Country: USA
Home Phone: 555/123-2222
User 1: Irene
E-mail Address: ppush@tampabay.rr.com

David Ness' summary of work can be found at http://mywebpages.comcast.net/dness

Some feeling for J and K may result from looking how a simple problem is coded.