www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Template mixins and selective imports

reply jmh530 <john.michael.hall gmail.com> writes:
I am trying to create a vectorize function that mixes in a new 
version of function with the same name that applies the function 
(to an ndslice).

The code below compiles without error and has the behavior I 
would expect.

However, when I change the function import to a selective import 
(e.g. from import std.math; to import std.math : sin;), then I 
get errors implying that the overload is not actually created.

Ideally, I would like to get this working with any kind of import.

One thing I noticed is that the fullyQualifiedName of sin changes 
quite a bit depending on whether you use one or the other.

This may be related to either of the following:
https://issues.dlang.org/show_bug.cgi?id=16287
https://issues.dlang.org/show_bug.cgi?id=16023



-----------------------------------

import std.traits : isFunction;

private enum _vectorize(string f) = "
     import mir.ndslice.slice : SliceKind, Slice;

     auto " ~ f ~ "(SliceKind kind, size_t[] packs, Iterator)
                                            (Slice!(kind, packs, 
Iterator) slice)
     {
         import mir.ndslice.topology : map;
         return slice.map!(f);
     }
";

mixin template vectorize(alias f)
     if (isFunction!f)
{
     mixin(_vectorize!(__traits(identifier, f)));
}

unittest
{
     import std.stdio : writeln;
     import mir.ndslice.slice : sliced;
     import mir.ndslice.topology : map;
     import std.math; //import std.math : sin;

     auto x = [0.0, 1.0, 2.0, 3.0].sliced;

     auto y = x.map!(sin);
     writeln(y);

     mixin vectorize!(sin);
     auto z = sin(x);
     writeln(z);
}
Aug 03 2017
parent reply Meta <jared771 gmail.com> writes:
On Thursday, 3 August 2017 at 15:29:47 UTC, jmh530 wrote:
 I am trying to create a vectorize function that mixes in a new 
 version of function with the same name that applies the 
 function (to an ndslice).

 The code below compiles without error and has the behavior I 
 would expect.

 However, when I change the function import to a selective 
 import (e.g. from import std.math; to import std.math : sin;), 
 then I get errors implying that the overload is not actually 
 created.

 Ideally, I would like to get this working with any kind of 
 import.

 One thing I noticed is that the fullyQualifiedName of sin 
 changes quite a bit depending on whether you use one or the 
 other.

 This may be related to either of the following:
 https://issues.dlang.org/show_bug.cgi?id=16287
 https://issues.dlang.org/show_bug.cgi?id=16023



 -----------------------------------

 import std.traits : isFunction;

 private enum _vectorize(string f) = "
     import mir.ndslice.slice : SliceKind, Slice;

     auto " ~ f ~ "(SliceKind kind, size_t[] packs, Iterator)
                                            (Slice!(kind, packs, 
 Iterator) slice)
     {
         import mir.ndslice.topology : map;
         return slice.map!(f);
     }
 ";

 mixin template vectorize(alias f)
     if (isFunction!f)
 {
     mixin(_vectorize!(__traits(identifier, f)));
 }

 unittest
 {
     import std.stdio : writeln;
     import mir.ndslice.slice : sliced;
     import mir.ndslice.topology : map;
     import std.math; //import std.math : sin;

     auto x = [0.0, 1.0, 2.0, 3.0].sliced;

     auto y = x.map!(sin);
     writeln(y);

     mixin vectorize!(sin);
     auto z = sin(x);
     writeln(z);
 }
I'm not 100% certain, but I believe you have to bring the vectorized overload of sin into the overload set, so first try `mixin vectorize!sin vsin; alias sin = vsin;` and see if it works. https://dlang.org/spec/function.html#overload-sets
Aug 03 2017
parent reply Meta <jared771 gmail.com> writes:
On Thursday, 3 August 2017 at 19:03:55 UTC, Meta wrote:
 `mixin vectorize!sin vsin; alias sin = vsin;` and see if it
Should be `alias sin = vsin.sin;`
Aug 03 2017
parent jmh530 <john.michael.hall gmail.com> writes:
On Thursday, 3 August 2017 at 19:05:47 UTC, Meta wrote:
 On Thursday, 3 August 2017 at 19:03:55 UTC, Meta wrote:
 `mixin vectorize!sin vsin; alias sin = vsin;` and see if it
Should be `alias sin = vsin.sin;`
Thanks, this pointed me in the right direction. I got the line below working. mixin vectorize!sin temp; alias vsin = temp.sin; auto z = vsin(x); I couldn't give it the name of sin or the name of the identifier. This is a little ugly and would require the user to make the adjustment themselves. Below seems to work if the user doesn't import the relevant function, though it will still result in errors if they selectively import that function. I think the combination of the two will be sufficient. private enum _vectorizeAlt(string mod, string func) = " auto " ~ func ~ "(SliceKind kind, size_t[] packs, Iterator) (Slice!(kind, packs, Iterator) slice) { import mir.ndslice.topology : map; return slice.map!(" ~ mod ~ "." ~ func ~ "); } "; mixin template vectorizeAlt(string mod, string func) { mixin("static import " ~ mod ~ ";"); import mir.ndslice.slice : SliceKind, Slice; mixin(_vectorizeAlt!(mod, func)); } unittest { import std.stdio : writeln; import mir.ndslice.slice : sliced; import mir.ndslice.topology : map; auto x = [0.0, 1.0, 2.0, 3.0].sliced; mixin vectorizeAlt!("std.math", "sin"); auto y = sin(x); }
Aug 03 2017