Namespace Play
Vector 7:2, page 138
Transcribed from the printed issue; not yet reviewed. Read it in the PDF of the issue, page 138
I had some fun poking about the innards of packaged workspaces and namespaces, so I put together this short annotated APL2 session to show the sort of things I found out. It is not a tutorial session, but a very personal and possibly idiosyncratic view of Namespaces.
Creating a packaged workspace is rather boring, and it is much more interesting to look at one distributed with APL2. The obvious choice is PACKAGE workspace which packages up workspaces. The official way to get at the PACKAGE function is 3 11 ⎕NA 'PACKAGE', but if you look in the Names file which APL2 reads when presented with a 3 11 ⎕NA you can see that under VM the real left argument to ⎕NA should be:
The 1 being returned shows that we hit bull’s eye, and have got the correct fully qualified name. The ‘AP2VNRP2’ is the name of a VM simulated load library, and ‘AP2PPKG’ is the member name. Under TSO you would normally only need to give the member name ‘AP2PPKG’ as the APL start process would normally give automatic access to the various load libraries required.
Define a function to save typing out all that gobbledegook:
As we get going things can get confused as to which namespace a function runs in. Functions starting with A_ are defined in, and run in, the Active workspace. A_NA_P will be accessed from other namespaces, but the body of the function will always run in the Active workspace and will ⎕NA to a name in the PACKAGE namespace.
Now let’s see what functions have been defined in the PACKAGE namespace. You can ⎕NA to system functions as well as user functions, but you have to give a surrogate name otherwise it gets confused. Anyhow we want to show where the function runs with a P_ for the PACKAGE namespace:
The PACKAGE namespace is ‘open’, in that there is no restriction on the objects that may be accessed. It could have been packaged up with only the PACKAGE function available for Name Association, in which case the statement above would have returned a zero and none of the following would have been possible.
A list of functions in the PACKAGE namespace can be neatly displayed with:
The sneaky way to get inside an open namespace is to fix a function that blows up inside it:
The function P_STOP does not exist in our namespace, as the P_FX function used its right argument in the PACKAGE namespace, and fixed the function there. We will have to get at it before running it:
Now we are in the PACKAGE namespace, and can muck about at leisure:
Variables which have been ⎕NA’ed are even easier than functions, because you don’t have to worry about where they have been defined:
Lets get at the A_NA_P function in the PACKAGE namespace so we can post things back into the Active workspace. In a packaged namespace '' 11 ⎕NA allows one to get at objects in the Active workspace. As before, a little function saves typing and its name will make it clear where it runs:
Running A_NA_P causes an implicit switch back to the active workspace, and then the body of the function is executed. What one has to hold onto is that A_NA_P always runs in the Active Workspace and does a ⎕NA to the PACKAGE namespace, regardless of from where it is called. P_VAR and P_NA_A should now appear back in the Active workspace:
)RESET
)FNS
A_NA_P P_FX P_NA_A P_NL P_STOP PACKAGE
P_VAR
THIS VARIABLE WAS ASSIGNED IN THE PACKAGE NAMESPACE
We have now got the functions A_NA_P and P_NA_A accessible in both namespaces which enable us to post objects back and forth. Now let’s mess about with variables to show how one can change them in either namespace and get consistent results:
The Package namespace variable P_VAR has been reassigned. A new variable has been created in the Active workspace, and we have caused it to be available in the Package namespace by running the P_NA_A function, which flips into the Package namespace and does the ⎕NA back to the Active Workspace. A surrogate name A_VSUG was given just to be different.
Get into the Package namespace and see what has happened:
Surrogate names make it possible for packaged workspace functions to work safely on a list of variable names without having to use execute. Alterations can be made in place so that big arrays do not have to be passed to and fro. However, ⎕NA is quite expensive in CPU; doing ⎕NA on 1000 variables can get rather boring.
Reassignment can be carried out in the Package namespace, and low and behold, the changes pop up in the Active namespace:
A )SAVE at this point keeps all the changes we have made as a sort of hidden part of our workspace, but does not touch the original AP2PPKG member of the Load Library.
)SAVE PLAY
????????
)CLEAR
CLEAR WS
)LOAD PLAY
????????
)FNS
A_NA_P P_FX P_NA_A P_NL P_STOP PACKAGE
P_STOP
P_STOP[2]
)FNS
A_NA_P ATR CLOSE COIBM DAN . . . . . P_NA_A P_STOP
This feature could be useful for developing and debugging a packaged workspace. When development has finished )OUT can be used to write out all the required objects, and then the package can be re-created with the new code.
Two functions are supplied by IBM to help manage the packaged environment, called EXP and QNS, which we will get at in both namespaces:
The second statement shows that we can ⎕NA to a function indirectly, which is an unpleasantly convoluted way of going about things, but might be useful. The 0 11 means that we do not need to check whether the names are functions or variables. There are some decidedly arcane situations where 0 11 has to be used, but this is not one of them. QNS tells us how the namespace was entered:
The right argument is always 0. Could a future enhancement change this? Strictly speaking, QNS gives the left argument to ⎕NA used to access the function which caused an explicit entry to the namespace. If PACKAGE had been entered the official way with 3 11 ⎕NA 'PACKAGE', then QNS 0 would have returned 3 11. Also, the new Program Interface feature of APL2 allows packaged workspaces to be entered without calling an APL function, in which case QNS returns '' 11. Use QNS with care.
EXP executes a statement in the previous namespace, whatever that may be:
We could have done the same job with X←50 and A_NA_P 'X', if we had known that the previous namespace was in fact the Active workspace. It may be better to think of ways of keeping track of namespaces so that explicit ⎕NAs can be done instead of blindly using EXP everywhere. The IBM manual gives some examples of how this can be done.
Hopefully the session has given the flavour of Packaged workspaces and namespaces, which will enable you to get stuck in and develop useful applications.