Right now, Native doesn't play well with dead-code elmination. Additionally, Native review is a big bottleneck for producing and publishing new librairies. Finally, there is no way to unclude JS code which calls ports using the Elm compiler.
/**
--The top of the file declares the structure of the Native module
--and must be a valid Elm syntax declaration
module Native.SomeModule where
--Used Native modules must be explicitly imported
import Native.Utils
--We can import pre-existing library functions
--this includes them in the final output
--but they can't be explicitly called from Elm.
--A Native module must act as an interface.
import raw "Bootstrap.js"
-every used non-Native function must be explicitly imported
import Signal exposing (constant)
--Each exposed Native function is declared as a String literal in Elm
--with the name of the JS function that defines it
--This lets us statically check that no top-level functions are missing
nativeFun = "nativeFun"
otherFun = "otherFun"
**/
//The rest of the JS file is just a series of JS statements
var nativeFun = function(x)
{
if (Elm.Utils.constructor(x) == "Nothing" )
{
Elm.Utils.construct("Nothing");
}
//We construct "type" (algebraic data) values using a library function
return Elm.Utils.construct("Just", 3);
};
var otherFun = function(y)
{
return nonExposedFunction(y);
};
//We are allowed to declare other functions
//that can't be imported by Elm
var nonExposedFunction(y)
{
var ret = [];
//We build records out of arrays
//and access fields using a library function
ret["field"] = Elm.Utils.field(y, "elmField");
ret["field2] = 3;
//a library function constructs the record out of the array
return Elm.Signal.constant(Elm.Utils.record(ret));
};
- The structure of the module is declared at the top, using normal Elm syntax
- The user doesn't write a .make() function, or return a .values object. That's all done mechanically, we would be guaranteed those functions/values would always be well formed.
- The imported Native modules, and imported and exported Elm functions, must be explicitly declared
- Elm ADT and Record values are not manipulated directly, but using a library function, so Native modules would not break if Elm changed its internal representations.
- There's new syntax for including a JS file in compilation, such as pre-existing libraries.
- The module structure is defined using Elm syntax, so we can use existing parsers, and it flows nicely with the rest of the project.
- Much less Native review needed to ensure a module is well formed.
- More resistant to breaking changes.
- The
import raw
syntax can be used to include the JS side of Ports code.
- Could be slower, since we're calling library functions to access Elm values. (Could be solved by inlining).
- Requires pre-processing of comments (could be solved by putting the structure Elm declaration in its own file).
- There are now 3 types of JS ffi (Native, Ports, import raw)
@lazlo, those points both make sense. The second one is quite nice, as it might let us add a second level of static checks making sure the right values are defined. Hopefully things like this will help avoid spaghetti code...