More on Constructors in Haxe
What's bugging me about constructors is making things easy for people to guess where they can get things.
What I'd like
Type.Constructor(args);
This isn't, for various reasons, an option. For example:
typedef SomeObject = {
final value : String;
}
Has no runtime representation: SomeObject is not a value
Which makes sense, typedef
s don't have reflection either, they are compile time structures.
abstract AnotherObject(String) from String{
}
If you try to reference an abstract like AnotherObject
without one of it's members, you get Cannot use abstract as value
, which makes sense because at runtime what is happening is that the member functions of AnotherObject
are being called with a value of it's delegated type.
A Fix of Sorts
Haxe happily handles phantom types, so we can use this, with a little boilerplate to get something predictable:
enum TAG<T>{
TAG;
}
You can fox the system by constructing the phantom type through typing your function explicitly.
static public function AnotherObject():TAG<AnotherObject>{
return TAG;//compiler will not complain, and pattern matching works.
}
To make this more accessible I use a [wildcard](https://github.com/ohmrun/stx_nano/blob/develop/src/main/haxe/stx/nano/Wildcard.hx), which because of the way Haxe publishes enum constructors plus the way static extensions work gives us a space to create predictable constructors.
var a = __;
$type(a);//Wildcard
and a static extension pivoting on the wildcard value:
class AnotherObjectCtr{
static public function AnotherObject(wildcard:Wildcard):TAG<AnotherObject>{
return TAG;
}
and can be used like this:
final ctrs = __.AnotherObject();
$type(ctrs);//TAG<AnotherObject>
And if you want to add to the list of constructors, you can do so as follows:
using AnotherObjectCtrMembers;
class AnotherObjectCtrMembers{
static public function unit(tag:TAG<AnotherObject>):AnotherObject{
return ("test":AnotherObject);
}
}
and the whole thing looks like:
using stx.Nano;
using AnotherObjectCtr;
using AnotherObjectCtrMembers;
function test_ctr(){
final v = __.AnotherObject().unit();
$type(v);//AnotherObject
trace(v);//"test"
}
Running code here