Help / Learning / Ch 26: Script Files

From J Wiki
Jump to navigation Jump to search


>> << Pri JfC LJ Phr Dic Voc !: Rel NuVoc wd Help Learning J


Chapter 26: Script Files

A file containing text in the form of lines of J is called a script-file, or just a script. By convention a script has a filename terminating with .ijs . The process of executing the lines of J in a script-file is called "loading" a script.

We write our own scripts for our particular programming projects. In addition, the J system comes supplied with a library of predefined scripts of general utility.

The plan for this chapter is to look at

  • built-in verbs for loading scripts
  • the load verb and its advantages, including convenient loading of library scripts
  • the "profile" script automatically loaded at the beginning of a J session

26.1 Creating Scripts

It will be useful to identify a directory where we intend to store our own scripts.

There is a directory j701-user convenient for the purpose. It is installed automatically as part of a J installation. Its full pathname is given by

   jpath '~user'
c:/users/homer/j701-user
   

A variable, scriptdir say, can hold the name of our chosen script directory together with a trailing '/'

   ] scriptdir =: (jpath '~user') , '/' 
c:/users/homer/j701-user/
   

Scripts are usually created using a text editor, but we can use J to create small examples of scripts as we need them. Here is an example of creating a tiny script, with a filename of say example.ijs, using the built-in verb 1!:2 thus:

   (0 : 0) (1!:2) < scriptdir,'example.ijs'
plus =: +
k    =: 2 plus 3
k plus 1   
)

26.2 Loading Scripts

There is a built-in verb 0!:1 to load a script. The argument is a filename as a boxed string.

   0!:1 < scriptdir,'example.ijs'
   plus =: +
   k    =: 2 plus 3
   k plus 1   
6

We see on the screen a display of the lines of the script as they were executed, together with the result-values of any computations. The definitions of plus and k are now available:

plus k
+ 5

The verb 0!:1, as we saw, loads a script with a display. If there is an error in the script, 0!:1 will stop. We can choose whether or not to display, and whether to stop or to continue loading after an error. There are four similar verbs:

0!:0 no display stopping on error
0!:1 with display stopping on error
0!:10 no display continuing on error
0!:11 with display continuing on error

For example:

   0!:0 < scriptdir,'example.ijs'

We see nothing on the screen. The value computed in the script for k plus 1 is discarded.

26.3 The load Verb

There is a verb load which is predefined, that is, automatically available in the standard J setup. It can be used just like 0!:0 to load a script

   load < scriptdir,'example.ijs'

The script is loaded without a display and stopping on error. There is a companion verb loadd which loads with a display, stopping on error.

   loadd < scriptdir, 'example.ijs'
   plus =: +
   k    =: 2 plus 3
   k plus 1   
6

load and loadd have several advantages compared with 0!:n . The first of these is that the filename need not be boxed.

   loadd scriptdir, 'example.ijs'
   plus =: +
   k    =: 2 plus 3
   k plus 1   
6
   

26.4 Local Definitions in Scripts

Now we look at the treatment of local variables in scripts. Here is an example of a script.

   (0 : 0) (1!:2) < scriptdir, 'ex1.ijs'
w   =: 1 + 1
foo =: + & w  
)

Suppose that variable w has the sole purpose of helping to define verb foo and otherwise w is of no interest. It would be better to make w a local variable.

Firstly, we need to assign to w with =. in the same way that we assign to local variables in explicit functions. Our revised script becomes:

   (0 : 0) (1!:2) < scriptdir, 'ex2.ijs'
w   =. 1 + 1
foo =: + & w  
)

Secondly, we need something for w to be local to, that is, an explicit function, because outside any explicit function (that is, "at the top level") =. is the same as =: All that would be needed is the merest wrapper of explicit definition around 0!:n, such as:

   LL =: 3 : '0!:0 y'

If we now load our script

   LL < scriptdir, 'ex2.ijs'

and then look at the results:

foo w
+&2 error

we see that foo is as expected, and, as intended, there is no value for w. Therefore w was local to the execution of the script, or strictly speaking, local to the execution of LL.

An advantage of the load verb is that it provides the explicit function needed to make w local.

   erase 'foo';'w'
1 1
   
   load scriptdir, 'ex2.ijs'

foo w
+&2 error

26.4.1 Local Verbs in Scripts

In the previous example, the local variable w was a noun. With a local verb, there is a further consideration. Here is an example of a script which tries to use a local verb (sum) to assist the definition of a global verb (mean).

   (0 : 0) (1!:2) < scriptdir, 'ex3.ijs'
sum  =. +/
mean =: sum % # 
)
   
   load  < scriptdir, 'ex3.ijs'

We see that this will not work, because mean needs sum and sum, being local, is no longer available.

mean sum
sum % # error

The remedy is to "fix" the definition of mean, with the adverb f. (as we did in Chapter 12). Our revised script becomes

   (0 : 0) (1!:2) < scriptdir, 'ex4.ijs'
sum =. +/
mean =: (sum % #)  f.
)

Now mean is independent of sum

   load  < scriptdir, 'ex4.ijs'

mean sum
+/ % # error

26.5 Loading Into Locales

We looked at locales in Chapter 24. When we load a script with 0!:n or load it is the current locale that becomes populated with definitions from the script.

By default, the current locale is base. In general, we may wish to load a script into a specified locale, say locale one.

Here is one way:

   load_one_  scriptdir, 'example.ijs'
   
   plus_one_
+

Another way is to let the script itself specify the locale. For example,

   (0 : 0) (1!:2) < scriptdir, 'ex5.ijs'
18!:4 < 'two'
w   =. 1 + 1
foo =: + & w  
)

and then the script steers itself into locale two

   load scriptdir, 'ex5.ijs'
   
   foo_two_
+&2

Here is a further advantage of load compared with 0!:n. Notice that the current locale is base.

   18!:5 ''  NB. current locale before loading
+----+
|base|
+----+

If we now load ex5.ijs, the current locale is still base afterwards, regardless of the fact that the script visited locale two.

   load scriptdir,'ex5.ijs'
   18!:5 ''  NB. current locale after loading
+----+
|base|
+----+

However, loading the same script with 0!:n does NOT restore the previously current locale.

   18!:5 '' NB. current locale before loading
+----+
|base|
+----+
   0!:0 < scriptdir,'ex5.ijs'
   18!:5 '' NB.  current locale after loading
+---+
|two|
+---+
   

so we conclude that self-steering scripts should be loaded with load and not with 0!:n.

We return to base.

   18 !: 4 < 'base'

26.6 Repeated Loading, and How to Avoid It

Another advantage of load is this. Suppose one script depends on (definitions in) a second script. If the first includes a line such as load 'second' then

the second is automatically loaded 

when the first is loaded.

If we load the first script again (say, after correcting an error) then the second will be loaded again. This may be unnecessary or undesirable. The predefined verb require is like load but does not load a script if it is already loaded.

Here is a demonstration. Suppose we have these two lines for the first script:

   (0 : 0) (1!:2) < scriptdir,'first.ijs'
    require scriptdir, 'second.ijs'
    a =: a + 1
)

Here the variable a is a counter:

every time first.ijs is loaded,
a will be incremented. 

Similarly for a second script:

   (0 : 0) (1!:2) < scriptdir, 'second.ijs'
    b  =: b + 1
)

We set the counters a and b to zero, load the first script and inspect the counters:

(a =: 0),(b =: 0) load scriptdir, 'first.ijs' a,b
0 0   1 1

Evidently each script has executed once. If we now load the first again, we see that it has executed again, but the second has not:

load scriptdir,'first.ijs' a,b
  2 1

26.7 Load Status

The J system keeps track of ALL scripts loaded in the session, whether with load or with 0!:0. The built-in verb 4!:3 with a null argument gives a report as a boxed list of filenames. Here are the last few entries in this report for the current session.

   ,. _4 {. 4!:3 ''
+-----------------------------------+
|c:\users\homer\j701-user\ex4.ijs   |
+-----------------------------------+
|c:\users\homer\j701-user\ex5.ijs   |
+-----------------------------------+
|c:\users\homer\j701-user\first.ijs |
+-----------------------------------+
|c:\users\homer\j701-user\second.ijs|
+-----------------------------------+
   
   

Recall that we defined plus in the script example.ijs which we loaded above. The built-in verb 4!:4 keeps track of which name was loaded from which script. The argument is a name (plus for example) and the result is an index into the list of scripts generated by 4!:3. We see that plus was indeed defined by loading the script example.ijs

i =: 4!:4 < 'plus' i { 4!:3 ''
14 +------------------------------------+

|c:\users\homer\j701-user\example.ijs|

+------------------------------------+

26.8 Library Scripts

26.8.1 The Standard Library

The J system comes supplied with script files containing a useful collection of predefined functions.

We can look at the list of scripts loaded automatically at the beginning of the session. For this we use the built-in verb 4!:3 to generate a boxed list of file-names. Here are the first 9 scripts:

   ,. 9 {. 4 !: 3 ''
+---------------------------------------------+
|C:\users\homer\j701\bin\profile.ijs          |
+---------------------------------------------+
|C:\users\homer\j701\system\util\boot.ijs     |
+---------------------------------------------+
|C:\users\homer\j701\system\main\stdlib.ijs   |
+---------------------------------------------+
|C:\users\homer\j701\system\util\scripts.ijs  |
+---------------------------------------------+
|C:\users\homer\j701\system\main\regex.ijs    |
+---------------------------------------------+
|C:\users\homer\j701\system\main\task.ijs     |
+---------------------------------------------+
|C:\users\homer\j701\system\util\configure.ijs|
+---------------------------------------------+
|c:\users\homer\j701-user\config\recent.dat   |
+---------------------------------------------+
|c:\users\homer\j701\system\main\ctag.ijs     |
+---------------------------------------------+
   

We see that among these is the script-file stdlib.ijs

Functions defined in stdlib.ijs end up in the z locale where they are conveniently available to the programmer. There are more than 300 things defined in the z locale:

   # nl_z_ ''
369
   

For example, the file-handling utility functions documented in the

J User Manual

are found in the z locale with names beginning with the letter 'f'.

   6 6 $ 'f' nl_z_ ''
+--------+----------+--------+-----------+---------+--------------+
|f2utf8  |fappend   |fappends|fapplylines|fboxname |fc            |
+--------+----------+--------+-----------+---------+--------------+
|fcompare|fcompares |fcopynew|fdir       |ferase   |fetch         |
+--------+----------+--------+-----------+---------+--------------+
|fexist  |fexists   |fgets   |fi         |flatten  |fliprgb       |
+--------+----------+--------+-----------+---------+--------------+
|fmakex  |foldpara  |foldtext|fpathcreate|fpathname|fputs         |
+--------+----------+--------+-----------+---------+--------------+
|fread   |freadblock|freadr  |freads     |frename  |freplace      |
+--------+----------+--------+-----------+---------+--------------+
|fsize   |fss       |fssrplc |fstamp     |fstring  |fstringreplace|
+--------+----------+--------+-----------+---------+--------------+
   

26.8.2 The J Application Library

There is an extensive collection of script-files forming the J Application Library (JAL). The JAL is documented here

26.9 User-Defined Startup Script

Suppose we have a collection of our own definitions which we wish to be loaded

automatically at the beginning of every J session.

To achieve this we can put our definitions into a script-file which must be named startup.ijs. The full pathname for this file is given by the expression

   jpath '~config/startup.ijs'  
c:/users/homer/j701-user/config/startup.ijs
   

Here is an example. We create the script-file with a few definitions. For this example we could define a few verbs useful for type-checking.

   (0 : 0)  (1 !: 2) < jpath '~config/startup.ijs'  
is_int    =: 4 = 3 !: 0
is_char   =: 2 = 3 !: 0
is_number =: 1 4 8 16 64 128  e.~  3!:0
is_scalar =: 0 = # @: $
is_list   =: 1 = # @: $
is_string =: is_char *. is_list
)

With this script-file in place, the next session should automatically load it. We verify this by looking at the list of scripts loaded at the beginning of the new session.

   ,. 11 {. 4 !: 3 ''
+---------------------------------------------+
|C:\users\homer\j701\bin\profile.ijs          |
+---------------------------------------------+
|C:\users\homer\j701\system\util\boot.ijs     |
+---------------------------------------------+
|C:\users\homer\j701\system\main\stdlib.ijs   |
+---------------------------------------------+
|C:\users\homer\j701\system\util\scripts.ijs  |
+---------------------------------------------+
|C:\users\homer\j701\system\main\regex.ijs    |
+---------------------------------------------+
|C:\users\homer\j701\system\main\task.ijs     |
+---------------------------------------------+
|C:\users\homer\j701\system\util\configure.ijs|
+---------------------------------------------+
|c:\users\homer\j701-user\config\recent.dat   |
+---------------------------------------------+
|c:\users\homer\j701\system\main\ctag.ijs     |
+---------------------------------------------+
|c:\users\homer\j701\system\util\jadetag.ijs  |
+---------------------------------------------+
|c:\users\homer\j701-user\config\startup.ijs  |
+---------------------------------------------+
   

We see that startup.ijs has been loaded and its definitions are available.

   is_string 'hello'
1
   

This is the end of Chapter 26.


NEXT
Table of Contents
Index


The examples in this chapter were executed using J version 701. This chapter last updated 29 Jul 2012
Copyright © Roger Stokes 2012. This material may be freely reproduced, provided that this copyright notice is also reproduced.


>> << Pri JfC LJ Phr Dic Voc !: Rel NuVoc wd Help Learning J