# μScript The purpose of this document is to be a guide to using the μScript language. It is not intended to explain any history of the language, implementation details or details on how to embed μScript in programs. For information on that, look [here](../../../README.md). ## Types μScript supports a couple of basic types, namely: - [Numbers](#numbers) (double-precision floating-point) - [Booleans](#booleans) - [Strings](#strings) - [Objects](#objects) - [Lists](#lists) - [Functions](#functions) Numbers, booleans and strings can be created just like in java. ## Numbers You can use the most common math operations on numbers. That includes addition, subtraction, multiplication, division, modulo, pow, and your standard comparison operators. Order of operation is also supported. The StdLib comes with additional constants and functions, namely: `PI`, `E`, `round`, `floor`, `ceil`, `abs`, `random`
Example
```mu listOf( 2 + 5, 2 - 5, 0.5 * 4, 2 + 2 * 3, (2 + 2) * 3, 4 / 2, 5 % 3, // this is modulo 2 ^ 10, // two to the power of ten 12 > 4, 5 < 3, 4 >= 4, 5 != 2, 8 == 8, round(PI, 2) + floor(E) // round also accepts a second argument: precision, but it can be ommitted to round to a whole number ) ``` Result: ``` [7, -3, 2, 8, 12, 2, 2, 1024, true, false, true, true, true, 5.1400] ```
## Booleans Your standard logic operators are supported. XOR/XNOR are just your normal `!=`/`==` operators. Make sure not to use `||`, as that is the string concatenation operator, not OR. You can also use ternary conditional operators as you would in java.
Example
```mu listOf( 1 < 3 ? "this is correct" : "it is not", // if the condition is true, do the first thing. Else, do the second !true, // not true & false, // and true & true, true | false, // or false | false ) ``` Result: ``` ['this is correct', false, false, true, true, false] ```
## Strings Strings only support concatenation via `||`. You can also concatenate other things to a string. Values of all other types can also be coerced into strings. Equality operations are supported. The StdLib comes with some additional functions, namely: `toUpper`, `toLower`, `contains` and `replace`
Example
```mu 15 || "string one"::toUpper() || 'string Two'::toLower() || "example"::contains("thing") || "yxamply"::replace("y", "e") ``` Result: ``` 15STRING ONEstring twofalseexample ```
## Objects You cannot create your own objects, but objects may be passed to your script from functions or as parameters. You can read (but not write) their fields via `.` or `[]`. In the following example, the objects `object` and `object2` is passed to the script. The StdLib also contains two objects, namely `date` and `time` which allow reading the current date and time. They also allow creating date/time objects and comparing them.
Example
```mu listOf( object2.valuename, // This is how you would normally do this object2['valuename'], // You can also use [] this['object2']['valuename'], // 'this' is always an object representing the current scope object2['value' || 'name'], // [] can contain any expression object[object2['sub'].val / 10], // [] even references to other field object2.sub['val'] * 2, // You can do anything with the value of a field object.subvalue / (object2.sub.val + 6), object2.stringfunc("some parameter"), // Objects can also contain functions date(2023, 5, 13), time(23, 55, 10), date(2020, 5, 10) > date.today ) ``` Result: ``` ['subvalue', 'subvalue', 'subvalue', 'subvalue', 'One', 20, 64, 'some parameter', 2023-05-13, 23:55:10, false] ```
## Lists Lists can be created with the stdlib function `listOf` (as seen in other examples). You can access their entries with `[]`, just like you would access fields for objects. In function calls, you can use the spread operator (`...`) to use all elements of the list as parameters. The StdLib also comes with some additional functions, namely `len`, `isEmpty`, `concat`, `filter`, `map`, `flatMap`, `fold` and `forEach`.
Example
```mu listOf( len(listOf(1, 2, 3)), isEmpty(listOf()), concat(listOf(1, 2), listOf(3, 4)), listOf(1, 2)::concat(listOf(3, 4))::len(), // Don't forget using the bind operator for readability in longer chains time(listOf(23, 55)..., 10), // You can use the spread operator in any call, not just variadic ones listOf(1, 2, 3)[1], // Lists are 0-indexed listOf(1, 2, 3, 4)::filter({n->n%2==0})::map({n->n/2}) // you can chain the additional functions for proper functional programming ) ``` Result: ``` [3, true, [1, 2, 3, 4], 4, 23:55:10, 2, [1, 2]] ```
## Functions μScript is functional as in functions being treated like any other data type. This means you can pass them to methods as arguments, store them in variables or do whatever else you feel like. A closure consists of a list of arguments (of which the last may be variadic) and some instructions.
Example
```mu someFunction = {n -> n * 2} // By assigning a closure to a variable, you get an equivalent to a normal java function someVal = 1 $someVal = 1 {->someVal = 12}() // If you try to change a variable from inside a closure, you create a copy of it. The outer scope doesn't change {->$someVal = 12}() // The only exception to that are variables prefixed with a dollar sign // These work like mutable variables in other languages /* Use `...` to mark the last argument of a closure as variadic All arguments that don't fit in the previous parameters will be packed in it as a list Note that the length of that list may be 0 */ someFunction2 = { a, b... -> isEmpty(b) ? a : a * someFunction2(b...) // you can use the spread operator on that list like any other } listOf( someFunction(1), // Closures are ran with parentheses {->"some expression(s)"}(), // You don't have to store them to call them once... {f1, f2 -> f1(f2(5))}(someFunction, {n->n}), // ... or to pass them to a higher order function {-> 12 + 3 10 + 2 5 + 2 // The last expression in a closure is its result. This is the same behavior as scripts (like the one this runs in) }(), {-> 12 + 3; // You can (and probably should) use semicolons to seperate expressions 10 + 2; 5 + 2; }(), 1::someFunction(), // You can use the bind operator '::' to create a new closure using the value to the left as the first argument // In this case, this new closure is executed immediately using the parentheses, but doing that isn't necessary 1::({n->n})(), // Instead of a name, you can also use any expression as the right part of a bind operator (if it is in parentheses) someVal, $someVal, someFunction2(1, 2, 3, 4) ) ``` Result: ``` [2, 'some expression(s)', 10, 7, 7, 2, 1, 1, 12, 24] ```