-
-
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
@:using should work for all type kinds #8188
Comments
I think we should not support anonymous types (structures and functions), at least initially, because of their decentralized nature and the resulting potential for conflict. Scenario: // library A:
package libA;
@:using(libA.Vector.VectorTools)
typedef Vector = {
var x:Float;
var y:Float;
}
class VectorTools() {
static public function times(a:Vector, b:Vector):Float
return a.x * b.x + a.y * b.y;
}
// library B:
package libB;
@:using(libB.Vector.VectorTools)
typedef Vector = {
var x:Float;
var y:Float;
}
class VectorTools() {
static public function times(a:Vector, b:Vector):Float
return a.x * b.y - a.y * b.x;
} Put both in a single project and kaboom, you have a conflict. Either one gets applied or the other. Let's assume libB's global static extension wins. In that case, all code in libA that does During the original proposal, it never occurred to me that this could actually be used on typedefs, because In any case, unless somebody has a brilliant idea how to support typedefs while preventing libraries from mistakenly hijacking types they don't own, I propose to explicitly forbid package libB;
@:using(libB.SomeCleverTrick)
typedef B = libA.A;
package libC;
@:using(libC.OtherCleverTrick)
typedef C = libA.A; Any library should only be able to augment types for which it has complete ownership, e.g. an interface which either resides in this library and only in this library (regardless of whether some other lib has an interface of the same structure) or not. There's always the option to pull fun tricks with macros, but I think it's fair to say that if your lib manipulates other 3rd party code via macros, the consequences are yours to bear. In the same vein, perhaps it would make sense to back off of "the nice thing about metadata is that you can inject them from the outside", because it's a pretty explicit incitement to the type of behavior that drives the very author of this suggestions nuts ;) |
I think it's important that if not all types are supported, there's a proper compile-time error for it (rather than it just silently doing nothing). That would avoid any more of the confusion we've seen in those 3 issues. |
As for the rest of the argument: I (and apparently others, according to those issues) expected using libA.Vector.VectorTools;
using libB.Vector.VectorTools;
class Main {
static function main() {
var v1:libA.Vector = {x: 0, y: 0};
var v2:libB.Vector = {x: 0, y: 0};
v1.printLibName(); // b
v2.printLibName(); // b
}
} Edit: I realize that you're mostly making the argument that |
In that example you put |
@RealyUniqueName But if that was doable, my example should work too? The first argument of the static extension methods is properly typed as |
Indeed. @:using(my.pack.ArrayTools)
typedef MyArray<T> = Array<T>;
function myFun(a:MyArray<Int>) {
if(a.contains(42)) {
return theAnswer();
}
return comeBackLater();
} |
But wait. |
That is not how static extensions work. If you write
That is exactly the type of thing that |
Except |
It's not about being "hidden" or not, it's about boundaries, which are the fundamental basis for composability. With If as a user of
That's what I meant by "I propose to explicitly forbid Let me be clear: I'm not against supporting typedefs on some principled stance about implicitness. I personally believe that it should be left to the user to figure out what degree of "magic" best works for them and their team. My opposition is purely on pragmatic grounds:
|
Yes and as a library author, you should not be doing that for anonymous types for the reasons I've explained quite abundantly. It may be convenient, but it won't work at the scale of an ecosystem. |
|
The only thing left to decide and implement is |
In any case |
Since |
Adding to the discussion issue for future reference if this is revisited: an example where For example, js.lib.Iterator would become @:using(js.lib.HaxeIterator)
typedef Iterator<T> = {
function next():IteratorStep<T>;
} |
@haxiomic Maybe this could also be achieved by wrapping it in an abstract? |
@Gama11 That works but didn't semantically marry up with haxe iterators when I tried it in the original PR Although I need to think on it again because it's quite confusing |
@back2dos But there is a difference between |
Just merging these three issues that are all essentially about the same thing:
@:using
not behaving as expected and only working on some kinds of types.The text was updated successfully, but these errors were encountered: