~~Title: Evaluator Variables~~ The evaluator supports the following variable types: ^Type^Description^Minimum^Maximum^ |bool|boolean (`true` or `false`)|n/a|n/a| |int|signed 32-bit integer|-2147483648|2147483647| |uint|unsigned 32-bit integer|0|4294967295| |int64|signed 64-bit integer|-9223372036854775808|9223372036854775807| |uint64|unsigned 64-bit integer|0|18446744073709551615| |double|double-precision floating point|1.7E-308|1.7E+308| |date|date/time|1601-01-01 00:00:00|9999-12-31 23:59:59| |str|string|n/a|n/a| |path|path|n/a|n/a| |map|value container|n/a|n/a| When you initialise a variable, some types are inferred automatically: ^Example^Initialises as^ |x = true;|bool| |x = false;|bool| |x = 15;|uint| |x = -15;|int| |x = 5000000000;|uint64| |x = -5000000000;|int64| |x = 1185.15;|double| |x = "string";|str| |x = [a = 1; b = 2;];|map| There are two ways you can explicity initialise a variable as a certain type. This is required for //date// and //path// variables which are always initialised from strings. * You can use the **[[:reference::evaluator:as|As]]** operator, for example `d = "2023-08-20" as date;` * You can use the `:` operator, for example `d: date = "2023-08-20";` For example, to initialise a variable as a path as opposed to a plain string: p = "C:\Windows" as path; p = p + "System32"; Output(p); --> "C:\Windows\System32" Note in the above example that the final string contains a backslash between "Windows" and "System32" - that's because it was initialised as a //path// variable, and adding strings to //path// variables adds path separators automatically. See the documentation for the **[[:reference::evaluator:as|As]]** operator for more details on explicit initialisation. The `:` operator uses the same type keywords as the **As** operator does. The evaluator will implicitly convert variable types if needed. For example, if you call a function that's documented as taking an //int// but you pass it a //uint//, and //int64// or even a //str//, the value will be converted automatically (assuming such a conversion is possible, of course). You can use the **[[:reference:evaluator:typeof]]** function to determine a variable's type. ==Variable names== Ordinary variables must begin with a letter; after that, they can contain any number of letters, numbers or symbols like `_` and `$`. The evaluator also lets you access external variables that begin with a `$` sign. For example, a function that uses `@set name Jon` and then invokes evaluator code would be able to access that variable using the name `$name`. External variables scoped to tabs and Listers can be accessed, for example `$glob:name` would let you get or set a globally scoped variable from within the evaluator. Normally, attempting to use the value of a variable that doesn't exist causes an error, however for compatibility reasons, variables that begin with a `$` allow this - if they haven't been previously defined they'll simply return an empty string. You can also access environment variables from evaluation code as you can in normal functions. For example, Output(%PROGRAMFILES%); --> C:\Program Files You can set environment variables from evaluation code too but note that this only affects the environment inside Opus itself - globally the rest of the system won't see the changed value. ==Numeric constants== You can express numeric constants in a number of ways: * Plain decimal numbers such as `15` or `-15`. * Hexadecimal numbers such as `0xe`. * Size values such as `5kb`, `21gb`, `1.75tb` (note: only supports binary units.) * Date units using suffixes `h` (hour), `m` (minute), `s` (second), `d` (day), `M` (month) and `y` (year) when adding to or subtracting from dates. * Fractional numbers such as `1185.15`. * `true` and `false` are also available as boolean constants. * `pi` is predefined as the value of π. ==Other predefined constants== * `CRLF` is a predefined value that expands to a carriage return and linefeed character. You can use it if you want to build multiline strings in the evaluator. ==Value containers== A //value container// is a variable that can contain other variables - similar to a //struct// in C++ or a //map// in JavaScript. Value containers are defined using the `[ ]` operator. The square brackets act like a //scope// - within the brackets, variables you assign will become members of the container. For example, // defines an empty container x = [ ]; // defines a container with three members x = [ a = 5; b = 10; c = "hello!"; ]; After a value container is created and / or initialised, you can access its member variables (or add new ones) using the `.` operator. Output(x.c); --> hello! x.c = Left(x.c, 5) + " world!"; Output(x.c); --> hello world!