# Stack and workspace info#

Let’s continue with other things which deal with functions and other items under program control.

## Latent expression ⎕LX#

If you want to have an application start without having the user enter a command (for example, a function name) to boot it, you can assign an expression to ⎕LX (Latent eXpression) and then save your workspace with ⎕SAVE. When the workspace is loaded (including from the command line) APL will do ⍎⎕LX. This is what happens when you load the various workspaces supplied with APL.

)load dfns
≢⎕LX
⎕LX

/Applications/Dyalog-18.2.app/Contents/Resources/Dyalog/ws/dfns.dws saved Thu Apr  7 00:21:30 2022

An assortment of D Functions and Operators.

tree #                ⍝ Workspace map.
↑¯10↑↓attrib ⎕nl 3 4  ⍝ What's new?
⍕notes find 'Word'    ⍝ Apropos "Word".
⎕ed'notes.contents'   ⍝ Workspace overview.


236

'
An assortment of D Functions and Operators.

tree #                ⍝ Workspace map.
↑¯10↑↓attrib ⎕nl 3 4  ⍝ What''s new?
⍕notes find ''Word''    ⍝ Apropos "Word".
⎕ed''notes.contents''   ⍝ Workspace overview.
'


## Name classification ⎕NC#

Since APL does not enforce a naming scheme (although you might want to adopt one), you may wonder what a certain name is. ⎕NC (Name Classification) to the rescue! Each type of item has a number. 2 is variable, 3 is function, 4 is operator, 9 is object.

⎕CY'dfns'   ⍝ Copy the dfns workspace silently
var←42
⎕NC ↑'blah' '123' 'var' 'to' 'notes'

0 ¯1 2 3 9


0 is undefined (but valid name). ¯1 is invalid name. 1 is really rare these days. It is a line label, and can only occur while a tradfn/tradop is running or suspended:

∇tradfn
label:
⎕NC↑'label' 'label2' 'label3'
label2:
∇

tradfn

1 1 0


Sometimes you want even more info. If the argument to ⎕NC is nested, then the values get a decimal which mean: .1=traditional, .2=field/direct, .3=property/tacit, .4=class, .5=interface, .6=external class, .7=external interface.

⎕CY'dfns'   ⍝ Copy the dfns workspace silently
var←42
⎕NC 'blah' '123' 'var' 'to' 'notes'

0 ¯1 2.1 3.2 9.1


## Name list ⎕NL#

Using those same codes, you can also use ⎕NL (Name List) to enquire which items of those name classifications are visible. For example, here are all of the dfns workspace’s operators:

⎕CY'dfns'
⎕NL 4

Cut
Depth
H
UndoRedo
_fk
acc
alt
and
ascan
ascana
at
avl
bags
big
bsearch
bt
case
cf
cond
cxdraw
dft
do
each
else
file
fk
fk_
fnarray
foldl
for
invr
kcell
limit
lof
logic
ltrav
mdf
memo
nats
of
or
perv
pow
pred
profile
rats
ratsum
ravt
redblack
repl
roman
rows
sam
saw
sbst
splay
tc
ticks
time
traj
trav
until
vof
vwise
while


You can also specify decimals to get just those specific things. You can get just things beginning with specific letters, too, by giving a list of letters as left argument:

⎕CY'dfns'
'b' ⎕NL 4.2

bags
big
bsearch
bt


If you’d rather have a VTV (vector of text vectors, i.e. a list of strings), then use negative numbers. APLers often use this shortcut to list everything:

⎕CY'dfns'
10↑⎕NL-⍳9    ⍝ Truncated for display purposes; contains 300+ items...

┌──────────┬───────────┬───────┬─────────┬────────┬─────┬─────────┬───┬───┬────┐
│APLVersion│ActivateApp│Caption│ChildList│Cholesky│Coord│CursorObj│Cut│DDE│Data│
└──────────┴───────────┴───────┴─────────┴────────┴─────┴─────────┴───┴───┴────┘


## Expunge ⎕EX#

If you find that the name you want to use is unavailable, you may want to EXpunge its current value with ⎕EX:

⎕NC'var' ⊣ ⎕EX 'var' ⊣ var←42

0


There we created, removed, and enquired about the name var.

## Shadow ⎕SHADOW#

If you only want to use an already used name temporarily, then you can use ⎕SHADOW instead of ⎕EX. The name will then be freed up for your use until the current function terminates. Note that shadowing happens automatically in dfns and dops when you just do regular assignments. In a dfn, var←42 really means ⎕SHADOW 'var' ⋄ var←42.

Be careful using ⎕SHADOW though. It is much better to localise your variables in the function header by putting ;varName at the end of the header.

## State indicator ⎕SI#

Let’s say you’ve built a bunch of functions that call each other, and then you run it, and it stops due to some bug. Now you need some situational awareness. You already know that ⎕NL will let you check which names are defined, and ⎕NC what type of things they are. ⎕SI (State Indicator) will give you a list of function names on the stack:

foo←{goo ⍵}
goo←{moo ⍵}
moo←{⎕SI}
foo⍬

┌───┬───┬───┐
│moo│goo│foo│
└───┴───┴───┘


## Line count ⎕LC#

⎕LC (Line Count) will give you a list of corresponding line numbers where each function in ⎕SI is holding:

]dinput
foo←{
goo ⍵

}

]dinput
goo←{

moo ⍵
}

]dinput
moo←{

⎕LC}

foo ⍬

2 3 1


## Size ⎕SIZE#

If you get a WS FULL error, you may want to check how much memory is being used to represent a variable. Use ⎕SIZE:

nums←⍳100 100
⎕SIZE'nums'

480040


## Workspace available ⎕WA#

You might also need to know how much [workspace available] (⎕WA) you have:

nums←⍳100 100
⎕SIZE'nums'
⎕WA

480040

8564555456


## Screen dimensions ⎕SD#

⎕SD is the Screen Dimensions, which for a Jupyter kernel is something fairly arbitrary:

⎕SD

24 80