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

alias templates #21663

Closed
wants to merge 15 commits into from
Closed

alias templates #21663

wants to merge 15 commits into from

Conversation

metagn
Copy link
Collaborator

@metagn metagn commented Apr 13, 2023

closes nim-lang/RFCs#466, succeeds #20064

This is unlikely to break any code or need an adaptation period, so it's fine to not rush it. (I hope I am not delaying a new release by piling up PRs)

{.alias.} templates are templates that take no arguments and act like var/let/const/type symbols in that:

  • They cannot be overloaded
  • They are always called when used as a symbol, including as the address of a call expression, meaning foo() where foo is an alias template now means what foo()() would have meant before

This is a stricter definition than the one in #20064.

Normal templates and macros can still be called with the alias syntax under the same conditions as before, and these conditions are now computed at the template/macro declaration and saved into sfNoalias (reused symbol flag). If sfNoalias is included, then a template or macro cannot be called with the alias syntax. Currently this can also be triggered with the {.noalias.} pragma but this is not particularly necessary, just compatible with the implementation detail

The alias syntax now also works for types (for both types of templates/macros).

Potential future directions:

  • make deprecatedStmt use this and remove the final use of skAlias

@Araq
Copy link
Member

Araq commented Apr 13, 2023

My latest thoughts on this are: Why are nullary templates not automatically .alias? What harm would it cause?

@metagn
Copy link
Collaborator Author

metagn commented Apr 13, 2023

Should have been more clear (been having sleep problems), this is a different version from the old PR and the one exactly written in the RFC. I could write another RFC for this new version, though to me this seems like the natural conclusion.

The alias syntax is used very broadly and commonly mixed with normal call syntax so there's no good reason to remove it for templates in general, so I agree if that was your sentiment. This version circumvents the normal call syntax entirely with the annotation instead of soft allowing the alias syntax or whatever; and also completely cannot be overloaded.

This compiles with this PR and before:

template foo: int = 3
echo foo == foo() # true

But this doesn't compile with this PR:

template foo: int {.alias.} = 3
echo foo() # error: cannot call 3

There's a couple benefits with opting out of the call syntax:

  1. We can alias overloaded proc symbols without using varargs[untyped] and potentially getting interfered with by some overload. This feature apparently gets requested a lot (links from every symbol becomes 1st class; defines 0-cost lambda and aliases; generics/iterators/templates/etc can be passed to any routine #11992):

https://forum.nim-lang.org/t/5015
https://forum.nim-lang.org/t/1515
btbytes/nim-cookbook#21
https://www.reddit.com/r/nim/comments/5v2rgw/alias_echo_to_print/
https://forum.nim-lang.org/t/1810

  1. It can more faithfully mimic variables, types etc in things like byaddr or DSLs

Personally this feature isn't essential to me because 1. I don't really need or use proc aliases 2. my only issue with "mimicking" has been straight up bugs forcing the call syntax which have since been fixed

But it allows stuff people want for very little cost, is conceptually easier to grasp and remember than an unconstrained alias syntax imo (especially with the overloading limitations), simplifies code, gives good errors, maybe has performance benefit, and maybe more

I agree that no matter what some kind of nullary flag set at the template declaration automatically is good, it would save some computation (currently reusing sfNoalias for this negated)

@metagn metagn changed the title alias templates alias templates, fixes and improvements to existing alias syntax Apr 14, 2023
@Araq
Copy link
Member

Araq commented Apr 14, 2023

I don't want to see code like

  template minus: untyped {.alias.} = `-`
  assert minus(bar) == -15
  assert minus(bar, minus(bar)) == 30

It's obfuscation. You are supposed to use template minus(a, b): untyped = a - b; template minus(a): untyped = -a

These pure aliases are more of an anti-feature than a feature.

@metagn
Copy link
Collaborator Author

metagn commented Apr 14, 2023

I can split this patch again into the sfNoalias optimization (with or without {.noalias.} also working) + type fix + tests for the alias syntax, and maybe an RFC for the alias templates (this depends on the other patch anyway). It's just that this is the simplest and cheapest way by far to me to implement something commonly discussed.

If template minus: untyped is bad we can also force the body to be typed (thus disallowing the minus(a, minus(b)) stuff). The chief problem is in DSLs that generate template field: untyped = obj.field, when field is supposed to be a proc() people will have to do field()() instead of field() when they just use field normally. The redefinition error stuff is also unnecessary (fail safe instead of fail fast).

@metagn
Copy link
Collaborator Author

metagn commented Apr 14, 2023

Split off the uncontroversial stuff into #21671. Marking as draft instead of closing in case we come up with something better (like the typed thing)

@metagn metagn marked this pull request as draft April 14, 2023 23:03
@metagn metagn changed the title alias templates, fixes and improvements to existing alias syntax alias templates Apr 14, 2023
@metagn
Copy link
Collaborator Author

metagn commented Apr 16, 2023

Just closing for now, this is not a priority

@metagn metagn closed this Apr 16, 2023
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.

Pragma to mark symbol-imitating templates/macros
2 participants