Types
MAGES maps every .NET data type to one of its data types:
- Number (
System.Double) - Boolean (
System.Boolean) - String (
System.String) - Matrix (
System.Double[,]) - Complex (
System.Numerics.Complex) - Complex Matrix (
System.Numerics.Complex[,]) - Object (
System.Collections.Generic.IDictionary<System.String, System.Object>) - Function (
Mages.Core.Function, essentially aDelegatemappingObject[]toObject) - Nothing (
null)
These seven kinds of types spawn the whole set of capabilities offered by MAGES. For instance, even if we use a function like catch (see Functions) the result will be an IDictionary<String, Object> instance. There is no special type returned.
Type Mapping
The following table yields the essential type mapping.
| MAGES | .NET |
|---|---|
| Complex | Complex |
| Number | Double |
| Single | |
| Decimal | |
| Byte | |
| UInt16 | |
| UInt32 | |
| UInt64 | |
| Int16 | |
| Int32 | |
| Int64 | |
| Boolean | Boolean |
| String | String |
| Char | |
| CMatrix | Complex[,] |
| Matrix | Double[,] |
| Double[] | |
| List |
|
| Function | Function |
| Delegate | |
| Object | IDictionary<String, Object> |
| Object | |
| Nothing | null |
The table on described the direct relations. Furthermore, there are some additional relations.
Type Casting
MAGES allows casting between its own types. For instance, any number can be casted to a boolean with the negate operator ~.
~~1.5 // true
~~0 // false
There are also other occasions where numbers are transformed to booleans. Similarly, strings transform to boolean.
~~"test" // true
~~"" // false
Therefore any non-empty string represents true. Empty strings are interpreted as false.
Objects are false if they are empty. So we show the following examples:
~~new { a: 0 } // true
~~new { } // false
Functions are always true. Nothing is always false. The big exception to all the shown identities are matrices. Here the not operator only transforms the matrix to a logical matrix (only consisting of zeros and ones, but still equivalent to a .NET double[,]). This is time to introduce to useful logical helper functions, all and any. Both of them transform any non-matrix value as booleans - as seen previously. However, for matrices they do not stop at logical matrices, but go all the way to booleans.
any([0, 0, 1]) // true
all([0, 0, 1]) // false
any([0, 0, 0]) // false
all([1, 1, 1]) // true
any returns true once any non-zero value is found in the matrix. all returns false once any zero value is found in the matrix.
The following tables yield information on casting possibilities.
From x |
To y |
Code |
|---|---|---|
| Number | Boolean | y = any(x) |
| String | y = stringify(x) |
|
| Matrix | y = x' |
|
| Complex | Boolean | y = any(x) |
| String | y = stringify(x) |
|
| Matrix | y = x' |
|
| Boolean | Number | y = +x |
| String | y = stringify(x) |
|
| Matrix | y = x' |
|
| String | Number | y = +x |
| Boolean | y = any(x) |
|
| Matrix | y = x' |
|
| CMatrix | Number | (nothing) |
| Boolean | y = any(x) |
|
| String | y = stringify(x) |
|
| Matrix | Number | (nothing) |
| Boolean | y = any(x) |
|
| String | y = stringify(x) |
|
| Object | Number | y = +x // NaN |
| Boolean | y = any(x) |
|
| String | y = stringify(x) |
|
| Matrix | y = x' // [NaN] |
|
| Function | Number | y = +x // NaN |
| Boolean | y = any(x) // true |
|
| String | y = stringify(x) |
|
| Matrix | y = x' // NaN |
|
| Nothing | Boolean | y = any(x) // false |
| String | y = stringify(x) |
|
| Matrix | y = x' // [NaN] |
Things that have not been mentioned, e.g., casting from number to function are not directly possible, but can be done trivially. For instance, a number x can be brought into a function y by writing y = () => x. Similarly, everything can be converted to an object. Here we just need to know what we call the key. If we go with the name value then we can use y = new { value: x } to transform any value to an object.
For transforming a matrix into a number multiple ways are possible. If the cast is required internally then the first value is picked if there is just a single value. Otherwise NaN is taken due to ambiguity. Explicitly, however, there are multiply options, e.g., picking a specific element, performing a special operation such as det or trace, or using a self-defined way.
Type Checking
Furthermore, two interesting functions exist: is and as. Both take a type name (e.g., Number) and a value as arguments. However, while the former returns a boolean value indicating if the value is of the given type, the latter returns the converted value or undefined.
