www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Mixin and imports

reply jmh530 <john.michael.hall gmail.com> writes:
In the code below, foo!fabs compiles without issue, but 
foo!"fabs" does not because the import is not available in the 
string mixin. If I move the import to the top of the module, then 
it works. However, then if I move foo to another module, then it 
will no longer compile since it is in different modules.

Is there any way I can make sure the mixin knows about the import?

I am just using fabs as an example. Ideally, I would want to use 
any function from any other module. I can figure out how to do 
it, for instance, if the only functions that were allowed were 
those in one module, like std.math.

```
double foo(alias f)(double x) {
     return f(x);
}

template foo(string f) {
     mixin("alias foo = .foo!(" ~ f ~ ");");
}

void main() {
     import std.math: fabs;

     double x = 2.0;
     double y = foo!fabs(x);
     double z = foo!"fabs"(x);
}
```
Jun 07 2020
next sibling parent reply Mike Parker <aldacron gmail.com> writes:
On Monday, 8 June 2020 at 02:55:25 UTC, jmh530 wrote:
 In the code below, foo!fabs compiles without issue, but 
 foo!"fabs" does not because the import is not available in the 
 string mixin. If I move the import to the top of the module, 
 then it works. However, then if I move foo to another module, 
 then it will no longer compile since it is in different modules.

 Is there any way I can make sure the mixin knows about the 
 import?
The problem isn't the mixin. It's the template. Templates take the scope of their declaration, not their instantiation. So the mixin is getting the template's scope. Anyway, this appears to work: `double z = foo!"std.math.fabs"(x);`
Jun 07 2020
parent reply jmh530 <john.michael.hall gmail.com> writes:
On Monday, 8 June 2020 at 04:13:08 UTC, Mike Parker wrote:
 [snip]


 The problem isn't the mixin. It's the template. Templates take 
 the scope of their declaration, not their instantiation. So the 
 mixin is getting the template's scope.

 Anyway, this appears to work:

 `double z = foo!"std.math.fabs"(x);`
Thanks, that makes sense. However, I get the same error with the code below. Am I doing something wrong? double foo(alias f)(double x) { return f(x); } template foo(string f) { mixin("alias foo = .foo!(" ~ f ~ ");"); } void main() { static import std.math; double x = 2.0; double y = foo!(std.math.fabs)(x); double z = foo!"std.math.fabs"(x); }
Jun 08 2020
parent reply Paul Backus <snarwin gmail.com> writes:
On Monday, 8 June 2020 at 10:23:24 UTC, jmh530 wrote:
 On Monday, 8 June 2020 at 04:13:08 UTC, Mike Parker wrote:
 [snip]


 The problem isn't the mixin. It's the template. Templates take 
 the scope of their declaration, not their instantiation. So 
 the mixin is getting the template's scope.

 Anyway, this appears to work:

 `double z = foo!"std.math.fabs"(x);`
Thanks, that makes sense. However, I get the same error with the code below. Am I doing something wrong? double foo(alias f)(double x) { return f(x); } template foo(string f) { mixin("alias foo = .foo!(" ~ f ~ ");"); } void main() { static import std.math; double x = 2.0; double y = foo!(std.math.fabs)(x); double z = foo!"std.math.fabs"(x); }
If you want to refer to symbols in the scope where the template is instantiated, you will have to move the mixin outside of the template: double foo(alias f)(double x) { return f(x); } template foo(string f) { enum foo = "foo!(" ~ f ~ ")"; } void main() { import std.math: fabs; double x = 2.0; double y = foo!(fabs)(x); double z = mixin(foo!"fabs")(x); }
Jun 08 2020
parent reply jmh530 <john.michael.hall gmail.com> writes:
On Monday, 8 June 2020 at 10:28:39 UTC, Paul Backus wrote:
 [snip]
Thanks for that suggestion. That works for me. Unfortunately, it's probably not worth the extra effort though, versus doing foo!fabs in my case.
Jun 08 2020
parent FunkyD <MrFunky YourDaddy.com> writes:
On Monday, 8 June 2020 at 10:41:53 UTC, jmh530 wrote:
 On Monday, 8 June 2020 at 10:28:39 UTC, Paul Backus wrote:
 [snip]
Thanks for that suggestion. That works for me. Unfortunately, it's probably not worth the extra effort though, versus doing foo!fabs in my case.
If they are all from std.math you can easily mixin in the template. just import std.math there then it should work. If you want more general arbitrary functions you can get the module of the function by using an alias. Alternatively you can just pass the function itself as an alias or template parameter. There are ways to do what you want but it's kinda hacky. I can't remember the details though. Basically you use mixins and traits to get the module the symbol exists in and then you can use a string mixin to import that module.
Jun 08 2020
prev sibling next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Monday, 8 June 2020 at 02:55:25 UTC, jmh530 wrote:
 In the code below, foo!fabs compiles without issue, but 
 foo!"fabs" does not because the import is not available in the 
 string mixin.
Why do you even want foo!"fabs"? Usually when I see people having this problem it is actually a misunderstanding of what is possible with the foo!fabs style - which is better in basically every way and can be used in most the same places. So what's your bigger goal?
Jun 08 2020
parent jmh530 <john.michael.hall gmail.com> writes:
On Monday, 8 June 2020 at 12:20:46 UTC, Adam D. Ruppe wrote:
 [snip]

 Why do you even want foo!"fabs"? Usually when I see people 
 having this problem it is actually a misunderstanding of what 
 is possible with the foo!fabs style - which is better in 
 basically every way and can be used in most the same places.

 So what's your bigger goal?
There were some other functions in the module that allow the use of function!"thinginquotes". However, most of those functions are using the "thinginquotes" to avoid writing function!(SomeEnum.thinginquotes). That really isn't the thing to fix in this case. So I think it makes sense for me to give up what I was trying to do.
Jun 08 2020
prev sibling parent reply data pulverizer <data.pulverizer gmail.com> writes:
On Monday, 8 June 2020 at 02:55:25 UTC, jmh530 wrote:
 ```
 ...
 template foo(string f) {
     mixin("alias foo = .foo!(" ~ f ~ ");");
 }
...
 ```
Out of curiosity what does the "." in front of `foo` mean? I've seen that in some D code on the compiler in GitHub and have no idea what it does. I tried Googling it to no avail. It doesn't have anything to do with UFCS does it? Thanks
Jun 08 2020
next sibling parent ag0aep6g <anonymous example.com> writes:
On 08.06.20 16:27, data pulverizer wrote:
 Out of curiosity what does the "." in front of `foo` mean? I've seen 
 that in some D code on the compiler in GitHub and have no idea what it 
 does. I tried Googling it to no avail. It doesn't have anything to do 
 with UFCS does it?
https://dlang.org/spec/module.html#module_scope_operators
Jun 08 2020
prev sibling parent reply jmh530 <john.michael.hall gmail.com> writes:
On Monday, 8 June 2020 at 14:27:26 UTC, data pulverizer wrote:
 [snip]

 Out of curiosity what does the "." in front of `foo` mean? I've 
 seen that in some D code on the compiler in GitHub and have no 
 idea what it does. I tried Googling it to no avail. It doesn't 
 have anything to do with UFCS does it?

 Thanks
ag0aep6g provided the link to it, but it's one of those things that has been difficult for me to understand as well. I believe the original code had `foo` in a template. So in that case it was necessary. I'm not sure if it still is in my simplified version.
Jun 08 2020
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 6/8/20 11:11 AM, jmh530 wrote:
 On Monday, 8 June 2020 at 14:27:26 UTC, data pulverizer wrote:
 [snip]

 Out of curiosity what does the "." in front of `foo` mean? I've seen 
 that in some D code on the compiler in GitHub and have no idea what it 
 does. I tried Googling it to no avail. It doesn't have anything to do 
 with UFCS does it?

 Thanks
ag0aep6g provided the link to it, but it's one of those things that has been difficult for me to understand as well. I believe the original code had `foo` in a template. So in that case it was necessary. I'm not sure if it still is in my simplified version.
The dot operator simply specifies that the symbol you are looking for is defined at global scope, so it just changes the lookup rules. Even though it makes the code clearer what foo you are looking at, it was not necessary -- removing the dot works. In some cases it is necessary to use the . lookup rule, because you have another symbol that will be picked first. For example: int x; template bar(string x) { mixin("alias " ~ x ~ " = .x;"); } -Steve
Jun 08 2020
parent data pulverizer <data.pulverizer gmail.com> writes:
On Monday, 8 June 2020 at 16:02:02 UTC, Steven Schveighoffer 
wrote:
 On 6/8/20 11:11 AM, jmh530 wrote:
 On Monday, 8 June 2020 at 14:27:26 UTC, data pulverizer wrote:
 [snip]

 Out of curiosity what does the "." in front of `foo` mean? 
 [snip]
ag0aep6g provided the link to it [snip]
The dot operator simply specifies that the symbol you are looking for is defined at global scope, so it just changes the lookup rules. Even though it makes the code clearer what foo you are looking at, it was not necessary -- removing the dot works. In some cases it is necessary to use the . lookup rule, because you have another symbol that will be picked first. For example: int x; template bar(string x) { mixin("alias " ~ x ~ " = .x;"); } -Steve
Thanks both of you. It's one of those puzzling things that was at the back of mind that has just been resolved.
Jun 08 2020