Closed bendmorris closed 6 years ago
I'm in favor of this, since I myself had the need to both store type info in metadata and pass it as an argument in a macro function and it always ends up with something ugly like (_:SomeType)
with subsequent parsing, so it basically asks to have a syntax for that and :Type
syntax makes sense to me too, because of the way we already use colon for type hinting/checking.
I don't think the proposal makes sense in Haxe type system. In Haxe MyClass<Int>
and MyClass<Float>
are both the same value MyClass
(which is the class itself). And there's no way to represent MyClass<Int>
at runtime so it can't be runtime type checked etc. (for instance we forbid type parameters in "catch" for this reason).
So my first question would be : what problem is this proposal trying to solve?
I agree that it is somewhat useless at runtime, but it is rather inconsistent that these expressions do already have a runtime value, but no syntax can express them (as mentioned I can get the runtime "value" via a typedef now.) The main use case for me is to use complex types in metadata and as arguments to macros, in an officially supported way without hacks like (_:MyType<T>)
. This other proposal has one concrete example case, and I can imagine many others:
extern class Array<T> {
@:const(:Array<Const<T>>) function concat(a:Const<Array<T>>):Array<T>;
}
(Obligatory "yo dawg, I heard you like evolution proposals...")
In Haxe
MyClass<Int>
andMyClass<Float>
are both the same value MyClass
This isn't true of @:generic
classes at least. How would I reference a specifically parameterized generic class and pass it to Std.is?
@:generic class MyClass<T> {
var val:T;
public function new(val:T) this.val = val;
}
class Test {
static function main() {
var e = new MyClass<Int>(1);
trace(Std.is(e, MyClass)); // false
trace(Std.is(e, MyClass<Int>)); // doesn't compile
}
}
And note that again this is possible once I add a typedef, because the only barrier is syntax:
typedef MyClassInt = MyClass<Int>;
trace(Std.is(e, MyClassInt)); // true
So currently we need superfluous typedefs in order to reference a specific @:generic
class at runtime.
I don't think that it justify adding new syntax that is very specific to this case.
var _ : MyClass<String>
and I think macro : MyClass<String>
should maybe work as well. That's a good enough workaround@:generic is
or use macros to solve this problemIn both cases, adding new syntax should only be done when it clearly opens new possibilities that wouldn't be possible otherwise. The more syntax a language has the more complex it is to learn/read. Also, using :
for this case locks it for other future (and better) uses, so I think this proposal should be rejected.
I agree, but I don't think that justify adding a specific syntax just for that.
On Wed, Apr 18, 2018 at 9:04 AM, Ben Morris notifications@github.com wrote:
And note that again this is possible once I add a typedef, because the only barrier is syntax:
typedef MyClassInt = MyClass
; trace(Std.is(e, MyClassInt)); // true So currently we need superfluous typedefs in order to reference a specific @:generic class at runtime.
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/HaxeFoundation/haxe-evolution/pull/44#issuecomment-382284768, or mute the thread https://github.com/notifications/unsubscribe-auth/AA-bwMNMYyXrhNsuzXPKXeVaf8I6AgZsks5tpuV6gaJpZM4SvUSF .
Fair enough (although short lambdas are an obvious counterexample which opened no new possibilities.) If we did adopt something that made use of this (such as the Const<T>
proposal) I think opinions might shift on whether this workaround is acceptable. i.e. I don't think officially requiring:
@:const(var _:Array<Const<T>>) function concat(a:Const<Array<T>>):Array<T>;
in user code and the std library would be reasonable.
I'm also not really sold on this one. I acknowledge that it makes a specific case a bit nicer, but that alone is not enough to justify adding a new syntax.
Hmm, maybe @FrancisBourre can comment on whether or not this is useful.
We currently use strings and parse those at compile time, e.g. @type('String -> Int -> Bool')
. We have that a few hundred times in our code base. And we have @Dependency(var _:SomeType)
another few hundred times.
I'm voting for a close until someone propose a better solution.
Adds a syntax to represent types as expressions:
var a = :Array<a.b.MyClass>;
Discussed in https://github.com/HaxeFoundation/haxe/issues/6910, PR: https://github.com/HaxeFoundation/haxe/pull/6913
Rendered version