-
-
Notifications
You must be signed in to change notification settings - Fork 671
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add @:using #7462
Add @:using #7462
Conversation
Is it possible to implement it via keyword instead of a meta? enum MyOption<T> using MyOption.MyOptionTools {...} |
As I said, I'm not sure if that's necessary. Also, the nice thing about metadata is that you can inject them from the outside... |
I think the |
Sounds like a pretty cool approach and so I tried using this on a Vector3 typedef without much success. typedef Vector3 =
{
var X : Float;
var Y : Float;
var Z : Float;
} The reason for using typedefs here is that the compiler is often able to optimize the code, resulting in not creating an instance at all (which is very nice!). For example: var temp : Vector3 = {X: 0, Y: 0, Z: 0}; Becomes: var inlobj_X = 0;
var inlobj_Y = 0;
var inlobj_Z = 0; The regular way of adding, for example, an add function to Vector3 with static extension and the using keyword fine. I really liked the approach in this topic because it allows the Vector3 typedef to kind of define that it always wants a set of functions. @:using(Vector3.Vector3Math)
typedef Vector3 =
{
var X : Float;
var Y : Float;
var Z : Float;
}
class Vector3Math
{
public static inline function Add(vector : Vector3, value : Float)
{
return
{
X: vector.X + value,
Y: vector.Y + value,
Z: vector.Z + value
}
}
} import project.Vector3;
class Test
{
public function new()
{
var vector : Vector3 = {X: 0, Y: 0, Z: 0};
temp.Add(10);
}
} The result is that the compiler outputs that project.Vector3 has no field Add. |
Another "closely" related thing is that it would be very cool if one could create static constructors through this approach as well. So for example: @:using(Vector3.Vector3Math)
typedef Vector3 =
{
var X : Float;
var Y : Float;
var Z : Float;
}
class Vector3Math
{
public static inline function Empty(vector : Vector3, value : Float)
{
return
{
X: 0,
Y: 0,
Z: 0
}
}
} And then use it like this: import project.Vector3;
class Test
{
public function new()
{
var vector : Vector3.Empty();
}
} |
remcohuijser |
The problem is mostly that FWIW this gives you the same interface (although it differs from a type perspective): @:structInit class Vector3 {
var X : Float;
var Y : Float;
var Z : Float;
static public function Empty():Vector3 return { X: 0, Y: 0, Z: 0 };
} |
Well this indeed gets me a bit further, thanks for that! |
Thanks for thinking with me here. I really want to make them as low level as possible so that the compiler can optimize most of the stuff away. I actually think that I might look into writing a macro that converts occurrences of a vector3 inside a function to 3 separate float values. |
As discussed, this allows type-level static extensions through the
@:using(Path1, Path2)
metadata. It works exactly like module-level static extensions and is checked right after that, but before global static extensions.I was considering suggesting a specific syntax for this, e.g.
class Main using MainUsing { }
, but I'm not sure if that's necessary.There are no extensive tests yet; this is my usage example:
Output:
And here's the obligatory example with enums so everybody goes "Aaaah so that's why this is useful":
Generated JS:
I even remembered to show these fields in completion.