User commands
Contents
User commands#
We’ve used the user command ]RunTime
to compare the speed of two otherwise equivalent expressions elsewhere.
You may also have encountered system commands like )save, )clear and )off. The system commands are an integral part of the interpreter (and have been so for a very long time). That is, for Dyalog APL, they are written in C.
System commands are not APL functions, but rather a way to directly interact with the system. Thus, they do not follow APL syntax. Instead, they act more like commands on a command line. That’s why they’re called commands.
Sometimes, this non-syntactic way is really useful tor day-to-day stuff, and you’d want that for your APL code as well. This is where user commands come in. They have exactly the same syntax model as system commands, they just begin with a ]
instead of a )
.
The only thing built into the interpreter is that whenever it sees a line in the session beginning with ] it takes the rest of that line and calls ⎕SE.UCMD
with the line as a character vector argument. Dyalog APL comes pre-installed with a “user command processor”, i.e. a function ⎕SE.UCMD
which takes care of the rest. The default user command system is tightly integrated with SALT
, but you could write your own drop-in, should you with to do so. Dyalog APL also comes loaded with more than 100 pre-defined user commands, some are simple and complex. All are written in APL, and you can change them as you see fit.
] -?
─────────────────────────────────────────────────────────────────────────────── 140 commands: ARRAY Compare Edit CALC Factors FromHex PivotTable ToHex CCM Cluster Contacts Contracts Defaults Export Find List Lites Load Nodecounts Nodespecs Plan Plans Provisioned Region Regions Regload Regprov Splunk User DEVOPS DBuild DTest EXPERIMENTAL Get FILE CD Collect Compare Edit Find Open Replace Split ToLarge ToQuadTS Touch FN Align Calls Compare Defs DInput Latest ReorderLocals LINK Add Break Create Export Expunge GetFileName GetItemName Import Refresh Resync Status MYCMDS Quote NS ScriptUpdate Summary Xref OUTPUT Box Boxing Disp Display Find Format HTML Layout Plot Repr Rows View PERFORMANCE Profile RunTime SpaceNeeded SALT Boot Clean Compare List Load Refresh RemoveVersions Save Set Settings Snap TATIN CheckForLaterVersion DeletePackage Documentation GetDeletePolicy Init InstallPackage ListPackages ListRegistries ListTags ListVersions LoadDependencies LoadPackage LoadTatin Pack PackageConfig PackageDependencies Ping PublishPackage ReinstallDependencies UninstallPackage UserSettings Version TOOLS ADoc APLCart Calendar Config Demo Help Version TRANSFER In Out UCMD UDebug ULoad UMonitor UNew UReset USetup UVersion WS Check Compare Document FindRefs FnsLike Locate Map Names NamesLike Nms ObsLike Peek SizeOf VarsLike ] ⍝ for general user command help ] -?? ⍝ for brief info on each command ]grp -? ⍝ for info on the "GRP" group ]grp.cmd -? ⍝ for info on the "Cmd" command of the "GRP" group
At this point, we should mention that all these user commands have a whole host of options which you can specify with various arguments or modifiers. It would be too much to go into details about it all, but you can always get documentation about any user command with ]cmdname -?
, for example:
]calls -?
─────────────────────────────────────────────────────────────────────────────── ]FN.Calls Produce the calling tree of a function in a class/namespace/scriptfile ]Calls <function> [<namespace>] ]Calls -?? ⍝ for more information and examples
Now that we are talking about the special syntax of user commands, the command processor has another few tricks up its sleeve.
If for some reason you want to capture the result of a user command, you can do so with ]varname←cmdname
. If you want to silence a user command, you can do that with ]←cmdname
.
Remember that we said everything after the ]
is passed as argument to ⎕SE.UCMD
? That means that you can even call user command under program control: ⎕SE.UCMD 'cmdname'
. Anything else you’d write on the line just goes inside that character vector.
Let’s have a look at some of the available user commands.
]CD#
There are simple things like ]cd
:
]cd
/Users/stefan/work/notebooks/cultivations/contents
]cd
, in its niladic form, shows the interpreter’s current working directory. You can set the current working directory, too, by
]cd /Users/stefan/work/notebooks
]cd /Users/stefan/work/notebooks/cultivations/contents
/Users/stefan/work/notebooks/cultivations/contents
/Users/stefan/work/notebooks
Note that when you set the current working directory this way, ]cd
will echo back the directory it changed from, not the one it changed to.
]DInput#
If you’ve ever wanted to enter or paste a multi-line statement into the session, you can use ]dinput
. Note, however, that this is likely to be superseded in a future version by the currently experimental multi-line input mode.
What is a multi-line statement? Remember that you don’t have to assign dfns before you use them; you can insert them inline. And dfns may have multiple lines. Effectively, you then have a single multi-line statement.
Now, as soon as you press Enter in the session, you code will be executed, and if it has any un-closed braces, e.g. 2+{a←⍳10
it will fail. However, if you enter ]dinput
you will get a new prompt indicated by a dot ·
and then you can begin entering (or pasting) multi-line statements. ]dinput
will keep track of your brace-nesting level and indicate it with more dots.
You can also just type ]dinput f←
and then paste a multi-line dfn there, beginning on that line. That’ll define it in the workspace.
Another important use for ]dinput
is when you write multi-line functions in a Jupyter notebook cell, as you will have seen already in many places in this book.
]Calls#
There are also various code analysis tools, like ]calls
. It will produce a calling tree:
]calls getEnvir ⎕se.SALTUtils
Level 1: →getEnvir F:rlb F:splitOn F:splitOn1st F:GetUnicodeFile F:SALTsetFile F:UnixFileExists Level 2: getEnvir→UnixFileExists Level 2: getEnvir→SALTsetFile Level 2: getEnvir→GetUnicodeFile ⍝ Read a Unicode (UTF-8 or even UCS-2) file ⍝ This version allows excluding specific 1-byte characters before the translation ⍝ This prevents TRANSLATION errors in classic interpreters F:condEncl F:numReplace F:Special F:Uxxxx Level 3: GetUnicodeFile→condEncl Level 3: GetUnicodeFile→Special Level 3: GetUnicodeFile→Uxxxx Level 3: GetUnicodeFile→numReplace ⍝ fromto is the list of lists of numbers to replace F:num Level 4: numReplace→num F:isChar Level 5: num→isChar Level 2: getEnvir→splitOn1st ⍝ Split on 1st occurrence of any chars in str Level 2: getEnvir→splitOn Level 2: getEnvir→rlb
This says that the getEnvir
function in ⎕SE.SALTUtils
calls these six functions, which in turn call the other listed functions, each at its level. This is really useful if you’re trying to extract some utility function and need to know its dependencies.
]Settings#
A workspace stores information about each function; who was it last modified by, and when. This information can also be saved in script files with ]save
if you turn on “atinfo tracking”. You can turn turn that on with ]settings track atinfo
. Then you can list which functions were recently modified: ]Latest 20180501 -by=Fred
track
isn’t the only setting:
]settings
compare APL cmddir /Users/stefan/.local/lib/python3.10/site-packages/dyalog_kernel/:/Users/stefan/MyUCMDs:/Applications/Dyalog-18.2.app/Contents/Resources/Dyalog/SALT/spice debug 0 editor notepad edprompt 1 fndels 0 mapprimitives 1 newcmd auto track varfmt xml workdir .:/Applications/Dyalog-18.2.app/Contents/Resources/Dyalog/Library/Core:/Applications/Dyalog-18.2.app/Contents/Resources/Dyalog/Library/Conga:/Applications/Dyalog-18.2.app/Contents/Resources/Dyalog/SALT
These are basically like OS environment variables, but used just by SALT
. For example, edprompt
determines if the editor should ask you before writing changes to scripted items back to their source file. varfmt
determines how ]save
should save variables; as XML or as APL statements that produce the value. cmddir
tells SALT
where to look for user commands.
As you can gather, you can just drop your own or downloaded user commands into the mentioned /MyUCMDs
dir and you’re in business. Watch the webinar about how to write your own user commands!
]ReorderLocals#
If you’ve ever written anything moderately complex as a tradfn, you may have been annoyed that, as you edit along, your list of local variables on the header line is not neatly ordered. ]reorderlocals
allows you to sort the header row of all (or some of) the functions currently in the workspace: ]reorderlocals MyFn
or ]reorderlocals F*
or just ]reorderlocals
.
]CopyReg#
If you’re on Windows, you have a few goodies especially for you. When the time comes to upgrade your Dyalog between major versions, but you’ve spent a whole year customising the current version to your liking. There is a user command that allows you to easily migrate your settings between versions:
]CopyReg 17u64 -to=18u64
does the job (you may need admin privileges, though).
The command processor#
At this point, we should mention that all these user commands have a whole host of options which you can specify with various arguments or modifiers. It would be too much to go into details about it all, but you can always get documentation about any user command with ]cmdname -?
:
]Summary#
There are also commands that let you get an overview of things:
]summary ⎕se.Parser
Name Scope Size Syntax Parse P 17128 r1f Propagate 2744 r2f Quotes 2256 r1f Switch 2616 r2f deQuote 1512 r1f fixCase 120 r2f if 48 r2f init PC 14040 n1f splitParms 3400 r1f sqz 10872 r2f upperCase 10960 r2f xCut 10648 r2f
This analyses the ⎕SE.Parser
class and tells you a little bit about each function. P
means public, C
constructor, and the syntax is whether they have a result, number of arguments, and type (function/monadic operator/dyadic operator).
]XRef#
]xref
will produce a cross reference of all items in a namespace, which ones call or reference which, how they do so (global/local) and what type they all are.
]Box#
You may already know about ]box
. It is, for example, responsible for that nice boxed output you can see on TryAPL. You can turn that on and off, and decide exactly how you want it to display things with the user command. For now, let’s just see what the current settings are in this notebook:
]box ?
]Box ON -style=min -view=min -trains=tree -fns=on
]Rows#
There is a lesser known, but very useful, companion to ]box
called ]rows
. Probably, by now, you’ve entered a statement that caused way too much output, so your session would just scroll and scroll. Right? Well, the ]rows
user command can protect you against that but limiting output to the current height and width of your window.
]rows ?
]Rows OFF -style=long -fold=off -fns=off -dots=·
So if you do ]rows on -fold=3
it will cut any output four lines before the bottom of your screen, insert a row of dots (or whichever character you choose, e.g. ]rows on -fold=3 -dots=~
) and then display the last three lines of the output. It will then also (by default) not wrap lines that are too long, but rather will cause them to continue beyond the right edge of the screen (scroll horizontally to see it). Again, see ]box -?
and ]rows -?
for the full details.
]Disp, ]Display#
If you prefer boxing off during normal work, but want to display some results boxed here and there, you can use ]disp
and ]display
for that. ]disp
is much like ]box -style=mid
and ]display
is like ]box -style=max
.
As you saw above, the notebook uses -style=min
, but that doesn’t always give you enough information:
2 3⍴'' (⍳3) (0 0⍴0) 'a'
┌─┬─────┬─────┐ │ │1 2 3│ │ ├─┼─────┼─────┤ │a│ │1 2 3│ └─┴─────┴─────┘
OK, we’ve go three empty (or are they filled with spaces?) elements. But what are they really?
]display 2 3⍴'' (⍳3) (0 0⍴0) 'a'
┌→────────────────────┐ ↓ ┌⊖┐ ┌→────┐ ┌⊖┐ │ │ │ │ │1 2 3│ ⌽0│ │ │ └─┘ └~────┘ └~┘ │ │ ┌⊖┐ ┌→────┐ │ │ a │ │ │1 2 3│ │ │ - └─┘ └~────┘ │ └∊────────────────────┘
Now we can see what exactly each thing is; we’ve got two empty character vectors and one 0-by-0 numeric matrix. We can also see that the a
is a scalar, and the 1 2 3
s are vectors (not e.g. one-row matrices).
]ADoc#
If you comment your code using markdown, you can use ]adoc
to automatically generate some documentation of it. ]adoc MyClass
will open your browser with a nicely formatted html document that has comments and syntax information gleaned from your code.
]Calendar#
For a quick calendar, do:
]Calendar
July 2022 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
You can also specify a year or a month and a year, for example:
]Calendar January 1969
January 1969 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
]Chart (Windows only)#
If you are on Windows, you’ll have a handful more user commands than if not. Perhaps the coolest of them is the Chart Wizard. It has a button in the IDE:
But it is also available as a user command. Try e.g. ]chart (⍳50)×↓|1○(500÷⍨⍳50)∘.×⍳50
. If you’re not on Windows, you can still generate charts using SharpPlot (for which ]chart
is just a GUI). Here’s some example code for that, and the chapter on plotting in this book.
]Version#
If you ever run into trouble with your APL system, you may want to know the version numbers of various parts and dependencies of your APL system:
]version -extended
* Assuming "TOOLS.Version"; to see a list of all valid user commands that start with "version", type ]version* -? Dyalog 18.2.45505 64-bit Unicode, BuildID 50b14a3f /Applications/Dyalog-18.2.app/Contents/Resources/Dyalog/lib/htmlrenderer.dylib: 2022-04-07 00:35:16 OS Darwin 21.5.0 Darwin Kernel Version 21.5.0: Tue Apr 26 21:08:37 PDT 2022; root:xnu-8020.121.3~4/RELEASE_ARM64_T6000 x86_64 CPUs 8 Link 3.0.19 SALT 2.9 UCMD 2.51 .NET (unavailable) WS 18.2 Conga Version: 3.4.1612 loaded from: /Applications/Dyalog-18.2.app/Contents/Resources/Dyalog/lib/conga34_64.dylib Copyright 2002-2022 Dyalog Ltd. GnuTLS 3.6.15 Copyright (c) 2000-2021 Free Software Foundation, Inc. Copyright 2002-2022 Dyalog Ltd. SQAPL (unavailable)
]UVersion#
If you’re having trouble with a user command, you can get the version number of it with:
]uversion calendar
framework: 2.51 command: ]TOOLS.Calendar source: /Applications/Dyalog-18.2.app/Contents/Resources/Dyalog/SALT/spice/jsutils.dyalog version: 1.18 revision: 1574 commit: 2019 01 29 Adam: Help
]Compare#
There is actually a whole family user commands, all called Compare
. They are in the groups SALT
, WS
, ARRAY
, FN
, and FILE
. You can use them to compare two similar items, just may have done file diffs, but here you can do them on various things related to APL. For example, ]WS.Compare path1/ws1 path2/ws2
compares two workspaces, and ]NS.Compare #.ns1 #.ns2
compares two namespaces. Of course, if your items are stored in script files, you could use your favourite diff tool, but it probably doesn’t have any understanding of the APL code involved.
]Document#
If you want a “hardcopy” of your workspace or part of it, you can use ]document
to list all items, describe what they are, and show how they look if typed into the session.
]FindRefs#
If you work with a lot of objects, especially if they point to each other, you may find ]findrefs
useful. It will follow all pointers (refs) and report everything. For example,
A ← ⎕NS '' ⋄ B←C←D←A
V ← 0 C 2 99
]findrefs
#: followed 6 pointers to reach a total of 2 "refs" Name # #.B+4 more
]Names#
]Names
lists names in workspaces in various ways, with sophisticated means for filtering. For example, to show all tradfns (nameclass 3.1) with a name containing a lowercase l
, we can use a shell-style glob expression:
⎕CY 'salt'
]names 3.1 -filter=*l*
3.1: GetUnicodeFile PutUTF8File SALTsetFile disableSALT enableSALT regClose regGetHandle
The -filter=
option can also take full regexes,
]names 3.1 -filter=/.*\d.*/ ⍝ Tradfn names containing a digit
3.1: PutUTF8File
Note that the regex pattern is implicitly anchored to the beginning and end, so your pattern must match the whole name.
]Map#
A really cool user command is ]map
which draws a tree view of your workspace or (if given an argument) a specific namespace:
]map ⎕SE.Dyalog
⎕SE.Dyalog · ∇ Serial · Array · · ~ DEBUG sysVars · · ∇ Deserialise DeserialiseQA L QA RoundtripQA Serialise SerialiseQA ∆NS ∆NSinverse · · ∘ Ed Inline Is · · serialise · · · ~ cc cr cs di ec nl oc or os qu sp · · · ∇ Any0 Basic Char Clean Empty Esc HiRank Join Lead0 Mat Nested Ns Null Num Ptr Repr Scal Ser Simple String Table Tacit Unempty Vec Vec1 · · · ∘ _Paren_ _Sub_ · Callbacks · · ~ loaded · · ∇ BootSALT FontChange LoadFonts NJoin SECreate SetBoxButton WSLoaded startup · Hooks · · ∇ Deregister Handle Init Norm Num Register Registered · Out · · ~ DEBUG OUTSpace allSettings cmds · · ∇ Dft Filter Init Rows SD SetCallback flipBox pfnops timestamp · · ∘ Box · · B · · · ~ fns state style trains view · · F · · · ~ includequadoutput state stop timestamp · · L · · · ~ pfkey state · · R · · · ~ dots fns fold state style · SALT · · ~ List · SEEd → ⎕SE.[SessionEditor] · Utils · · ~ APLcartTableCache APLcartTableTime lc uc · · ∇ APLcart APLcartTable CD CDshy Config ExpandConfig Version View condRavel cut disp display dmb drvSrc dtb expr externs formatPar formatText fromXML fromto layoutPar layoutText lcase nkds psmum relativeTies repObj repObjQA reshapeText setupKeys showCol showRow toMatrix toVector toXML trimEnds txtreplace ucase where ∆FMT1 · · ∘ currying nabs · · SALT_Data → ⎕SE.[Namespace] · · qa · · · ∇ ExpandConfig
The tree structure itself are the nested namespaces, while the lists of names are ordered by type; ~
are variables, ∇
are functions, ∘
are operators. It also displays ref-names and where they point.
]Peek#
But perhaps the most powerful user command of them all is ]peek
. It allows you to “peek” into a different workspace, execute an expression there, then come back with the result, all without polluting or modifying neither the current workspace, nor the workspace that was peeked into:
]peek dfns queens 5
┌─────────┬─────────┐ │⍟ · · · ·│· ⍟ · · ·│ │· · ⍟ · ·│· · · · ⍟│ │· · · · ⍟│· · ⍟ · ·│ │· ⍟ · · ·│⍟ · · · ·│ │· · · ⍟ ·│· · · ⍟ ·│ └─────────┴─────────┘
How to place five queens on a 5-by-5 chess board without them being able to capture each other, all without even loading any utilities! How about that? :-)
There are, of course, many, many more user commands, and new versions of Dyalog usually adds more.
]APLCart#
Version 18.2 of Dyalog added the ]aplcart
user command. APLCart is searchable collection of short APL phrases. It is a goldmine of answers to APL-related questions of the type “How do I do X in APL?” for a surprisingly wide range of X. The ]aplcart
command makes this resource available directly in the session,
]aplcart Append scalar to each column of matrix
X, Y, Z: any type array M, N: numeric array I, J: integer array A, B: Boolean array C, D: character array f, g, h: function ax: bracket axis s: scalar v: vector m: matrix ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── Xm⍪Ys ⍝ Append scalar to each column of matrix ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── Showing 1 of 1 matches
]aplcart
has a number of options and capabilities. You can, for example, filter results by regular expression:
]aplcart /highest|lowest/
X, Y, Z: any type array M, N: numeric array I, J: integer array A, B: Boolean array C, D: character array f, g, h: function ax: bracket axis s: scalar v: vector m: matrix ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── M∨N ⍝ Greatest Common Divisor of M and N M∧N ⍝ Lowest Common Multiple of M and N ⌈/N ⍝ Maximum of N ⌊/N ⍝ Minimum of N ⍳⍨Nv ⍝ Assign ranking based on non-descending scores Nv (ties all get highest ranking of used slots) ⍸⍨Nv ⍝ Assign ranking based on non-descending scores Nv (ties all get lowest ranking of used slots) Is(⊃>⍥|⌽,)Js ⍝ Choose the number closer to zero (the left one if tied) Is(⌈(⊃>⍥|⌽,)⌊)Js ⍝ Choose the number closer to zero (the positive one if tied) Ms{⍵×⍺÷⍵[⊃⍒|⍵]}Nv ⍝ Scale Nv so the maximum element is Ms {s←0 ⋄ ⌈/{s⊢←0⌈s+⍵}¨⍵}Nv ⍝ Largest sum of any contiguous subvector ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── Showing 10 of 12 matches (-list=<n> to show up to <n>; -list to show all)
or ask it to generate the URL to the corresponding search query on the website itself:
]aplcart /highest|lowest/ -url
https://aplcart.info?q=/highest|lowest/
A -b
opens your default web browser on the corresponding results page instead of displaying it in the session.
]Get#
18.2 also added the ]Get
command. There is a lot to this (it comes with comprehensive documentation; see ]get -??
), and we’ll only skim the surface here. ]Get
provides a unified interface for quickly getting data (and code) into Dyalog from a multitude of different sources, including local files, by URL, or from git repositories. Note that this is intended as a development aid, and not something that should be relied upon during runtime or production.
From ]Get -??
:
]Get
is a development tool intended as a one-stop utility for quickly getting bringing resources into the workspace while programming. Do not use at run time, as exact results may vary. Instead, use precisely documented features like⎕JSON
,⎕CSV
,⎕XML
, and⎕FIX
in combination with loading tools like⎕NGET
,HttpCommand
,⎕SE.Link.Import
, etc.
]Get
supports importing directories and the following file extensions (files with any other extensions are imported as character vectors): apla, aplc, aplf, apli, apln, aplo, charlist, charmat, charstring, charvec, class, csv, dcf, dcfg, dws, dyalog, function, interface, js, json, json5, operator, script, tsv, xml, zip
Here’s an example of fetching–and decoding–a remote XML-file:
]Get raw.githubusercontent.com/Dyalog/MiServer/master/Config/Logger.xml
#.Logger
]disp #.Logger
┌─┬────────────┬────────────────┬───┬─┐ │0│Logger │ │ │3│ ├─┼────────────┼────────────────┼───┼─┤ │1│active │0 │ │5│ ├─┼────────────┼────────────────┼───┼─┤ │1│anonymousIPs│1 │ │5│ ├─┼────────────┼────────────────┼───┼─┤ │1│directory │%SiteRoot%/Logs/│ │5│ ├─┼────────────┼────────────────┼───┼─┤ │1│interval │10 │ │5│ ├─┼────────────┼────────────────┼───┼─┤ │1│prefix │ │ │1│ └─┴────────────┴────────────────┴───┴─┘
]Repr#
Also making its debut in 18.2 was ]repr
. It takes an APL value and returns (by default) an expression that produces this value.
]repr #.Logger
]repr 0 1 1 1 1 0 0 1 0 1 1 0 0 0 0 0 0 0 0 1 1
(6 5⍴0 'Logger' '' (0 2⍴⊂'') 3 1 'active' (,'0') (0 2⍴⊂'') 5 1 'anonymousIPs' (,'1') (0 2⍴⊂'') 5 1 'directory' '%SiteRoot%/Logs/' (0 2⍴⊂'') 5 1 'interval' '10' (0 2⍴⊂'') 5 1 'prefix' '' (0 2⍴⊂'') 1)
(0,(4/1),0 0 1 0 1 1,(8/0),1 1)
That’s useful enough, but it has a few other handy tricks up its sleeve, too. Perhaps you want to convert a specific APL value to csv?
]repr 'ABC'⍪2 3⍴⍳6 -f=csv
"A","B","C" 1,2,3 4,5,6
or maybe you need help with showing the correct parenthesing of a train?
]repr +⌿÷1⌈≢
(+⌿)÷(1⌈≢)