www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Is it possible to use tokens as template parameters?

reply rempas <rempas tutanota.com> writes:
Is it possible to do something like that?

```
mixin template lel(alias N, alias V) {
   auto N = V;
}

void main() {
   mixin lel!(name, "Hmmmm");
}
```

In this case, it would (if it was possible) get replaced with: 
`auto name = "Hmmmm";`
Is there something I'm missing?
Aug 14
next sibling parent reply Tejas <notrealemail gmail.com> writes:
On Saturday, 14 August 2021 at 11:23:12 UTC, rempas wrote:
 Is it possible to do something like that?

 ```
 mixin template lel(alias N, alias V) {
   auto N = V;
 }

 void main() {
   mixin lel!(name, "Hmmmm");
 }
 ```

 In this case, it would (if it was possible) get replaced with: 
 `auto name = "Hmmmm";`
 Is there something I'm missing?
You have to use mixins to achieve the desired effect. ```d mixin template lel(T, string N, string V) { mixin(T.stringof ~ " " ~N ~ " = " ~ V ~ ";"); } import std; void main(){ mixin lel!(string, "name", ` "hmmmm" `); writeln(name); } } ```
Aug 14
parent reply rempas <rempas tutanota.com> writes:
On Saturday, 14 August 2021 at 12:19:59 UTC, Tejas wrote:
 On Saturday, 14 August 2021 at 11:23:12 UTC, rempas wrote:
 Is it possible to do something like that?

 ```
 mixin template lel(alias N, alias V) {
   auto N = V;
 }

 void main() {
   mixin lel!(name, "Hmmmm");
 }
 ```

 In this case, it would (if it was possible) get replaced with: 
 `auto name = "Hmmmm";`
 Is there something I'm missing?
You have to use mixins to achieve the desired effect. ```d mixin template lel(T, string N, string V) { mixin(T.stringof ~ " " ~N ~ " = " ~ V ~ ";"); } import std; void main(){ mixin lel!(string, "name", ` "hmmmm" `); writeln(name); } } ```
The behavior I want to achieve is not having to enclose the word (tokens) in double quotes.
Aug 14
next sibling parent evilrat <evilrat666 gmail.com> writes:
On Saturday, 14 August 2021 at 13:50:52 UTC, rempas wrote:
 The behavior I want to achieve is not having to enclose the 
 word (tokens) in double quotes.
Then it is not possible. D is strictly hygienic in that regard. You either use explicit mixin or string paramter. It is possible to have it with alias by using std.meta ```Alias!"name_here"``` or similar short template like below, but both has same limitation, there is absolutely no way to get rid of quotes. ```d auto t(T) { enum t = T; } writeln("token".t); ```
Aug 14
prev sibling parent reply Alexandru Ermicioi <alexandru.ermicioi gmail.com> writes:
On Saturday, 14 August 2021 at 13:50:52 UTC, rempas wrote:
 The behavior I want to achieve is not having to enclose the 
 word (tokens) in double quotes.
The closest you can get is using q{mixed d code} syntax that is basically a string containing d code, and hence subject to some checkups, and ide highlighting. Though why do you need this? Regards, Alexandru
Aug 14
parent rempas <rempas tutanota.com> writes:
On Saturday, 14 August 2021 at 15:21:51 UTC, Alexandru Ermicioi 
wrote:
 On Saturday, 14 August 2021 at 13:50:52 UTC, rempas wrote:
 The behavior I want to achieve is not having to enclose the 
 word (tokens) in double quotes.
The closest you can get is using q{mixed d code} syntax that is basically a string containing d code, and hence subject to some checkups, and ide highlighting. Though why do you need this? Regards, Alexandru
I mean I don't... But I was just curious if that's possible. Using a constant would probably also work I guess.
Aug 14
prev sibling parent reply jfondren <julian.fondren gmail.com> writes:
On Saturday, 14 August 2021 at 11:23:12 UTC, rempas wrote:
 Is it possible to do something like that?

 ```
 mixin template lel(alias N, alias V) {
   auto N = V;
 }

 void main() {
   mixin lel!(name, "Hmmmm");
 }
 ```

 In this case, it would (if it was possible) get replaced with: 
 `auto name = "Hmmmm";`
 Is there something I'm missing?
When I was learning Rust I kept running into syntaxes like this in books and examples. The funny thing was that the latest versions of the libraries had all gotten rid of these macros. To be able to put something like `mime!(text/html)` in your code seemed cool, using Rust's token-based macros, but then it was more trouble than it was worth and the fad ended with prejudice. Your exact usage can be made to work: ```d enum prop { name, title, location, etc } enum { name, title, location, etc } mixin template lel(alias p, alias v) { import std.traits : hasMember; static assert(hasMember!(prop, p.stringof)); mixin("auto " ~ p.stringof ~ " = " ~ v.stringof ~ ";"); } void main() { import std.stdio : writeln; mixin lel!(name, "Hmmmm"); writeln(name); } ``` And how might this be more trouble than it's worth? 1. `name` is always a valid identifier prior to its definition, so rearranging your code can result in surprising behavior (`writeln(name) // oops this is 0`) without an error, not even a complaint about shadowing. 2. `v` is more limited in expression than you might think. For example, this fails: ```d auto x = 2; mixin lel!(name, &x); // variable `x` cannot be read at compile time x++; writeln(*name); // can only `*` a pointer, not a `int` ```
Aug 14
parent reply rempas <rempas tutanota.com> writes:
On Saturday, 14 August 2021 at 20:35:18 UTC, jfondren wrote:
 On Saturday, 14 August 2021 at 11:23:12 UTC, rempas wrote:
 [...]
When I was learning Rust I kept running into syntaxes like this in books and examples. The funny thing was that the latest versions of the libraries had all gotten rid of these macros. To be able to put something like `mime!(text/html)` in your code seemed cool, using Rust's token-based macros, but then it was more trouble than it was worth and the fad ended with prejudice. [...]
Makes sense. I also thought that Rust's macro_rules! were cool but I understand your point. Thanks a lot!
Aug 14
parent reply Daniel N <no public.email> writes:
On Sunday, 15 August 2021 at 05:47:34 UTC, rempas wrote:
 [...]
Makes sense. I also thought that Rust's macro_rules! were cool but I understand your point. Thanks a lot!
opDispatch can create strings, which can either be directly mixed in, or the generated string can be send to mixin templates. ```d import std; static struct Yay { string opDispatch(string name, T...)(T vals) { return q{ auto %s = 777; }.format(name); } } enum yay=Yay(); void main() { mixin(yay.magic); magic.writeln; } ```
Aug 15
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 8/15/21 1:40 AM, Daniel N wrote:

 static struct Yay
 {
      string opDispatch(string name, T...)(T vals)
I sometimes wish templates had opDispatch abilities. Then we could instantiate a template with a symbol and the the template could receive it as string just like the way it works for opDispatch. So, this could work: Flag!isCool isCool; instead of today's Flag!"isCool" isCool; Basically, it would still be a string parameter but the quotes need not be provided: template Flag(string tag) { // ... } I realize that this might hide some bugs but so does opDispatch, no? Ali
Aug 16
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 8/16/21 1:59 PM, Ali Çehreli wrote:
 On 8/15/21 1:40 AM, Daniel N wrote:
 
  > static struct Yay
  > {
  >      string opDispatch(string name, T...)(T vals)
 
 I sometimes wish templates had opDispatch abilities. Then we could 
 instantiate a template with a symbol and the the template could receive 
 it as string just like the way it works for opDispatch. So, this could 
 work:
 
    Flag!isCool isCool;
 
 instead of today's
 
    Flag!"isCool" isCool;
 
 Basically, it would still be a string parameter but the quotes need not 
 be provided:
 
 template Flag(string tag) {
    // ...
 }
 
 I realize that this might hide some bugs but so does opDispatch, no?
Well, aliases do work with operators, so.... ```d import std.typecons; struct S { alias opDispatch(string foo) = Flag!foo; } void main() { S.bar x; import std.traits; pragma(msg, fullyQualifiedName!(typeof(x))); // std.typecons.Flag!("bar") } ``` -Steve
Aug 16
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 8/16/21 12:37 PM, Steven Schveighoffer wrote:

 ```d
 import std.typecons;

 struct S
 {
      alias opDispatch(string foo) = Flag!foo;
 }

 void main()
 {
      S.bar x;
      import std.traits;
      pragma(msg, fullyQualifiedName!(typeof(x))); //
 std.typecons.Flag!("bar")
 }
 ```
Me no understand. :) I see it as an example of how opDispatch is privileged. It nicely parses a token and provides it as a string. Templates don't have that. I want to be able say std.typecons.Flag!foo f; instead of std.typecons.Flag!"foo" f; Ali
Aug 16
parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 8/16/21 5:45 PM, Ali Çehreli wrote:
 On 8/16/21 12:37 PM, Steven Schveighoffer wrote:
 
  > ```d
  > import std.typecons;
  >
  > struct S
  > {
  >      alias opDispatch(string foo) = Flag!foo;
  > }
  >
  > void main()
  > {
  >      S.bar x;
  >      import std.traits;
  >      pragma(msg, fullyQualifiedName!(typeof(x))); //
  > std.typecons.Flag!("bar")
  > }
  > ```
 
 Me no understand. :) I see it as an example of how opDispatch is 
 privileged. It nicely parses a token and provides it as a string. 
 Templates don't have that. I want to be able say
 
    std.typecons.Flag!foo f;
 
 instead of
 
    std.typecons.Flag!"foo" f;
Well, I mean it's just `.` instead of `!`. What's the big deal? ;) Honestly, I didn't expect this to work when I tried it, but I did know that aliases do work with operator overloads (a hugely cool feature). -Steve
Aug 16