From J Wiki
Jump to navigation Jump to search

simple problem solved simply in J, J video narration, APL and J in formal proofs, Dijkstra, tools shape thinking, distinct cognitive systems, updating J labs for version 8

Location:: BEST

Regular monthly meeting of NYCJUG on Tuesday, April 8th, 2014.

Meeting Agenda for NYCJUG 20140408

1. Beginner's regatta: some simple ways to approach a simple problem: see
"J as an Interviewing Tool.doc".

2. Show-and-tell: narration for J videos: see "J in 10 Minutes-Video2 narration
explanation and code.doc".

J on multiple devices: see "Infernal Devices".

3. Advanced topics: using APL/J for formal proofs - see "A letter from
Dijkstra on APL.doc".

4. Learning, teaching and promoting J, et al.: the hammer shapes the hand:
see "Shaping Tools Built our Brains.doc".

A perspective on different learning styles: see "Distinct Human Cognitive

The labs as J's most powerful advertisement: see "Updating J Labs for
Version 8.doc".


Starting with a problem Dan Bron had posted to the J-Forum, we compared the numerous succinct J solutions to the unwieldy one in Java offered in answer to the original question.

We then talked about the effectiveness of the recent, short videos introducing various J topics to a novice audience and the difficulties of narrating these videos.

We briefly marveled at Joe Bogner's recent flurry of effort to install J on every device he had available to him. Pepe compared his timings of "Joey Tuttle's problem" to J on one of his own, unconventional computing devices.

We then discussed the puzzling attitudes of the late Edsgar Dijkstra as evinced in a letter he sent to a colleague in 1982, as shown and discussed here by Roger Hui. Roger proceeds to discuss some of the points in Dijkstra's letter, then demonstrates some mathematical proofs using APL. In the PDF version attached here, I've included his original J version of the proofs alongside the APL version.

Next, we looked at some interesting, recent research suggesting that the human brain evolved in tandem with, and because of, the development of some of the earliest tools used by humankind. Continuing to examine cognition, we looked at other research purporting to show that people have at least two distinct cognitive systems: an explicit one under which we can reason about our reasoning process, and an implicit one that appears to function pre-consciously.

Finally, we concluded with a plea from Ian Clarke to get all the J labs updated to work in the latest release of the language, version 8. Some expressed the opinion that the labs are not necessarily one of the best pedagogical tools we have for learning and promoting J.

Beginner's Regatta

J as an Interviewing Tool

Preamble: Prefixes and Suffixes

To understand the following exchange, it would be good to review how J's "infix" (prefix) and "outfix" (suffix) adverbs work.

Here, we illustrate by applying the "box" verb "<" to directly illustrate how these adverbs affect the scope of the verb supplied to them.

   <\ 'abcde'            NB. Prefixes
   <\. 'abcde'           NB. Suffixes
   2<\'abcde'      NB. Fixed window
+--+--+--+--+      NB. prefix
   _2<\'abcde'     NB. Non-overlapping
+--+--+-+          NB. fixed window
   <\ \. 'abcde'         NB. Prefixes of
+-+--+---+----+-----+    NB. suffixes
|b|bc|bcd|bcde|     |
|c|cd|cde|    |     |
|d|de|   |    |     |
|e|  |   |    |     |
  <\. \ 'abcde'        NB. Suffixes of
+-----+----+---+--+-+  NB. prefixes
|a    |    |   |  | |
|ab   |b   |   |  | |
|abc  |bc  |c  |  | |
|abcd |bcd |cd |d | |

The Problem and Proposed Solutions

from:  Dan Bron
date:  Thu, Mar 27, 2014 at 3:37 PM
subject: [Jprogramming] J as an interviewing tool

A question on StackExchange [1]:

"I was asked the following interview question over the phone:

Given an array of integers, produce an array whose values are the product of every other integer excluding the current index.


[4, 3, 2, 8] -> [3*2*8, 4*2*8, 4*3*8, 4*3*2] -> [48, 64, 96, 24]


His answer is given in the postscript. It spans 3 kilobytes over 86 lines. The community's responses aren't much of an improvement (by that metric; by other metrics - Java-specific ones, they are decent advancements).

The J answer?

     1 */\. 4 3 2 8
 48 64 96 24

Could've answered the interviewer in a sentence, right over the phone.


[1] Code Review StackExchange question "Array whose values are the product of every other integer":

 import java.math.BigInteger;
 import java.util.Arrays;

 public class ProductOfAnArray {
     public static void main(String[] args) {
         try {
                     .calcArray(new int[] { 4, 3, 2, 8 })));
                     .calcArray(new int[] { 4, 0, 2, 8 })));
                     .calcArray(new int[] { 4, 0, 2, 0 })));
                     .calcArray(new int[] {})));
                             .calcArray(new int[] { 4, 3, 2, 8, 3, 2, 4, 6, 7,
                                     3, 2, 4 })));
                             .calcArray(new int[] { 4, 3, 2, 8, 3, 2, 4, 6, 7,
                                     3, 2, 4 })));
                     .calcArray(new int[] { 4432432, 23423423, 34234, 23423428,
                             4324243, 24232, 2342344, 64234234, 4324247,
                             4234233, 234422, 234244 })));
         } catch (Exception e) {
             // debug exception here and log.

      * Problem: Given an array of integers, produce an array whose values are
      * the product of every other integer excluding the current index.
      * Assumptions. Input array cannot be modified. input is an integer array
     public static BigInteger[] calcArray(final int[] inp) throws Exception {
         if (inp == null)
             throw new Exception("input is null");

         int cnt = 0;
         BigInteger multiple = new BigInteger("1");
         boolean foundZero = false;

         for (int i : inp)

          {    if (i == 0)

         {   cnt++; foundZero = true;
                 if (cnt < 2) continue;
                 else         break;
             multiple = multiple.multiply(BigInteger.valueOf(i));

         BigInteger ans[] = new BigInteger[inp.length];

         for (int i = 0; i < inp.length; i++) {
             if (foundZero) {
                 if (cnt < 2) {
                     ans[i] = (inp[i] == 0) ? multiple : new BigInteger("0");
                 } else {
                     ans[i] = new BigInteger("0");
             } else {
                 ans[i] = multiple.divide(BigInteger.valueOf(inp[i]));
         return ans;


from:  Roger Hui
date:  Thu, Mar 27, 2014 at 3:44 PM

Suppose you did not have the outfix operator, but still have array ops.

     x=: 4 3 2 8
    I=: =i.#x
 1 0 0 0
 0 1 0 0
 0 0 1 0
 0 0 0 1
    (-.I)*/ .(^~) x
 48 64 96 24


The brevity and expressiveness of J can be very impressive.

from:  Lee Fallat
date:  Thu, Mar 27, 2014 at 4:08 PM

Just wanted to say...

....Seriously blowing my mind here guys. I keep reconsidering completely learning J when I see things like this.

As for an interviewing tool, well, I'm sure it would impress many. ---

from:  Dan Bron
date:  Thu, Mar 27, 2014 at 4:10 PM

Oh, I like this game!

   (*/ % ]) 4 3 2 8
48 64 96 24
   (*/@#~1-=@i.) 4 3 2 8
48 64 96 24


from:  Thomas Costigliola
date:  Thu, Mar 27, 2014 at 4:26 PM

   (*/@{/~<@<@<"0@i.@#)  4 3 2 8
 48 64 96 24

[Thomas's answer deserves a little unraveling...]

     (<@<@<"0@i.@#)  4 3 2 8

It helps if you know that indexing with a triply-enclosed index removes the indexed item.

     ({/~<@<@<"0@i.@#)  4 3 2 8
  3 2 8
  4 2 8
  4 3 8
  4 3 2

So, he removes each item successively from the entire list before multiplying together the results.


from:  Peter B. Kessler
date:  Thu, Mar 27, 2014 at 4:36 PM

I came up with

   (%~ */) 4 3 2 8
48 64 96 24

but I think your solution is more readable.


Roger's reply demonstrates that short, simple expressions like this allow us to more easily deduce the full range of their behavior.

from:  Roger Hui
date:  Thu, Mar 27, 2014 at 5:06 PM

It fails when x has a 0 but is not all 0 :

    (*/ % ]) 2 0 8 3
 0 0 0 0


from:  Jose Mario Quintana
date:  Thu, Mar 27, 2014 at 5:52 PM

  */@}.@(|."0 _~ i.@#) 4 3 2 8
48 64 96 24


from:  Roger Hui
date:  Thu, Mar 27, 2014 at 5:58 PM

   */@-."1 0~ 4 3 2 8
 48 64 96 24
    */@-."1 0~ 4 0 2 8


J in 10 Minutes: 2. Desktop Application

I’ve offered to provide narration for Martin Saurer’s J videos. The one on which I’m currently working is the second one in which he claims to develop a desktop application in 10 minutes.

My technique for doing the narration is to compose a script while watching the video. I include the elapsed time of the video at numerous points in the script to help pace it.

So, the initial section of the current script looks something like this:

Script for narration of : "J in 10 minutes (2. Desktop Applications)":

J is a general-purpose, high-performance, array-oriented programming language.  It is also a notation for expressing computational concepts clearly and concisely.

We're going to show you, in ten minutes, how to write a full-fledged desktop application in J based on the Qt user-interface framework.


Here we see an example of an interactive J session window, the version that runs under Qt.  The lines beginning with "NB." are comments.

We define the GUI in what we call a noun, which is variable named "first_gui".  This noun lists windowing commands to define a parent control named "first", labeled with the text "My first window".  This parent contains a child control - a button named "but1" - labeled with the text "My first button".


Next we define a J verb - a program - named "first_start" to start up our GUI object.

This verb runs a series of "wd" commands to perform different windowing operations based on its arguments.  These arguments are character strings.
The first "wd" command uses our previously-defined "first_gui" noun as its argument, defining the form we mentioned.

The second use of "wd" invokes the command "pshow" to display the form.  The third "wd" command places the form 600 pixels over and 300 down with a size 200 across and 200 down.


Code for Video

The result of the demo presents a GUI, backed by some data from files, that looks like the following. example of GUI for "Swiss weather" application from video

The code presented at the end of the video looks like this.

NB. ****************************************************************************
NB. File:        MeteoDemo.ijs
NB. Author:      Martin Saurer, Datavision GmbH, 02.03.2014
NB. Description: visulaization of swiss weather data
NB.              (rain & temperature) 1864-2013.
NB. License:     GPL Version 3.
NB. ****************************************************************************

NB. Required library scripts
require 'tables/dsv'
require 'graphics/plot'

I suggested to the author that the following change be made since the code as written will not run if imported into a directory other than the one assumed by the code. The following change allows the user to set "FilePath" to the proper root directory in which the files reside before loading the code and not have the loaded code reset it if it already exists.

nameExists=: 0:"_ <: [: 4!:0 <^:(L. = 0:)
NB. Specify data path and files
3 : 0 ]0
   if. -. nameExists 'FilePath' do. FilePath =: '~user/MeteoDemo/' end.

The rest of the code is as follows.

DataFile =: 'WeatherData.csv'
StatFile =: 'WeatherStations.csv'

NB. Read Data Files
data =: (';';'') readdsv jpath FilePath,DataFile
stat =: (';';'') readdsv jpath FilePath,StatFile

NB. Build array with weather station keys (symbols) and clear names
stat =: |:(0,1){|:((I.(0{|:stat)e.(0{|:data)){stat)

NB. Split 2nd column string ('yyyymm') into 2 columns yyyy | mm, and
NB. convert these strings to numbers
NB. Convert 3rd and 4th column from strings to numbers
yeamon =: (>(". each (1{|:data)))%100
years  =: ;/<.yeamon
months =: ;/1+<.100*(yeamon-(<.yeamon))
data   =: (0{|:data),.years,.months,.(". each 2{|:data),.(". each 3{|:data)
data=: (10*&.>_1{"1 data) _1}&.|:data  NB. Temp in tenths of a degree.

NB. Utility verb to get weather station text from key
stat_get_text    =: 3 : '>(I. (<y) E. 0{|:stat){1{|:stat'

NB. Utility verbs to select records from data
data_get_station =: 4 : ' (I. (<y) E. 0{|:x){x'
data_get_year    =: 4 : ' (I. (<y) E. 1{|:x){x'
data_get_month   =: 4 : ' (I. (<y) E. 2{|:x){x'

NB. Month/Year labels for plot and GUI
month_names =: <;._2] 0 : 0
month_labels =: 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec'
month_ticks  =: ": i. 12
year_labels  =: ": 1864 + 10 * i. 16
year_ticks   =: ": 10 * i. # ". year_labels

NB. Utility verb to create LF separated string
vfmx =: 3 : '}:(,|."1 [ 1,.-. *./\"1 |."1 y='' '')#,y,.LF'

NB. Utility verb to get event data for a widget
getval =: 3 : 0
   fd =. wd 'qd'
   >(((<y) E. 0{|:fd) i. 1) { (1{|:fd)

NB. Default values for station, year, month
statkey =: >0{0{|:stat
yearkey =: 0
montkey =: 0

NB. GUI definition
meteo_win =: 0 : 0

   rem Window name;
   pc meteo;

   rem Window title;
   pn Swiss Weather Data (Rain/Temperature) of the Years 1864-2013;

   rem Vertical then horizontal panel;
   bin vh;

   rem Three selection lists: Waether station, Year, Month;
   bin v; cc l1 static; cn Station; cc statlist listbox; bin z;
   bin v; cc l2 static; cn Year;    cc yearlist listbox; bin z;
   bin v; cc l3 static; cn Month;   cc montlist listbox; bin z;

   rem Grid;
   bin zg;

   rem Grid cell;
   grid cell 0 0; minwh 640 320;

   rem Isigraph control as plot output;
   cc plotwind isigraph;

NB. GUI start
meteo_run =: 3 : 0
   wd 'reset'
   wd meteo_win

   plotwind            =: conew 'jzplot'
   PForm__plotwind     =: 'meteo'
   PFormhwnd__plotwind =: wd 'qhwndp'
   PId__plotwind       =: 'plotwind'

   wd 'set statlist items ',vfmx > dquote each 1{|:stat
   wd 'set yearlist items ','"*" ',":>~.1{|:data
   wd 'set montlist items ','"*"',LF,vfmx > dquote each month_names

   wd 'pcenter'
   wd 'pshow'

   wd 'set statlist select 0'
   wd 'set yearlist select 0'
   wd 'set montlist select 0'

   wd 'pmove 300 100 800 600'

NB. GUI end
meteo_close =: 3 : 0
   wd 'pclose'

NB. Weather station list event handler
meteo_statlist_select =: 3 : 0
   statkey =: > (". getval 'statlist_select') { 0{|:stat
   if. (#statkey) = 0 do.
      statkey =: >0{0{|:stat

NB. Year list event handler
meteo_yearlist_select =: 3 : 0
   yearkey =: ". getval 'yearlist_select'
   yearkey =: yearkey + ((yearkey > 0) * 1863)

NB. Month list event handler
meteo_montlist_select =: 3 : 0
   montkey =: ". getval 'montlist_select'

NB. Update plot window
meteo_plotwind_paint =: 3 : 0

   NB. Reset
   pd__plotwind 'reset'

   NB. Error handler

      NB. Legend
      pd__plotwind 'textcolor blue'
      pd__plotwind 'text 50 900 Rain mm/m^2'
      pd__plotwind 'textcolor red'
      pd__plotwind 'text 50 840 Temperature °C*10'

      NB. X-Axis labels
      if. yearkey = 0 do.
         pd__plotwind 'xticpos ',year_ticks
         pd__plotwind 'xlabel  ',year_labels
         if. montkey = 0 do.
            pd__plotwind 'xticpos 0'
            pd__plotwind 'xlabel  0'
         if. montkey = 0 do.
            pd__plotwind 'xticpos ',month_ticks
            pd__plotwind 'xlabel  ',month_labels
            pd__plotwind 'xticpos 0 1 2'
            pd__plotwind 'xlabel _ ',(>(montkey-1){month_names),' _'

      NB. Plot data
      plot_data =. data data_get_station statkey
      if. yearkey > 0 do.
         plot_data =. plot_data data_get_year yearkey
      if. montkey > 0 do.
         plot_data =. plot_data data_get_month montkey

      NB. Rain data
      rain_data =. |:>3{|:plot_data
      if. (#rain_data) < 2 do.
         rain_data =. 3 $ rain_data

      NB. Temperature data
      temp_data =. |:>4{|:plot_data
      if. (#temp_data) < 2 do.
         temp_data =. 3 $ temp_data

      NB. Rain data
      pd__plotwind 'color blue'
      pd__plotwind rain_data

      NB. Temperature data
      pd__plotwind 'color red'
      pd__plotwind temp_data

      NB. Show
      pd__plotwind 'show'


NB. Start GUI

Advanced topics

This article (subscription required), in The New Scientist magazine, reports on the theory of Frederick Coolidge and Thomas Wynn at the University of Colorado in Colorado Springs who argue that humans'

last cognitive leap was down to a chance mutation that increased our ability to hold several ideas in mind and manipulate them. Even in modern humans, this "working memory" is limited to about seven items. However, a small increase would have had huge consequences. An improved ability to remember what had just been said would have increased the sophistication of conversation, allowing more complex grammar with many different clauses. That means you can think and plan more hypothetically, using "what if" and "if, then" statements, for instance.

Working memory is also associated with creativity and innovation, because it allows you to mentally explore different solutions to a problem. Wynn and Coolidge also point to research suggesting that enhanced working memory could have improved our long-term memory and future planning because it provides a bigger mental "blackboard" on which we can assemble the details of our past experiences, and draw on them to work out the best way to proceed with the task ahead.

Other scientists quoted in the article, Bruce Bradley and Nada Khreisheh at the University of Exeter, are building a case that links the development of certain kinds of (stone-age) tools to the development of distinctively human cognitive abilities. For instance, "[t]he idea of using one tool to create a more useful implement is itself a conceptual leap. But just as important is the fact that it takes a dexterity and motor control not seen in other apes to create [a] jagged Oldowan-style tool.... This includes coordinating your limbs so that one hand is doing a different job from the other."

From the perspective of a J tool-user, this raises some interesting possibilities about the way the use of a tool may shape how we think.

From the standpoint of teaching J, another article on some scientific research, which points to the existence of distinct human cognitive systems, appears at least somewhat germane.

This article's summary states that "[c]ognitive scientists may have produced the strongest evidence yet that humans have separate and distinct cognitive systems with which they can categorize, classify, and conceptualize their worlds." These two systems, one "explicit", meaning that this kind of thought is conscious and available to introspection, the other "implicit", which is not conscious or amenable to introspection.

Learning, teaching and promoting J

Updating J Labs for Version 8.01

from:	 Ian Clark
to:	 General forum <>
date:	 Mon, Mar 17, 2014 at 1:30 PM
subject: [Jgeneral] Labs and demos for j801

Labs and demos are vital vehicles for attracting and retaining a new J audience. Not to say helping people rapidly acquire a new J skill. J602 had a fine set of labs. Some run as they stand under JHS and JQt, not to mention JConsole. But we don't know which those are.

M$ and IBM have an army of documenters who make sure a new version is released with a viable library of manuals and on-line helps. Comparisons are invidious. Jsoftware, being a tiny company, is pretty streamlined in that regard. Most of our documentation is written by keen users - and there's no other way to do it.

1. Could I issue an appeal from Chris Burke and myself for all contributors of j602 labs to revise them for j801? You can contact me as the focal point for this exercise (though I can't undertake to troubleshoot the inevitable technical issues--but we do have a programming forum).

2. We need a legion of grunts to do simple testing. That means running the Labs menu and choosing each lab in turn and seeing if it runs -- and if not why not.

I've given up on a Control- page for this exercise. J801 is far less cross-platform than J602, so each platform needs testing separately. As I said above, you can contact me as the focal point for this exercise (though I can't undertake to troubleshoot code issues).

Please contact me by PM (see Ian Clark on jwiki). Please don't clutter the forum with stuff on individual labs at this stage. I guess it's too much to expect you to go into Trac and fix the code yourself (though that would be stellar!). So a simple PM to me saying what works and what doesn't will do for a start. I shall endeavour to record all this somewhere on a public chart, to avoid the worst duplication of effort. I shall also broadcast progress from time to time.

The immediate aim is to avoid shipping a fubar list of labs. This will initially result in a much-depleted list, but too bad! A secondary aim (pie in the sky) is to migrate all the valuable j602 labs to J801 platforms. The first objective is absurdly simple. The second absurdly difficult. There are new docs on the wiki, starting at, which also include a section on migration.

Happy testing!

Ian Clark


-- Devon McCormick <<DateTime(2014-04-15T18:47:52-0200)>>