Datatype Mapping
Introduction
Julia is strongly typed while JavaScript is loosely typed, and so care must be taken to best define rules for moving data between the two languages. There are two considerations.
- How to identify the most efficient type for a new variable and mechanism for its creation.
- How to avoid unnecessary object creation.
From JavaScript to Julia
Since Julia derives a good deal of its efficiency by being able to pass typing information to LLVM, as much typing information as possible is passed from JavaScript. Not only is the source type taken into consideration, but the value as well.
From JavaScript Primitive Types
JavaScript Type | JavaScript Value | Julia Type |
---|---|---|
null | null | Void |
Boolean | true or false | Bool |
Number | integer | Int64 |
Number | not an integer | Float64 |
String | ASCII or UTF8 | UTF8String |
Date | Date | DateTime* |
RegExp | Javascipt regular expression | Regex |
Date to DateTime*
Support for automatic conversion from Javascript's Date to Julia's DateTime has been added, however, the type DateTime was only added to Julia base in version 0.4, and so this feature is currently only supported when node-julia is installed against that version of Julia.
RegExp to Regex
Javascript regular expressions are converted to Julia regular expressions. The format of Javascript regex and Julia regex are similar but not exactly the same, though they are both based on PCRE. But although the format is different, the type of the constructing argument pattern is String which is passed exactly as specified.
From JavaScript Arrays
Passing JavaScript arrays to Julia presents a special problem. Because JavaScript does not differentiate arrays based on the type of the elements they contain, any sort of typing that Julia needs for optimizing would have to be inferred. Also, JavaScript multidimensional arrays are structured as arrays of arrays unlike Julia which again makes JavaScript arrays inefficient by comparison and conversion to equivalent Julia arrays tedious. And finally, if anything, JavaScript arrays are structured row-major while Julia arrays are column major.
Arrays passed to Julia are assumed to be regular.
Currently it is an error if the source array is irregular. To enforce this, the source array is examined, and if it is multidimensional, then all sibling arrays must have the same dimensions. For example this is a valid way to take the transpose of a 2x3 array
res = julia.exec('transpose',[[ 1, 2, 3 ], [ 4, 5, 6 ]]);
console.log('transpose is ',res);
which produces the following output
transpose is [ { '0': 1, '1': 4 }, { '0': 2, '1': 5 }, { '0': 3, '1': 6 } ]
however, this is an error
console.log('transpose is ',julia.exec('transpose',[[ 1, 2, 3 ], [ 4, 5 ]]));
and produces the following exception
console.log('transpose is ',julia.exec('transpose',[[ 1, 2, 3 ], [ 4, 5 ]]));
^
Error: Malformed input array
at Error (native)
since [ 1, 2, 3 ] has different length (3) than [ 4, 5 ] (2).
Arrays are assumed to be homogeneous.
Julia requires that the type of an array includes the element type and since Julia uses this information to select the method, and assuming the narrowest type will likely give rise to the most efficient method, the most narrow type is selected from all the elements as the Julia element type where Boolean is narrower than Integer is narrower than Number. In the case of Boolean appearing in array with Number, false is mapped to 0 and true is mapped to 1. It is currently an error for String to appear with anything other than String.
Type Any currently not supported.
Julia does all allow for heterogeneous Arrays by defining the umbrella type Any which is implicitly slow as the type must accompany the value. Thus this option is currently not available, but will be in an upcoming release.
Arrays of null
Arrays of null values are also allowed but share the same property as String; they can only exist alongside other null elements. Each element is mapped to the Julia value nothing.
Arrays of Native Arrays
To support speedy multidimensional arrays, mixed use of arrays and NativeArrays are allowed. The ultimate type will of this combination will be determined using homogeneity rules above see Buffer and Native Arrays for more information.
From Julia to JavaScript
This direction is easier to define since Julia types are more specific than those of JavaScript.
From Julia
The table below shows how the following Julia types are mapped to their corresponding JavaScript types.
Julia Type | JavaScript Type |
---|---|
Void | null |
Bool | Boolean |
Int8, Uint8, Int16, UInt16, Int32, UInt32 | Number |
Float32, Float64 | Number |
Int64, UInt64 | Number** |
ASCIIString,UTF8String | String |
SubString | String |
DateTime* | Date |
Regex | RegExp |
Datatype | JRef*** |
Julia Int64 and UInt64 will be mapped to Number **
Julia Int64 and Uint64 will be mapped to Number but for numbers larger than 9007199254740992, there will be loss of precision since JavaScript Numbers are internally represented using double.
Other Julia Datatypes Mapped to JRef ***
Beyond the basic mapping, Julia composites are retuned as JRefs which are an opaque type that can be passed back to Julia as arguments to eval, exec, and Script.exec, see JRef ] for more information.
From Julia Arrays
JavaScript NativeArrays are used whenever possible. Thus when the Julia return type is an array of Integer or Float, even if multidimensional, the result will contain NativeArrays as the most derived children. This support is paired with allowing arrays of NativeArrays as input.
Updated less than a minute ago