Behaviour, session
Contents
Behaviour, session#
There are several system functions that control behavioural aspects of the interpreter and the session itself.
Comparison tolerance ⎕CT
#
To deal with inexactness in floating point representation, we have ⎕CT
, which is Comparison Tolerance. Some APL primitives have implicit arguments, i.e. arguments which are given as values to (semi) global variables instead of on the right or left.
⎕CT
is a tiny value:
⎕CT
1E¯14
Two floating point numbers X
and Y
are considered to be equal if (|X-Y)≤⎕CT×(|X)⌈|Y
:
1=1+1e¯15
1
You can set ⎕CT
within reasonable limits (you can’t make two unequal ints the same), so you can just set it to something else if you need to modify (or even disable) this behaviour:
⎕CT←1E¯10 ⍝ More tolerant
1=1+1e¯11
⎕CT←0 ⍝ Disable comparison tolerance
1=1+1e¯15
⎕CT←1E¯14 ⍝ Reset to default
1
0
If you use 128-bit decimal floats (we’ll get back to that), you can instead use ⎕DCT
, Decimal Comparison Tolerance.
Division method ⎕DIV
#
Some of you may be uncomfortable with the default divide by zero behaviour:
0÷0
1
Dyalog has this thing called ⎕DIV
, Division method, which, when you set it to 1, lets all divisions by 0 give 0:
⎕DIV←1
0 0 3 3÷0 3 0 3
⎕DIV←0
0 0 0 1
If you want to error on division by zero, just use ×∘÷
instead of ÷
under the default ⎕DIV←0
.
Index origin ⎕IO
#
There is an old debate on whether to begin indexing with 0 or with 1. APL lets you choose by setting the Index Origin, ⎕IO
:
⍳4 ⊣ ⎕IO←0
⍳4 ⊣ ⎕IO←1
0 1 2 3
1 2 3 4
Note that using ⎕IO←0
means you have to accept negative indices in some cases:
3 4 5⍸2
0
⎕IO←0
3 4 5⍸2
⎕IO←1
¯1
Also note that these system variables can be localised. So if your dfn sets ⎕IO
it only applies to that function (and its children), but does not permanently affect the environment:
⎕IO,({⎕IO←0 ⋄ ⎕IO}⍬),⎕IO
1 0 1
Print precision ⎕PP
#
By default, APL prints 10 significant digits in floats. You can select how many to show by setting ⎕PP
, Print Precision:
⎕PP←3
÷7
⎕PP←10
÷7
0.143
0.1428571429
This affects ⍕
, too:
≢⍕÷7
12
≢⍕÷7 ⊣ ⎕PP←3
5
In other words, how many characters are needed to represent a seventh using that precision?
Now we can also get more precision:
○1 ⊣ ⎕PP←17 ⍝ 𝜋
3.141592653589793
⎕PP←10 ⍝ Set back to default value
Floating-point representation ⎕FR
#
What if we want even more decimal places in our 𝜋 from above? Bumping the print precision higher doesn’t work:
○1 ⊣ ⎕PP←34
3.141592653589793
The system simply doesn’t keep that much precision. For this we need to set ⎕FR
, Floating-point Representation. By default it is 645, meaning 64-bit binary. We can set it to 1287, meaning 128-bit decimal:
○1 ⊣ ⎕PP←34 ⊣ ⎕FR←1287
⎕FR←645
3.141592653589793238462643383279503
Recall also that you can set decimal comparison tolerance with ⎕DCT
.
Random link ⎕RL
#
Random link, ⎕RL
, lets you set a seed value for random numbers so you can reproduce the same random numbers again. It also lets you choose which method to use for calculating the next random number based on the seed.
⎕RL
is a two element array, but as opposed to normal arrays, you cannot modify ⎕RL
in-place; you have to assign to the entire array at once. The first element is the seed; an integer in the range 1
to ¯2+2*31
. You can also use 0
to auto-randomise, or ⍬
to optimise by not keeping track of the seed.
The second element is the method:
0=Lehmer
1=Mersenne
2=ask the OS.
If you ask the OS, you can’t provide a seed, so you have to use ⍬
:
?0 ⊣ ⎕RL ⍬ 2
0.12793188553860924
When asking our OS we get a different result each time:
?0 ⊣ ⎕RL ⍬ 2
0.5289210360276925
Let’s use Mersenne (the default) with a specific seed instead:
?0 ⊣ ⎕RL←42 1
?0 ⊣ ⎕RL←42 1 ⍝ Start the sequence at the same place
0.0019533783197548393
0.0019533783197548393
Account info ⎕AI
#
Account info, ⎕AI
, isn’t very interesting these days, except you can use ⎕AI[3]
as an absolute counter of milliseconds since the beginning of the session. This is useful to avoid having to deal with roll-overs when timing stuff.
How long does it take to wait a second?
a←3⊃⎕AI
⎕DL 1 ⍝ Sleep for 1s
a-⍨3⊃⎕AI
1289
Account name ⎕AN
#
⎕AN
is the account name, which for me is
⎕AN
stefan
Clear workspace ⎕CLEAR
#
Clear workspace, ⎕CLEAR
, is a special constant, which when referenced will clear the workspace just like )clear
does. This means you can use it in code.
Copy workspace ⎕CY
#
Copy workspace, ⎕CY
, is a function which copies from a workspace file to the current workspace. You give it the name of a workspace file as right argument, and optionally a name list on the left of items to copy. By default, it will copy everything.
'iotag'⎕CY'dfns' ⍝ Copy the iotag function from the dfns workspace
¯5 iotag 5
¯5 ¯4 ¯3 ¯2 ¯1 0 1 2 3 4 5
Delay ⎕DL
#
⎕DL
is delay as you saw before. It takes a number (floats are fine) of seconds and (shyly) returns the number of seconds actually used. ⎕DL
guarantees a delay of at least what you specified:
⎕←⎕DL 1
1.020727
Load ⎕LOAD
#
You may have already used )LOAD
. ⎕LOAD is basically the same, but in a function form. Give it the name of a workspace to load.
Off ⎕OFF
#
⎕OFF is similar to ⎕CLEAR
in that referencing its value causes the workspace to be closed, but it also terminates APL. ⎕OFF
has a special syntax though. If you put a value immediately to its right, that will become APL’s exit code.
Save ⎕SAVE
#
⎕SAVE is similar to )SAVE
in that it saves the current workspace to disk. However, ⎕SAVE
has a trick up its sleeve. If you use ⎕SAVE
under program control, you can then use ⎕LOAD
on the generated workspace file, and execution will continue where the ⎕SAVE
happened, with ⎕SAVE
giving the result 0. This allows you to write applications where the user can close the application and then resume the left-off state when opening the application again.
Time stamp ⎕TS
#
⎕TS
is time stamp, which returns the current system time as a 7-element vector; year, month, day, hour, minute, second, millisecond:
⎕TS
2022 7 27 8 37 2 31
When dealing with times and dates, there is also the date-time system function, ⎕DT
, which can convert between pretty much any date and time formats around.