Namespaces#

Let’s create the simplest APL type of object Dyalog APL has, the namespace. APLWiki has a good intro. A namespace is like a container for other APL items (functions, variables, and namespaces). It is very much like a JSON object.

One way to create a new empty namespace is using the system function ⎕NS. For now, we’ll just use a dummy right argument; . To assign into a namespace we use the dot-notation: namespace.name←value. Same goes when we want to query the value.

ba⎕NS 
a.var52
b.var42
a.var b.var
42 42

We created the namespace a. Then we used its value to set b, then we set var inside a and inside b to two different values, but when we queried the two values they had become the same (the latter). This is because APL objects are mutable. Another way to look at it is that the value isn’t really the namespace itself, but rather a reference to a single object we created with a single call to ⎕NS.

b a⎕NS¨  
a.var52
b.var42
a.var b.var
52 42

Here we called ⎕NS twice, once on each of the two s. And so b and a refer to two different objects. Also note that there is no assignment arrow between b and a, but don’t be fooled:

b a⎕NS 
a.var52
b.var42
a.var b.var
42 42

The last 42 42 result is of course (!) because of APL’s scalar extension (vectorisation/mapping/…). Refs are scalar values, and so the scalar was distributed to both names, just like b a←42 would have done.

You can also put functions inside a namespace:

ns⎕NS 
ns.fn{'hello' }
ns.fn 'world'
┌─────┬─────┐
│hello│world│
└─────┴─────┘

All APL built-ins exist (separately!) in every namespace.

a b⎕NS¨⍬⍬
a.⎕IO0
b.⎕IO1
a. 5
b. 5
0 1 2 3 4
1 2 3 4 5

Here is another way to create a namespace:

ns⎕JSON '{"a":52, "b":42}'
ns.a
ns.b
52
42

We can, of course, also use ⎕JSON to visualise (simple) APL objects:

a⎕NS   a.(x y z)1 2 'Brian'
⎕JSON a
{"x":1,"y":2,"z":"Brian"}

Namespaces are great ways to organise you code and data. But sometimes you need a better overview of the namespace content, or you want to put tradfns there (in an easy manner) or even put some comments in. To help you manage larger namespaces and especially code in namespaces, you can have a scripted namespace. The script is a simple text document which gets “fixed” into a namespace, much like the JSON text got converted to an APL object. This uses a syntax similar to the tradfn control structures, namely :Namespace :EndNamespace:

⎕FIX ':Namespace a' 'var←42' ':EndNamespace'
a.var
42

Of course, the ⎕FIX usage is even more cumbersome (except possibly when you need to define namespaces under program control), but in an interactive APL session, you can enter )ed ⍟nyns to open the editor with a new namespace script. In a Jupyter notebook cell you can create a scripted namespace using ]dinput:

]dinput
:Namespace b
var43
:EndNamespace
b.var
43

Here’s a scripted namespace with a few things in it; a variable, a dfn, and a tradfn:

]dinput
:Namespace ns
    var42
    dfn{
        'the argument:' 
    }
     rtradfn x
      r?x
    
:EndNamespace
var77
⎕NL -⍳9
ns.⎕NL -⍳9
var ns.var
┌─┬─┬──┬───┐
│a│b│ns│var│
└─┴─┴──┴───┘
┌───┬──────┬───┐
│dfn│tradfn│var│
└───┴──────┴───┘
77 42

We first ask for the Name List in # (the root namespace) and again inside ns and then we retrieve the value of #.var and ns.var.

By the way, from inside a namespace, you can access the parent namespace with ## and its parent with ##.## etc. # doesn’t have a parent though, so #.## is the same as #. This of course implies that you can nest namespaces. And indeed, you can even do so inside a script:

]dinput
:Namespace ns
    variable42
    dfn{
        'the arguments:' 
    }
    :Namespace inner
         rtradfn x
          r?x
        
    :EndNamespace
:EndNamespace
ns.inner.tradfn 3
3