Dan provided the solution for this particular problem, but in general
you can pass around an object (numbered locale) or execute your
functions within a numbered locale. Respectively, these correspond to
the functions:

   NB. Pass a locale as an argument
   inc1 =: 4 : '($y) $ n__x =: >:n__x'
   f1 =: 3 : 0
l =. cocreate ''
n__l =: _1
(l&inc1 L:0 z)  [  coerase l
)
   f1 z
┌─────┬─────┬─┐
│0 0 0│1 1 1│2│
│     │1 1 1│2│
│     │     │2│
│     │     │2│
└─────┴─────┴─┘

   NB. Execute in a new locale
   inc_loc_ =: 3 : '($y) $ n =: >:n'
   f_loc_ =: 3 :'inc L:0 y  [  (n=:_1)'
   f2 =: 3 : 0
l =. cocreate ''
coinsert__l 'loc'
(f__l y)  [  coerase l
)
   f2 z
┌─────┬─────┬─┐
│0 0 0│1 1 1│2│
│     │1 1 1│2│
│     │     │2│
│     │     │2│
└─────┴─────┴─┘

   n
|value error: n

The first doesn't require you to create a new named locale to insert
into the path of your object and is thus somewhat lighter. The second is
cleaner in the sense that it compartmentalizes the stateful code into
functions in a particular named locale, and only exposes a single
function to the base locale.

Marshall

On Sun, Jun 01, 2014 at 11:25:10AM -0600, Don Guinn wrote:
> One problem that has bugged me is the inability for an explicit definition
> to modify a value accessible to a caller without having to create a global
> name. A tacit definition can reference the caller's local names but copulas
> do not work in a tacit definition. And names in an explicit definition are
> either local within the definition or global.
> 
> 
> It is not a serious problem, but there are a few situations where it cannot
> be avoided. Such as the verb argument to an adverb or conjunction.
> 
> 
> One problem I was dealing with was to identify where atoms were within a
> boxed array.
> 
> 
>    ]z=:'abc';(i.2 3);,.1 2 3 4
> 
> +---+-----+-+
> 
> |abc|0 1 2|1|
> 
> |   |3 4 5|2|
> 
> |   |     |3|
> 
> |   |     |4|
> 
> +---+-----+-+
> 
> 
> I wanted to create a corresponding boxed array containing
> 
> 
> +-----+-----+-+
> 
> |0 0 0|1 1 1|2|
> 
> |     |1 1 1|2|
> 
> |     |     |2|
> 
> |     |     |2|
> 
> +-----+-----+-+
> 
> 
> This gets the job done but n has to be global. It cannot be a local name.
> 
> 
>    inc=: 3 : '($y)$n=:>:n'
> 
>    n=:_1
> 
>    inc L:0 z
> 
> +-----+-----+-+
> 
> |0 0 0|1 1 1|2|
> 
> |     |1 1 1|2|
> 
> |     |     |2|
> 
> |     |     |2|
> 
> +-----+-----+-+
> 
> 
> I needed to find a primitive which has side effects. One to put in an
> explicit definition so each time the definition is executed the primitive
> returns a different result. One such is ? (or ?.) but the result is random
> and there is no guarantee that it won't return duplicate numbers. Another
> is 6!:9 '' (clock counter). It is always ascending but no guarantee that
> fast enough processors might return the same number in successive calls.
> 
> 
> A new foreign was added in J7 - 6!:4'' (parser calls) which does the job
> quite nicely.
> 
> 
>    (3 : '6!:4''''')"0 ]i.3 4
> 
> 6836 6837 6838 6839
> 
> 6840 6841 6842 6843
> 
> 6844 6845 6846 6847
> 
> 
> This gives the desired result. No global name required.
> 
> 
>    inc=. 4 : '($y)$n-~6!:4 '''''
> 
>    n=.2+6!:4 ''
> 
>    (n&inc) L:0 z
> 
> +-----+-----+-+
> 
> |0 0 0|1 1 1|2|
> 
> |     |1 1 1|2|
> 
> |     |     |2|
> 
> |     |     |2|
> 
> +-----+-----+-+
> 
> 
> I'm not sure what the purpose of 6!:4 is, but it is an interesting tool.
> ----------------------------------------------------------------------
> For information about J forums see http://www.jsoftware.com/forums.htm
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm

Reply via email to