Jump to page: 1 2
Thread overview
Scope of Mixins
Aug 26, 2021
DLearner
Aug 26, 2021
Paul Backus
Aug 26, 2021
Adam D Ruppe
Aug 26, 2021
DLearner
Aug 26, 2021
Adam D Ruppe
Aug 26, 2021
Ali Çehreli
Aug 26, 2021
Adam D Ruppe
Aug 26, 2021
Ali Çehreli
Aug 26, 2021
Adam D Ruppe
Aug 26, 2021
DLearner
Aug 26, 2021
Adam D Ruppe
August 26, 2021

Please confirm that mixins of format:

string mxn1(string VarName) {
    ...
}

Invoked like:

mixin(mxn1("Var1"));

Have a wider scope than mixins like:

string mxn2(string VarName)() {
   ...
}

Invoked like:

mixin(mxn2!"Var2");

I tried direct replacement of former by the latter, could not get clean compile until definition moved into same module.

Best regards

August 26, 2021

On Thursday, 26 August 2021 at 16:16:55 UTC, DLearner wrote:

>

Please confirm that mixins of format:

string mxn1(string VarName) {
    ...
}

Invoked like:

mixin(mxn1("Var1"));

Have a wider scope than mixins like:

string mxn2(string VarName)() {
   ...
}

Invoked like:

mixin(mxn2!"Var2");

If the strings produced by mxn1("Var1") and mxn2!"Var2" are the same, mixing them in will have the same result. mixin() does not care where the string you pass to it comes from.

>

I tried direct replacement of former by the latter, could not get clean compile until definition moved into same module.

Something you are doing in the body of the functions is causing this, but because you have not included function bodies in your post, I cannot tell you what.

August 26, 2021
On Thursday, 26 August 2021 at 16:16:55 UTC, DLearner wrote:
> Please confirm that mixins of format:

You really shouldn't use string mixins like this at all. If you want to work with a variable, pass the variable itself as an argument to the function and use it with regular code instead of passing names as strings.

void do_something(alias v)() {
   // use v like a normal variable
}

int a;
do_someting!a; // pass the variable a as an alias so you can use it inside

August 26, 2021
On Thursday, 26 August 2021 at 16:28:22 UTC, Adam D Ruppe wrote:
> On Thursday, 26 August 2021 at 16:16:55 UTC, DLearner wrote:
>> Please confirm that mixins of format:
>
> You really shouldn't use string mixins like this at all. If you want to work with a variable, pass the variable itself as an argument to the function and use it with regular code instead of passing names as strings.
>
> void do_something(alias v)() {
>    // use v like a normal variable
> }
>
> int a;
> do_someting!a; // pass the variable a as an alias so you can use it inside

The object was to take a variable, and do alternative things with it depending on (say) whether it was an 'int' or an 'int*'.
Since entirely possible (indeed likely) that operations on 'int' invalid or meaningless with 'int*', to me seemed better to find a way that at _compile-time_ detected the difference, and only generated code valid for the type used.

Originally, there were mixins that only coped with each type.
These work, but a chore to update mixin name as variable type changed.
So idea is just one mixin which can compile-time detect variable type
and generate appropriate code.
Got it to work, except for this scoping issue...

August 26, 2021
On Thursday, 26 August 2021 at 17:01:06 UTC, DLearner wrote:
> The object was to take a variable, and do alternative things with it depending on (say) whether it was an 'int' or an 'int*'.

That's *very* easy to do with the alias. You can just check `typeof(v)` in there.
August 26, 2021
On 8/26/21 10:06 AM, Adam D Ruppe wrote:
> On Thursday, 26 August 2021 at 17:01:06 UTC, DLearner wrote:
>> The object was to take a variable, and do alternative things with it depending on (say) whether it was an 'int' or an 'int*'.
> 
> That's *very* easy to do with the alias. You can just check `typeof(v)` in there.

String mixins are appealing because they can inject code like C macros do. It's not trivially possible to do the same with template mixins.

import std.traits : isPointer;
import std.stdio : writeln;

mixin template valueFrom(alias var)
if (isPointer!(typeof(var))) {
  writeln("Dereferencing a pointer");  // ERROR
  x = *var;
}

mixin template valueFrom(alias var)
if (!isPointer!(typeof(var))) {
  writeln("Using a scalar");           // ERROR
  x = var;
}

void main() {
  int x;
  int i = 42;
  mixin valueFrom!i;

  int * p = &i;
  mixin valueFrom!p;
}

Yes, there are tricks one can play or change the design but when it comes to "injecting code", template mixins are not as convenient as string mixins.

Ali
August 26, 2021
On Thursday, 26 August 2021 at 17:39:16 UTC, Ali Çehreli wrote:
> String mixins are appealing because they can inject code like C macros do. It's not trivially possible to do the same with template mixins.

Template mixins are great, but obviously totally inappropriate here. I'm just talking about using a normal function, possibly with an alias argument, instead of any kind of mixin.

Too often D programmers reach for fancy code generation when a simpler function is a better fit.
August 26, 2021
On 8/26/21 10:45 AM, Adam D Ruppe wrote:
> On Thursday, 26 August 2021 at 17:39:16 UTC, Ali Çehreli wrote:
>> String mixins are appealing because they can inject code like C macros do. It's not trivially possible to do the same with template mixins.
> 
> Template mixins are great, but obviously totally inappropriate here. I'm just talking about using a normal function, possibly with an alias argument, instead of any kind of mixin.
> 
> Too often D programmers reach for fancy code generation when a simpler function is a better fit.

Agreed. Something like the following for the OP:

import std.traits : isPointer;

auto valueFrom(T)(T var)
if (isPointer!(typeof(var))) {
  return *var;
}

auto valueFrom(T)(T var)
if (!isPointer!(typeof(var))) {
  return var;
}

void main() {
  int x;
  int i = 42;
  x = valueFrom(i);

  int * p = &i;
  x = valueFrom(p);
}

In some cases it's more useful to have a 'static if' inside a single function template instead of two separate function templates.

Ali

August 26, 2021
On Thursday, 26 August 2021 at 18:07:48 UTC, Ali Çehreli wrote:
> In some cases it's more useful to have a 'static if' inside a single function template instead of two separate function templates.

In most cases that's better. A template constraint is really a way to say "this template cannot accept this". When you use it to overload, the conditions get ugly fast since you need to make sure they're all mutually exclusive and the error messages get wrong since the compiler isn't sure if the thing can or can't be accepted.

What you generally want to do here is if the call - from the user's perspective - should work, make sure it gets through the constraint. Then do the details of branches inside.
August 26, 2021

On Thursday, 26 August 2021 at 16:28:22 UTC, Adam D Ruppe wrote:

>

On Thursday, 26 August 2021 at 16:16:55 UTC, DLearner wrote:

>

Please confirm that mixins of format:

You really shouldn't use string mixins like this at all. If you want to work with a variable, pass the variable itself as an argument to the function and use it with regular code instead of passing names as strings.

void do_something(alias v)() {
// use v like a normal variable
}

int a;
do_someting!a; // pass the variable a as an alias so you can use it inside

Thank you for your suggestion.
For the record, the code below behaves as expected.

void main() {

   int  VarInt;
   int* VarIntPtr;
   double VarDbl;

   do_something!VarInt;
   do_something!VarIntPtr;
   do_something!VarDbl;
}

void do_something(alias v)() {

   import std.stdio;

   if (typeof(v).stringof == "int" ) {

      writeln("int var detected");
   } else if (typeof(v).stringof == "int*") {

      writeln("int* var detected");
   } else {

      writeln("Unrecognised type");
   }
}
« First   ‹ Prev
1 2