{
"cells": [
{
"cell_type": "markdown",
"id": "524da8c8",
"metadata": {},
"source": [
"# Behaviour, session\n",
"\n",
"There are several system functions that control behavioural aspects of the interpreter and the session itself. \n",
"\n",
"## Comparison tolerance `⎕CT`\n",
"\n",
"To deal with inexactness in floating point representation, we have `⎕CT`, which is [Comparison Tolerance](help.dyalog.com/latest/index.htm#Language/System%20Functions/ct.htm). 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.\n",
"\n",
"`⎕CT` is a tiny value: "
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "975bc692",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"1E¯14\n",
""
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"⎕CT"
]
},
{
"cell_type": "markdown",
"id": "d84c609e",
"metadata": {},
"source": [
"Two floating point numbers `X` and `Y` are considered to be equal if `(|X-Y)≤⎕CT×(|X)⌈|Y`:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "38e10c48",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"1\n",
""
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"1=1+1e¯15"
]
},
{
"cell_type": "markdown",
"id": "0dd42460",
"metadata": {},
"source": [
"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:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "4403486b",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"1\n",
""
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"text/html": [
"0\n",
""
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"⎕CT←1E¯10 ⍝ More tolerant\n",
"1=1+1e¯11\n",
"\n",
"⎕CT←0 ⍝ Disable comparison tolerance\n",
"1=1+1e¯15\n",
"\n",
"⎕CT←1E¯14 ⍝ Reset to default"
]
},
{
"cell_type": "markdown",
"id": "9de81145",
"metadata": {},
"source": [
"If you use 128-bit decimal floats (we'll get back to that), you can instead use `⎕DCT`, [Decimal Comparison Tolerance](help.dyalog.com/latest/index.htm#Language/System%20Functions/dct.htm). \n",
"\n",
"## Division method `⎕DIV`\n",
"\n",
"Some of you may be uncomfortable with the default divide by zero behaviour:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "b4416333",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"1\n",
""
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"0÷0"
]
},
{
"cell_type": "markdown",
"id": "9de62101",
"metadata": {},
"source": [
"Dyalog has this thing called `⎕DIV`, [Division method](http://help.dyalog.com/latest/index.htm#Language/System%20Functions/div.htm), which, when you set it to 1, lets all divisions by 0 give 0: "
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "4bfc9977",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"0 0 0 1\n",
""
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"⎕DIV←1\n",
"0 0 3 3÷0 3 0 3\n",
"⎕DIV←0"
]
},
{
"cell_type": "markdown",
"id": "6031a8c2",
"metadata": {},
"source": [
"If you want to error on division by zero, just use `×∘÷` instead of `÷` under the default `⎕DIV←0`.\n",
"\n",
"## Index origin `⎕IO`\n",
"\n",
"There is an old debate on whether to begin indexing with 0 or with 1. APL lets you choose by setting the [Index Origin](http://help.dyalog.com/latest/index.htm#Language/System%20Functions/io.htm), `⎕IO`:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "4cecbedd",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"0 1 2 3\n",
""
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"text/html": [
"1 2 3 4\n",
""
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"⍳4 ⊣ ⎕IO←0\n",
"⍳4 ⊣ ⎕IO←1"
]
},
{
"cell_type": "markdown",
"id": "2c39335b",
"metadata": {},
"source": [
"Note that using `⎕IO←0` means you have to accept negative indices in some cases: "
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "a1afce66",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"0\n",
""
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"3 4 5⍸2"
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "0420c65b",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"¯1\n",
""
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"⎕IO←0\n",
"3 4 5⍸2\n",
"⎕IO←1"
]
},
{
"cell_type": "markdown",
"id": "d3c01019",
"metadata": {},
"source": [
"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:"
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "2a4e382a",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"1 0 1\n",
""
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"⎕IO,({⎕IO←0 ⋄ ⎕IO}⍬),⎕IO"
]
},
{
"cell_type": "markdown",
"id": "6b350c12",
"metadata": {},
"source": [
"## Print precision `⎕PP`\n",
"\n",
"By default, APL prints 10 significant digits in floats. You can select how many to show by setting `⎕PP`, [Print Precision](http://help.dyalog.com/latest/index.htm#Language/System%20Functions/pp.htm): "
]
},
{
"cell_type": "code",
"execution_count": 24,
"id": "b6b71b0f",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"0.143\n",
""
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"text/html": [
"0.1428571429\n",
""
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"⎕PP←3\n",
"÷7\n",
"⎕PP←10\n",
"÷7"
]
},
{
"cell_type": "markdown",
"id": "39d8f62a",
"metadata": {},
"source": [
"This affects `⍕`, too:"
]
},
{
"cell_type": "code",
"execution_count": 26,
"id": "a7c4587a",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"12\n",
""
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"≢⍕÷7"
]
},
{
"cell_type": "code",
"execution_count": 27,
"id": "a01fa204",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"5\n",
""
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"≢⍕÷7 ⊣ ⎕PP←3"
]
},
{
"cell_type": "markdown",
"id": "a3fa2ef2",
"metadata": {},
"source": [
"In other words, how many characters are needed to represent a seventh using that precision? \n",
"\n",
"Now we can also get _more_ precision:"
]
},
{
"cell_type": "code",
"execution_count": 29,
"id": "e49fce24",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"3.141592653589793\n",
""
]
},
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"○1 ⊣ ⎕PP←17 ⍝ 𝜋"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "894504d4",
"metadata": {},
"outputs": [],
"source": [
"⎕PP←10 ⍝ Set back to default value"
]
},
{
"cell_type": "markdown",
"id": "e7667d4a",
"metadata": {},
"source": [
"## Floating-point representation `⎕FR`\n",
"\n",
"What if we want even _more_ decimal places in our 𝜋 from above? Bumping the print precision higher doesn't work:"
]
},
{
"cell_type": "code",
"execution_count": 32,
"id": "66c0120f",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"3.141592653589793\n",
""
]
},
"execution_count": 32,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"○1 ⊣ ⎕PP←34"
]
},
{
"cell_type": "markdown",
"id": "10f82dc0",
"metadata": {},
"source": [
"The system simply doesn't keep that much precision. For this we need to set `⎕FR`, [Floating-point Representation](http://help.dyalog.com/latest/index.htm#Language/System%20Functions/fr.htm). By default it is 645, meaning 64-bit binary. We can set it to 1287, meaning 128-bit decimal:"
]
},
{
"cell_type": "code",
"execution_count": 35,
"id": "38975a82",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"3.141592653589793238462643383279503\n",
""
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"○1 ⊣ ⎕PP←34 ⊣ ⎕FR←1287\n",
"⎕FR←645"
]
},
{
"cell_type": "markdown",
"id": "e6fa7598",
"metadata": {},
"source": [
"Recall also that you can set decimal comparison tolerance with `⎕DCT`.\n",
"\n",
"## Random link `⎕RL`\n",
"\n",
"[Random link](http://help.dyalog.com/latest/index.htm#Language/System%20Functions/rl.htm), `⎕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.\n",
"\n",
"`⎕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. \n",
"\n",
"The second element is the method:\n",
"\n",
"* 0=Lehmer\n",
"* 1=Mersenne\n",
"* 2=ask the OS.\n",
"\n",
"If you ask the OS, you can't provide a seed, so you have to use `⍬`:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "7ead9dd2",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"0.1279318855\n",
""
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"?0 ⊣ ⎕RL ⍬ 2"
]
},
{
"cell_type": "markdown",
"id": "25482fdb",
"metadata": {},
"source": [
"When asking our OS we get a different result each time: "
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "258f1901",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"0.528921036\n",
""
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"?0 ⊣ ⎕RL ⍬ 2"
]
},
{
"cell_type": "markdown",
"id": "045c8b63",
"metadata": {},
"source": [
"Let's use Mersenne (the default) with a specific seed instead:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "4bba783f",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"0.00195337832\n",
""
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"text/html": [
"0.00195337832\n",
""
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"?0 ⊣ ⎕RL←42 1\n",
"?0 ⊣ ⎕RL←42 1 ⍝ Start the sequence at the same place"
]
},
{
"cell_type": "markdown",
"id": "860e53cb",
"metadata": {},
"source": [
"## Account info `⎕AI`\n",
"\n",
"[Account info](http://help.dyalog.com/latest/index.htm#Language/System%20Functions/ai.htm), `⎕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.\n",
"\n",
"How long does it take to wait a second? "
]
},
{
"cell_type": "code",
"execution_count": 48,
"id": "414d205a",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"1335\n",
""
]
},
"execution_count": 48,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"a←3⊃⎕AI\n",
"⎕DL 1 ⍝ Sleep for 1s\n",
"a-⍨3⊃⎕AI"
]
},
{
"cell_type": "markdown",
"id": "2765325e",
"metadata": {},
"source": [
"## Account name `⎕AN`\n",
"\n",
"`⎕AN` is the [account name](http://help.dyalog.com/latest/index.htm#Language/System%20Functions/an.htm), which for me is"
]
},
{
"cell_type": "code",
"execution_count": 49,
"id": "08b3bbed",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"stefan\n",
""
]
},
"execution_count": 49,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"⎕AN"
]
},
{
"cell_type": "markdown",
"id": "558b73fb",
"metadata": {},
"source": [
"## Clear workspace `⎕CLEAR`\n",
"\n",
"[Clear workspace](http://help.dyalog.com/latest/index.htm#Language/System%20Functions/clear.htm), `⎕CLEAR`, is a special constant, which when referenced will clear the workspace just like `)clear` does. This means you can use it in code.\n",
"\n",
"## Copy workspace `⎕CY`\n",
"\n",
"[Copy workspace](http://help.dyalog.com/latest/index.htm#Language/System%20Functions/cy.htm), `⎕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. "
]
},
{
"cell_type": "code",
"execution_count": 51,
"id": "7743b8bc",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"¯5 ¯4 ¯3 ¯2 ¯1 0 1 2 3 4 5\n",
""
]
},
"execution_count": 51,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"'iotag'⎕CY'dfns' ⍝ Copy the iotag function from the dfns workspace\n",
"¯5 iotag 5"
]
},
{
"cell_type": "markdown",
"id": "bbbc9da7",
"metadata": {},
"source": [
"## Delay `⎕DL`\n",
"\n",
"`⎕DL` is [delay](http://help.dyalog.com/latest/index.htm#Language/System%20Functions/dl.htm) 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:"
]
},
{
"cell_type": "code",
"execution_count": 53,
"id": "670bef10",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"1.0179829999999999\n",
""
]
},
"execution_count": 53,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"⎕←⎕DL 1"
]
},
{
"cell_type": "markdown",
"id": "373e637c",
"metadata": {},
"source": [
"## Load `⎕LOAD`\n",
"\n",
"You may have already used `)LOAD`. [⎕LOAD](http://help.dyalog.com/latest/index.htm#Language/System%20Functions/load.htm) is basically the same, but in a function form. Give it the name of a workspace to load. \n",
"\n",
"## Off `⎕OFF`\n",
"\n",
"[⎕OFF](http://help.dyalog.com/latest/index.htm#Language/System%20Functions/off.htm) 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.\n",
"\n",
"## Save `⎕SAVE`\n",
"\n",
"[⎕SAVE](http://help.dyalog.com/latest/index.htm#Language/System%20Functions/save.htm) 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. \n",
"\n",
"## Time stamp `⎕TS`\n",
"\n",
"`⎕TS` is [time stamp](http://help.dyalog.com/latest/index.htm#Language/System%20Functions/ts.htm), which returns the current system time as a 7-element vector; year, month, day, hour, minute, second, millisecond: "
]
},
{
"cell_type": "code",
"execution_count": 54,
"id": "9b1188ff",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"2022 1 14 9 35 27 312\n",
""
]
},
"execution_count": 54,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"⎕TS"
]
},
{
"cell_type": "markdown",
"id": "8cc9db9c",
"metadata": {},
"source": [
"When dealing with times and dates, there is also the [date-time](http://help.dyalog.com/latest/index.htm#Language/System%20Functions/dt.htm) system function, `⎕DT`, which can convert between pretty much any date and time formats around."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c9cc48e0",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Dyalog APL",
"language": "apl",
"name": "dyalog-kernel"
},
"language_info": {
"file_extension": ".apl",
"mimetype": "text/apl",
"name": "APL"
}
},
"nbformat": 4,
"nbformat_minor": 5
}