Skip to content
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

[superseded] new macro for generic reflection: extractGeneric(Foo2[float, string], 0) is float #8554

Closed
wants to merge 2 commits into from

Conversation

timotheecour
Copy link
Member

@timotheecour timotheecour commented Aug 7, 2018

/cc @mratsim

  • this PR supports these:
Foo2[float, string].extractGeneric(0) is float
Foo2[float, string].extractGeneric(-1) is Foo2

in some contexts (IMO in most contexts), it's better to access generics by index rather than by name as mentioned by @mratsim here #8459 (comment)

I'm also not super fan of this because the "T" or "N" seems to come from nowhere

I also agree with that sentiment (see #8433 (comment)), mainly because it avoids polluting scope with a generics's parameters.

a user writing Foo.Bar may be expecting Bar(Foo) when in fact compiler interprets as accessing generic param Bar from generic type Foo.

@timotheecour timotheecour changed the title add extractGeneric: extractGeneric(Foo2[float, string], 0) is float new macro: extractGeneric(Foo2[float, string], 0) is float Aug 7, 2018
@timotheecour timotheecour changed the title new macro: extractGeneric(Foo2[float, string], 0) is float new macro for generic reflection: extractGeneric(Foo2[float, string], 0) is float Aug 7, 2018
Copy link
Collaborator

@mratsim mratsim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also solves #6454 (typetraits feature request - get subtype of a generic type).

This should be in typetraits not in sugar. Regarding name, since we have genericHead, maybe generic alone (or genericTail?) to match the naming.

Regarding signature, I feel like it should have a default value of 0:

macro extractGeneric*(T: typedesc, index:static[int] = 0): untyped =

@timotheecour
Copy link
Member Author

timotheecour commented Aug 7, 2018

  • I'd be ok with other names (actually genericParam seems even better) but I'd rather do the change just once; ok for genericParam ?
  • not documented, but typetraits is almost all magic procs currently; that being said I agree typetraits is better fit (options are
    typetraits, sugar, macros); ok for typetraits ?
  • typetraits.genericHead is currently magic; it's better IMO to minimize number of magic procs (easier to read/write/debug/extend etc), so (in another PR) I suggest we make genericHead(t) call this new macro, via extractGeneric(t, -1) and remove magic implementation from compiler core

Regarding signature, I feel like it should have a default value of 0:

that seems arbitrary esp in case generic has a number of params different from 1, if there's a default, it should be -1 which stands for Head, ie: extractGeneric(Foo[T0,T1]) would be Foo, not T0; ok for default of -1 ?

@zah
Copy link
Member

zah commented Aug 7, 2018

As an alternative, I've considered adding an indexing operator over the tuple type, which returns the respective element type:

(int, float)[1] is float

Then this feature may be more elegant if the API looks like this:

MyGenericType.genericParams[1]

Here, genericParams is a helper that returns a tuple type including all params.

@timotheecour
Copy link
Member Author

timotheecour commented Aug 7, 2018

As an alternative, I've considered adding an indexing operator over the tuple type

cool but can that happen sooner rather than later? I tried adding it as a proc but didn't work:

template `[]`*(T: typedesc): auto = #Error: no generic parameters allowed for Foo
  var ignore:T
  type(ignore[i])

import typetraits
let a=(1,"foo")
echo type(a)
type Foo=type(a)
echo Foo[0] # error

or should that be in "proc semArrGet(c: PContext; n: PNode; flags: TExprFlags): PNode =" ?
any help welcome to expedite this ;-)

EDIT one concern though: there obviously should be no runtime impact, but could that affect compile time / compile memory usage, if this is used extensively (even indirectly), whereby a whole type tuple (Foo,T0,T1) is returned instead of just the requested element?

@krux02
Copy link
Contributor

krux02 commented Nov 8, 2018

I have a different approach. I wrote a type normalization algorithm. You can see it here:
https://github.com/krux02/opengl-sandbox/blob/b539910bb7c5acf71a2acf1772f609f0ad0a0065/experiment/normalizeType.nim#L170

If I add this procedure to the macros library, it would solve this problem. The advantage here is that the result of the result of normalizeType is a type expression, it can be printed. It even handles aliases with generic arguments recursively.

@timotheecour
Copy link
Member Author

timotheecour commented Dec 4, 2018

ok I finally revived this PR and resolved conflicts; it's now hitting a regression unfortunately, see #9855

@krux02 normalizeType is indeeed useful (and should hopefully turn into a PR); however, this PR has a different goal that your approach doesn't address (IIUC): generic way to access (as-is) head Foo and arguments T0,T1,... of a generic type Foo[T1,T2,T2]
given type Bar = Foo[T1,T2,T2] I don't see how your approach get access to either Foo or, say, T2
So your approach and this PR are essentially orthogonal.

EDIT: hold on, I may see what you mean...

@krux02
Copy link
Contributor

krux02 commented Dec 4, 2018

@timotheecour when you normalize the type, you get a type expression of Foo[T1,T2,T2] and here you can simply access the members by index to get the generic arguments.

@Araq
Copy link
Member

Araq commented Feb 23, 2019

No RFC for this, in the wrong place and should use 0 instead of -1 for head. And then we need to maintain it and document all its edge cases. Rejected for now.

@Araq Araq closed this Feb 23, 2019
@mratsim
Copy link
Collaborator

mratsim commented Feb 25, 2019

There was a feature request though: #8554

@krux02
Copy link
Contributor

krux02 commented Feb 25, 2019

@mratsim I think you pasted the wrong link.

@timotheecour
Copy link
Member Author

@mratsim I think you pasted the wrong link.

=> #6454

@timotheecour timotheecour changed the title new macro for generic reflection: extractGeneric(Foo2[float, string], 0) is float [TODO] new macro for generic reflection: extractGeneric(Foo2[float, string], 0) is float Jan 6, 2020
@timotheecour timotheecour changed the title [TODO] new macro for generic reflection: extractGeneric(Foo2[float, string], 0) is float [superseded] new macro for generic reflection: extractGeneric(Foo2[float, string], 0) is float Jan 7, 2020
@timotheecour timotheecour mentioned this pull request Feb 17, 2020
@timotheecour timotheecour deleted the pr_extractGeneric branch March 6, 2020 09:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

typetraits feature request - get subtype of a generic type
5 participants