Groups keyboard shortcuts have been updated
Dismiss
See shortcuts

18!:4 slated for removal; use cocurrent/coclass

50 views
Skip to first unread message

Henry Rich

unread,
May 2, 2024, 9:38:04 AM5/2/24
to forum
18!:4 was intended to be used through the cover name cocurrent/coclass,
and was so documented.  When it is used without the cover name, its
definition is quirky enough to cause trouble.  If bare 18!:4 is hanging
around, all named executions must go through extra processing to account
for its side effects.  Depending on how early 18!:4 is used, it may be
'hanging around' for the entire J session.

This extra complexity gained nothing. Inspection of the Addons reveals
that only in a couple of places was 18!:4 used where cocurrent would not
serve as well.  Those places have been modified to use cocurrent.  All
other uses of 18!:4 in Addons have been replaced with cocurrent.

To avoid the wasted processing, we are removing 18!:4. 
cocurrent/coclass will be intrinsically defined to change the implied
locale.  Use those names, as you should have been doing all along.

Any code you have that executes 18!:4 must be changed.  Starting with
the next beta release, an attempt to execute 18!:4 will give a message. 
In a later beta the message will become an error.  You can use 9!:55 to
help locate the source of the message.

Henry Rich

Paul Jackson

unread,
May 15, 2024, 1:03:33 AM5/15/24
to fo...@jsoftware.com, henry...@gmail.com

If this is the wrong group to raise these questions please suggest the proper one.


Your statement “Inspection of the Addons reveals that only in a couple of places was 18!:4 used where cocurrent would not serve as well.” is clearly restricted to code released with J. I have a fair amount of published code which violates these assumptions and I'd like to understand what I'll need to do.


Help on Android, which is my primary development platform:


18!:4 y

Switch Current. Switch the current locale to y at the end of the currently executing named verb. Initially the current locale is base.


Help on Windows appears to be modified in accordance with the new rules:


18!:4 cannot be used directly, but only under the cover name cocurrent or coclass.


However, as I write this, the available beta update does not yet reject 18!:4 so I'd like to understand what the full rule will be.


  1. Is the definition of concurrent in the current beta sufficient to get correct behavior?

  2. Does that line of code have to be the only line in a named verb? Or could it be a parenthetical within a larger verb?

  3. Is there anything magic about creating the name cocurrent?

  4. Does the name concurrent have to be in the z locale in order to work properly?

  5. Is there a proposed alternative for people writing applications that don't include the z locale?



To unsubscribe from this group and stop receiving emails from it, send an email to forum+un...@jsoftware.com.

bill lam

unread,
May 15, 2024, 6:02:41 AM5/15/24
to fo...@jsoftware.com
I think you need not worry too much. There are only 2 things needed.
1. update base library and addons to the current version
2. In your applications, find and replace all naked 18!:4 with cocurrent

do not define cocurrent or coclass on your own. The base library or J interpreter will take care of it.

Pascal Jasmin

unread,
May 15, 2024, 9:06:30 AM5/15/24
to fo...@jsoftware.com
My recommendation is to define in base library  Cocurrent_z_ =: cocurrent

then if your code can rely on "enhanced use of 18!:4" in potentially overriden definitions of cocurrent, it can call Cocurrent (redefined by user) instead.  Where hopefully cocurrent calls work as 18!:4 did.

Henry Rich

unread,
May 15, 2024, 9:40:39 AM5/15/24
to Paul Jackson, fo...@jsoftware.com
JE is the same across platforms.  It appears that Android uses the original J Dictionary for Help.  That is out of date - use NuVoc.

2, 3.  Yes, the name cocurrent is magic.  That's because the function it performs is exceptional.  It is a rule that every return from a named execution restores the caller's implied locale - /except/ cocurrent/coclass, which change the implied locale on return.

1, 3, 4. The definition you see in the current beta is a stopgap to serve during the transition.  In the final version cocurrent_z_/coclass_z_ will be defined at startup and you will not be allowed to redefine or delete them.  That's why the beta7 version does that weird assignment inside ". .

5. If you have no z locale you must be bypassing stdlib at startup and running JE entirely on your own.  We speculated that such users are rare-to-nonexistent.  I will work with you privately if you are really doing this.

Please tell me if the following conversion guide suffices for you:

1. If you have lines of the form

name =: 18!:4

remove them and replace /name/ in your code with /cocurrent/.  The new /cocurrent/ will perform the boxxopen function.

2. If you have other uses of 18!:4 you need to see whether they require special treatment.  As implemented 18!:4 /did not/ do what the Dictionary definition you pointed to said it would do.  Instead, it changed the implied locale immediately and also carried that locale back into the caller of the executing named entity (not necessarily a verb).  The new beta9 version of cocurrent will conform to the Dictionary definition of 18!:4.  If you make use of the implemented behavior (that is, changing the locale both immediately and in the caller), you will have a little rewriting to do.  Almost all the uses of 18!:4 we saw were used simply to change the locale and could be updated by replacing the 18!:4 with cocurrent.

Henry Rich


Raul Miller

unread,
May 15, 2024, 9:49:53 AM5/15/24
to fo...@jsoftware.com, Paul Jackson
On Wed, May 15, 2024 at 6:40 AM Henry Rich <henry...@gmail.com> wrote:
> 2, 3. Yes, the name cocurrent is magic. That's because the function it performs is exceptional. It is a rule that every return from a named execution restores the caller's implied locale - /except/ cocurrent/coclass, which change the implied locale on return.

Just to be emphasize what's going on here: concurrent/coclass change
the implied locale on return from concurrent/coclass, where 18!:4
changed the implied locale on return from the caller.

In both J9.5 and j9.6beta7, after loading this script:
ex1=: {{
echo'1 ',;coname''
18!:4<'j'
echo'1 ',;coname''
}}

ex2=: {{
echo'2 ',;coname''
cocurrent'j'
echo'2 ',;coname''
}}

ex=: {{
echo;coname''
ex1''
echo;coname''
cocurrent'base'
echo '----------'
echo;coname''
ex2''
echo;coname''
cocurrent'base'
}}

I get:
ex''
base
1 base
1 j
j
----------
base
2 base
2 j
base

In other words, when eliminating 18!:4 from a script, one must also
call cocurrent or coclass from the routine which called the routine
which used 18!:4.

FYI,

--
Raul

Henry Rich

unread,
May 15, 2024, 10:00:29 AM5/15/24
to fo...@jsoftware.com
You are right.  Technically.  But in the addons we looked at, almost all
the uses of 18!:4 were in places where the side effect of changing the
locale in the caller was unintended.

I would change your advice to

when eliminating 18!:4 from a script, one must also check whether
calling functions need to repeat the cocurrent function.

Henry Rich

Henry Rich

unread,
May 15, 2024, 10:01:47 AM5/15/24
to fo...@jsoftware.com
That won't do, I fear.  cocurrent will set a new implied locale, but Cocurrent will restore the implied locale to whatever it was called in.

Henry Rich

Raul Miller

unread,
May 15, 2024, 10:10:24 AM5/15/24
to fo...@jsoftware.com
On Wed, May 15, 2024 at 7:00 AM Henry Rich <henry...@gmail.com> wrote:
> I would change your advice to
>
> when eliminating 18!:4 from a script, one must also check whether
> calling functions need to repeat the cocurrent function.

Yes, good point (though depending on what's going on and why 18!:4 was
being used frequently, other restructurings - perhaps eliminating
18!:4 from the original locations and/or expanding the called code
into the calling environment -- might be the right approach).

--
Raul

Henry Rich

unread,
May 15, 2024, 10:20:44 AM5/15/24
to fo...@jsoftware.com
18!:4 from my own code & code I've observed is used in 2 main ways:

1. To loop over a list of locales & apply the same verb in each locale. 
This looks like

for_loc. localelist do.
  18!:4 loc
  someverb someargs
end.

Here 18!:4 is a mistake, since it changes the implied locale in the
caller.  Using cocurrent fixes that.

2. To set the locale inline for subsequent verb definitions. Dissect had

setmonadlocale =: {{
<calculate a locale name>
18!:4 locname
}}

used as

setlocale 'bslash'
<now define functions in locale locname>

This had to be changed for the new version to

setmonadlocale =: {{
<calculate a locale name>
locname
}}

used as

cocurrent setlocale 'bslash'
<now define functions in locale locname>

I hope the analysis doesn't have to go any deeper than that.

Henry Rich

Paul Jackson

unread,
May 15, 2024, 12:57:07 PM5/15/24
to Henry Rich, fo...@jsoftware.com
Thanks for the detailed answers. This is just what I was looking for 

My New verb is the only thing I'll need to change. It is meant to behave more like I code in .Net. It creates a locale and if the right argument is not empty puts what I think of as a work space into it. Here is the current definition:

New=: {{
 NB. Create an object
 locale=. 18!:3 ''
 locale 18!:2~ 18!:2 <'base'  NB. Give it the name search path of base
 if. y-: '' do. locale
 elseif. locale {{ 18!:4 x [was=. 18!:5 ''
  err_pj_=: 'Run' runFile_pj_ 000 y
  0 0-: $err_pj_ [18!:4 was }}  y do. locale
 else. 25 Signal~ ,err_pj_ [18!:55 locale end.
}}

And here's how I redefined it to work both today and I assume when all your changes are complete.

New=: {{
 NB. Create an object
 locale=. 18!:3 ''
 locale 18!:2~ 18!:2 <'base'  NB. Give it the name search path of base
 if. y-: '' do. locale
 elseif. locale {{ cocurrent_z_ x
  err_pj_=: 'Run' runFile_pj_ 000 y
  0 0-: $err_pj_ }} y do. locale
 else. 25 Signal~ ,err_pj_ [18!:55 locale end.
}}

I appreciate that the J dictionary is woefully out of date in several areas, but it's also true that J on any Android after version 10 was released no longer supports browse or xedit. I've written my own standalone JavaScript app to replace the functionality but it's far too clunky to release with the rest of my tools.

Henry Rich

unread,
May 15, 2024, 1:21:38 PM5/15/24
to Paul Jackson, fo...@jsoftware.com
Yes.  If I'm following your code right, the side effect of 18!:4 (changing the locale in the caller) was just getting in the way, and using cocurrent saves you one call.

Henry Rich

Pascal Jasmin

unread,
May 15, 2024, 6:19:23 PM5/15/24
to fo...@jsoftware.com
It's been a while since I used this code, and not sure why it seemed essential at the time but, in general it is related to adding side effects for management of coclass(es)

assign_z_ =: 4 : '(x) =: y'


coclass 'OOP'

OOP_z_ =: <'OOP'

coclass =: 18!:4@boxxopen@:[ ((( 'C' , ]) assign boxopen)^:(0 = L.))



  coclass_OOP_ 'a'


 Ca_OOP_

┌─┐

│a│

└─┘


b__Ca__OOP =: 2  NB. allows 1 hierarchy of "singleton/module" access setting.  Allows mixed singletons and instances with same calling convention.


b_a_ 
2

The side effects also allows an easy list of locales created under OOP 

I've also found that the side effect of erasing previous "coclass" before creating it again can help restore the "virgin state" of loading a file and playing with the class in IDE.


Henry Rich

unread,
May 15, 2024, 6:37:41 PM5/15/24
to fo...@jsoftware.com
That's similar to what I had in dissect.  You will have to change it to

coclass =: [    ((( 'C' , ]) assign boxopen)^:(0 = L.))

and when you use it, use

coclass coclass_OOP_ 'a'

Henry Rich

Henry Rich

unread,
May 15, 2024, 10:28:25 PM5/15/24
to Paul Jackson, fo...@jsoftware.com
I think your rewrite is valid, but it's not /completely/ identical, in a way that shows how tricky 18!:4 is and, I hope, why we are justified in putting it to the sword.

Spot the difference:

Version with 18!:4


New=: {{
 NB. Create an object
 locale=. 18!:3 ''
 locale 18!:2~ 18!:2 <'base'  NB. Give it the name search path of base
 if. y-: '' do. locale
 elseif. locale {{ 18!:4 x [was=. 18!:5 ''
  err_pj_=: 'Run' runFile_pj_ 000 y
  0 0-: $err_pj_ [18!:4 was }}  y do. locale
 else. 25 Signal~ ,err_pj_ [18!:55 locale end.
}}

Version with cocurrent


New=: {{
 NB. Create an object
 locale=. 18!:3 ''
 locale 18!:2~ 18!:2 <'base'  NB. Give it the name search path of base
 if. y-: '' do. locale
 elseif. locale {{ cocurrent_z_ x
  err_pj_=: 'Run' runFile_pj_ 000 y
  0 0-: $err_pj_ }} y do. locale
 else. 25 Signal~ ,err_pj_ [18!:55 locale end.
}}

The difference?  Obviously, the first 18!:4 was replaced with cocurrent and the second 18!:4 was deleted.  How does that affect execution?

Before answering that: why was the second 18!:4 needed in the first version?  It seems to set the implied locale to the value it had when the New was called.  Why is that needed?  Answer: both 18!:4s are executed in an {{ }} definition, but it is not a /named/ definition.  The 18!:4 reaches back into the caller of the nearest /name/ which is New itself.  That is, the first 18!:4 will change the implied locale /in the caller of New/.  Did you see that?  The second 18!:4 is needed to reach back into the caller of New and restore its implied locale.

THE DIFFERENCE is that in the first version the last line:


25 Signal~ ,err_pj_ [18!:55 locale

executes in the original locale (which was reset by 18!:4 was), while in the second version it executes in locale x (set by cocurrent).

It looks like the locale doesn't matter there, so the difference is immaterial.

Henry Rich



On 5/15/2024 12:56 PM, Paul Jackson wrote:
Reply all
Reply to author
Forward
0 new messages