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

Complex type expressions #44

Closed
wants to merge 1 commit into
base: master
from

Conversation

Projects
None yet
5 participants
@bendmorris
Copy link

bendmorris commented Mar 18, 2018

Adds a syntax to represent types as expressions: var a = :Array<a.b.MyClass>;

Discussed in HaxeFoundation/haxe#6910, PR: HaxeFoundation/haxe#6913

Rendered version

@nadako

This comment has been minimized.

Copy link
Member

nadako commented Mar 18, 2018

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.

@skial skial referenced this pull request Mar 22, 2018

Closed

Haxe Roundup 424 #490

1 of 1 task complete
@ncannasse

This comment has been minimized.

Copy link
Member

ncannasse commented Apr 17, 2018

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?

@bendmorris

This comment has been minimized.

Copy link

bendmorris commented Apr 18, 2018

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> and MyClass<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
    }
}
@bendmorris

This comment has been minimized.

Copy link

bendmorris commented Apr 18, 2018

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.

@ncannasse

This comment has been minimized.

Copy link
Member

ncannasse commented Apr 18, 2018

I don't think that it justify adding new syntax that is very specific to this case.

  • for metas you can already sur var _ : MyClass<String> and I think macro : MyClass<String> should maybe work as well. That's a good enough workaround
  • generic classes requires typedefs, but you can also implement a @:generic is or use macros to solve this problem

In 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.

@ncannasse

This comment has been minimized.

Copy link
Member

ncannasse commented Apr 18, 2018

@bendmorris

This comment has been minimized.

Copy link

bendmorris commented Apr 19, 2018

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.

@Simn

This comment has been minimized.

Copy link
Member

Simn commented Apr 30, 2018

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.

@back2dos

This comment has been minimized.

Copy link
Member

back2dos commented Apr 30, 2018

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.

@ncannasse

This comment has been minimized.

Copy link
Member

ncannasse commented May 1, 2018

I'm voting for a close until someone propose a better solution.

@bendmorris bendmorris closed this May 1, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment