mixin bug?

2016-08-11 Thread Engine Machine via Digitalmars-d-learn

template F1(T)
{
   void bar() { writeln("Bar0"); }
}

template F2(T)
{
   mixin F1!T;
   void foo() { bar(); }
}

template F3(T)
{
   mixin F2!T;
   void bar() { writeln("Bar1"); } // <- This bar should be used 
for F2's foo!


}

struct F4(T)
{
mixin F3!T;
}

(Or on can turn F3 in to a struct directly)


Then f3.foo() calls bar from F0, not F3's bar! This seems like a 
big bug! One expects the same behavior of mixins regardless of 
mixin nesting.


While you could argue that foo, when declared, is calling F0's 
bar, this is not consistent with the view that mixin templates 
only adds what is not there. I don't like the idea that calls are 
resolved first come first serve as it means one can't extend 
templates in a natural logical way.











Re: Template parameters that don't affect template type

2016-08-11 Thread Engine Machine via Digitalmars-d-learn

On Thursday, 11 August 2016 at 18:11:30 UTC, Engine Machine wrote:
I have the need, in some cases, to pass static information to a 
template class but don't want it to affect its type.


import std.algorithm, core.stdc.stdlib;
struct X(int defaultSize = 100)
{
   int Size;
   int* p;
   void foo(int size)
   {
Size = max(size, defaultSize);
p = cast(int*)malloc(Size);
   }
}

If I do

X!100 x;
X!100 y;
X!50 z;

then I can do

x = y;

but not

x = z;

but of course D things these are completely different types. 
The type it self does not depend on the default size.


While one could argue that it can be unsafe, in the my context, 
it is not.


Is there any way to get D to understand I want do not want a 
template parameter to be part of the type comparison?


I use several parameters to pass info to the type that does not 
change affect the type itself. It prevents the "same type" from 
being used with "itself".


another example:

struct s(T1, T2)
{
T1;
}

then

s!(int, double)

and

s!(int, float)

should really be the same type! The fact that T2 is not used is 
important!


I guess D just can't handle it though?


Another good example is if something like

template X(bool ClearMemory = false)
{

}

ClearMemory would clearly not affect the type if it just clears 
memory that is malloc'ed, yet D would treat treat X!true from 
X!false.




Template parameters that don't affect template type

2016-08-11 Thread Engine Machine via Digitalmars-d-learn
I have the need, in some cases, to pass static information to a 
template class but don't want it to affect its type.


import std.algorithm, core.stdc.stdlib;
struct X(int defaultSize = 100)
{
   int Size;
   int* p;
   void foo(int size)
   {
Size = max(size, defaultSize);
p = cast(int*)malloc(Size);
   }
}

If I do

X!100 x;
X!100 y;
X!50 z;

then I can do

x = y;

but not

x = z;

but of course D things these are completely different types. The 
type it self does not depend on the default size.


While one could argue that it can be unsafe, in the my context, 
it is not.


Is there any way to get D to understand I want do not want a 
template parameter to be part of the type comparison?


I use several parameters to pass info to the type that does not 
change affect the type itself. It prevents the "same type" from 
being used with "itself".


another example:

struct s(T1, T2)
{
T1;
}

then

s!(int, double)

and

s!(int, float)

should really be the same type! The fact that T2 is not used is 
important!


I guess D just can't handle it though?







Re: Template parameters that don't affect template type

2016-08-11 Thread Engine Machine via Digitalmars-d-learn
On Thursday, 11 August 2016 at 19:28:47 UTC, Lodovico Giaretta 
wrote:
On Thursday, 11 August 2016 at 18:11:30 UTC, Engine Machine 
wrote:

[...]


If, in your case, it is possible to use one type as the other, 
then specify it.
I mean, implement a templated opAssign that allows you to 
assign values of one instantiation to values of another. While 
doing so, remember that this will not change the behaviour of 
the assigned-to variable, but will only transfer the runtime 
state from one variable to the other.


struct S(T1, T2)
{
T1 t;
void opAssign(T)(auto ref S!(T1, T) other)
{
t = other.t;
}
}
unittest
{
S!(int, float) x(1);
S!(int, char) y(3);

x = y;
assert(x.t == 3);// the 
value of x is changed
static assert(is(typeof(x) == S!(int, float)))   // the 
type of x isn't changed

}


Ok, well, my point is that in some cases, the OpAssign is 
trivially since everything is copied. I guess being explicit is 
not a bad thing in this case though.





Re: Template parameters that don't affect template type

2016-08-11 Thread Engine Machine via Digitalmars-d-learn

Also, what if we use a class instead of a struct?

in this case they are both references to the same thing.

I see a problem with reflection though, as one could get the 
template parameter value and it would wrong on conversion. D 
takes the easy way out of just preventing complex and potentially 
ill-defined behavior, I guess that is ultimately a good thing, 
even if it makes it a pain in some cases.




Re: mixin bug?

2016-08-11 Thread Engine Machine via Digitalmars-d-learn

On Thursday, 11 August 2016 at 19:05:58 UTC, sldkf wrote:
On Thursday, 11 August 2016 at 17:56:47 UTC, Engine Machine 
wrote:

template F1(T)
{
   void bar() { writeln("Bar0"); }
}

template F2(T)
{
   mixin F1!T;
   void foo() { bar(); }
}

template F3(T)
{
   mixin F2!T;
   void bar() { writeln("Bar1"); } // <- This bar should be 
used for F2's foo!


}

struct F4(T)
{
mixin F3!T;
}

(Or on can turn F3 in to a struct directly)


Then f3.foo() calls bar from F0, not F3's bar! This seems like 
a big bug! One expects the same behavior of mixins regardless 
of mixin nesting.


While you could argue that foo, when declared, is calling F0's 
bar, this is not consistent with the view that mixin templates 
only adds what is not there. I don't like the idea that calls 
are resolved first come first serve as it means one can't 
extend templates in a natural logical way.


I don't think it's a bug. F3's bar() doesn't exist yet in F2. 
Logically F1's one is called.


Yes, but when we "mixin" again, bar then does exist. I see the 
mixin as a sort of copy and paste. We only paste in what doesn't 
exist. So the first time bar gets inserted in to F2, but then 
that bar doesn't get inserted in to F3 because it already exists.


Basically a mixin of a mixin is not logically a mixin. That makes 
no sense to me.


A mixin is suppose to behave a certain way, but when we do a 
mixin of a mixin we get behavior that doesn't behave the same way 
as a single mixin.



The language allows to alias a mixin so that a particular 
overload can be called. In you case you can really target 
F1.bar without problem:




I don't want to target F1.bar, I want foo to target future bar's.

It is like overloading, but for templates.

If you were doing overloading, and it called the base function 
instead, it wouldn't be overloading, would it?



°°°
template F1(T){void bar() {writeln("Bar0");}}

template F2(T)
{
   mixin F1!T FF1;
   void foo() { FF3.bar; }
}



This requires F2 to know the future. It also forces it to use a 
specific bar. I want inheritance like logic. Which is what we get 
when we mixin one deep, but when we go deeper, it breaks. I think 
this is a bug. It seems like D is trying to resolve things only 
after each mixin, rather than resolving after all nested mixins 
are evaluated.







Re: Template parameters that don't affect template type

2016-08-11 Thread Engine Machine via Digitalmars-d-learn
On Thursday, 11 August 2016 at 18:42:51 UTC, Steven Schveighoffer 
wrote:

On 8/11/16 2:11 PM, Engine Machine wrote:
I have the need, in some cases, to pass static information to 
a template

class but don't want it to affect its type.

import std.algorithm, core.stdc.stdlib;
struct X(int defaultSize = 100)
{
   int Size;
   int* p;
   void foo(int size)
   {
Size = max(size, defaultSize);
p = cast(int*)malloc(Size);
   }
}

If I do

X!100 x;
X!100 y;
X!50 z;

then I can do

x = y;

but not

x = z;

but of course D things these are completely different types. 
The type it

self does not depend on the default size.


And they should be different types. The code generated for the 
type is different, in this case it's important to declare these 
are not the same type.


For example, if x = y worked, then what should x.foo(5) do?

While one could argue that it can be unsafe, in the my 
context, it is not.


Is there any way to get D to understand I want do not want a 
template

parameter to be part of the type comparison?


The type is part of the template, and the instantiations are 
different. So no.


I use several parameters to pass info to the type that does 
not change
affect the type itself. It prevents the "same type" from being 
used with

"itself".


Then define how the compiler can convert from one to another. 
Or redesign the type to specify the parameters at the right 
time.



another example:

struct s(T1, T2)
{
T1;
}

then

s!(int, double)

and

s!(int, float)

should really be the same type! The fact that T2 is not used 
is important!


That's not how template types work.

your code is shorthand for:

template s(T1, T2)
{
   struct s
   {
  T1 t1; // I assume you wanted to put a member here?
   }
}

Two different instantiations of s create two different 
namespaces where the structs are not the same.




I don't think this proves anything. You just rewrote the 
template. T2 is still not used in either case and hence the type 
does not depend on it.


Basically your logic is something like: A = 0*5 is different than 
B = 0*6. But both are the same, just because they look different 
doesn't change that.


I'd suggest if you don't use a template parameter, don't 
declare it. If you use it in a member function only (as in your 
first example), declare it in the member function as a template 
parameter.



I guess D just can't handle it though?


No, it doesn't handle incorrect assumptions very well ;)

-Steve


You are misunderstanding what I am asking or saying.

The code may be different, but one reference can store the value 
of another. The type itself does not depend on the parameter.


X!100 x;
X!50 y;

50 for y does not change anything to the outside world about y.

So, for all practical purposes, we have

X x;
X y;

in which case we can do

x = y; with no problem.

You are confusing the general case with the specific case. Sure, 
in general, it doesn't work, we know that. But not all types are 
dependent on their type parameter. Just because such parameters 
are specified does not necessarily mean they should be different 
types.



My example is not good because the types are different. If I did 
something like


void foo(int size)
   {
   Size = max(size, defaultSize, 100);
p = cast(int*)malloc(Size);
   }


Then it would be different.

in this case X!50 and X!100 would be the same. X!101 would not.



Re: mixin bug?

2016-08-11 Thread Engine Machine via Digitalmars-d-learn

On Thursday, 11 August 2016 at 21:25:20 UTC, sldkf wrote:
On Thursday, 11 August 2016 at 20:27:01 UTC, Engine Machine 
wrote:
This requires F2 to know the future. It also forces it to use 
a specific bar. I want inheritance like logic.


You are goind to hit a wall. Template programming is not OOP.
I'm not even sure that reflection would work in order to 
determine the most "recent" overload.


Well, duh, it is not oop, but that doesn't mean it doesn't have 
similar abstractions, you need to read between the lines a bit 
more.


Which is what we get when we mixin one deep, but when we go 
deeper, it breaks. I think this is a bug. It seems like D is 
trying to resolve things only after each mixin, rather than 
resolving after all nested mixins are evaluated.


This is the only issue I see: "It seems like D is trying 
to...". We need to know exactly what D does: 
https://issues.dlang.org/show_bug.cgi?id=16376.


It would be nice if D would bind the function calls lazily, so to 
speak, that is all I'm saying. This way we can get 
polymorphic/oop like behavior, if you will.


template A(T)
{
void Bark() { writeln("Ruff Ruff"); }
}

template B(T)
{
mixin A!T;
void Talk() { Bark(); }
}

template Duck(T)
{
mixin B!T;
private void Bark() { writeln("Quack"); }
}


this is a contrived and misleading example if you take it 
seriously.


But Duck.Talk(); should Quack. It would if D resolved Bark from 
Talk after the final "mixin". (In Duck, not in B). Else we are 
stuck with a barking duck.


What it seems to do is first evaluate the template A!T, then B!T, 
then Duck!T. Since B!T is evaluated first and plugged in to Duck, 
Talk is already resolved to use A!T.Bark. Rather, If Duck!T was 
evaluated first, D would understand that Bark was already defined 
and when Talk was added, it could have it use the bark defined in 
duck, rather than A.


This, would, of course, require a sort of Duck!T.B!T type, since 
B!T used inside of Duck would have a different Talk() than if it 
is not used in Duck.


Again, maybe the compiler is just to ignorant to do this as it is 
complex(might require flow analysis and all that stuff or just be 
an ill-defined problem in general).








Re: mixin bug?

2016-08-11 Thread Engine Machine via Digitalmars-d-learn

On Thursday, 11 August 2016 at 21:03:36 UTC, Ali Çehreli wrote:

On 08/11/2016 01:27 PM, Engine Machine wrote:

> I see the mixin as a sort of copy and paste.

That's the case for string mixins. Template mixins bring a name 
resolution scope. My understanding of the topic:


  
http://ddili.org/ders/d.en/mixin.html#ix_mixin.name%20space,%20mixin


The spec:

  https://dlang.org/spec/template-mixin.html

Ali


"When a mixed-in name is the same as a name that is in the 
surrounding scope, then the name that is in the surrounding scope 
gets used:"


Which is my point, for "2nd order or higher" mixins, this does 
not occur.


The why I see it is that mixin template is sort of like a copy 
and paste, but only paste if the members do not exist 
already(i.e., the current behavior for "1st order" mixins. I 
would expect the same logic to hold for higher order mixins since 
a mixin of a mixin is still a mixin).


I realize why D behaves the way it does, but this is limiting. It 
simply greedily resolves referencing members rather than lazily. 
If the greedy method actually has some desired characteristic, 
then a lazy mixin would be nice.


lazy mixin T1!T;






Re: mixin bug?

2016-08-12 Thread Engine Machine via Digitalmars-d-learn

On Friday, 12 August 2016 at 23:48:54 UTC, sldkf wrote:

On Friday, 12 August 2016 at 23:14:23 UTC, Engine Machine wrote:

On Friday, 12 August 2016 at 15:35:50 UTC, sldkf wrote:
On Friday, 12 August 2016 at 02:09:21 UTC, Engine Machine 
wrote:

On Thursday, 11 August 2016 at 21:25:20 UTC, sldkf wrote:

On Thursday, 11 August 2016 at 20:27:01 UTC, Engine Machine


This is not the solution to the original problem.

template X(T)
{
  int _len = 0;
  int Length() { return _len; }
  int length(this T)() { return (cast(T)this).Length(); }
}

template Y(T)
{
  mixin X!T;
  int Length() { return 3; }
}


Then calling length returns 0, while calling Length returns 3. 
But we obviously want length to "follow" Length, yet it 
doesn't due to D resolving length in X before it is mixed in 
Y!T.


No "length" returns 3.

https://ideone.com/T8HjZl

Really, it's there, in front of your eyes.


You're right. My mistake. Thanks!

Do I have to do this with every function call? Seems a bit 
tedious to have to add this T to every function and add this. to 
every call.





Re: Template parameters that don't affect template type

2016-08-12 Thread Engine Machine via Digitalmars-d-learn

On Thursday, 11 August 2016 at 20:43:13 UTC, Meta wrote:
On Thursday, 11 August 2016 at 18:11:30 UTC, Engine Machine 
wrote:

[...]


It can be done, but you have to be explicit and should think 
very carefully if this is really a good design.


struct X(int defaultSize = 100)
{
int size;
int* p;

void foo(int size)
{
size = max(size, defaultSize);
p = cast(int*)malloc(size);
}

X opAssign(X2: X!n, int n)(X2 other)
{
//Do whatever you want here
}

X2 changeDefaultSize(int n)()
{
auto newX = X!n(n, p);
p = null; //Release ownership of p

return newX;
}
}

void takesX50(X!50 x)
{
//...
}

void main()
{
X!100 n;
X!100 m;
X!50 o;

n = m;
o = m;

takesX50(n); //Error
takesX50(n.changeDefaultSize!50); //Okay
}

Really though this problem is properly solved by runtime 
polymorphism.


Thanks. I am using templates and in some cases use template 
arguments to set compile time properties, hence runtime won't 
work.  These arguments don't affect the type itself, as far as 
the functionality/behavior as I use them.


Re: mixin bug?

2016-08-12 Thread Engine Machine via Digitalmars-d-learn

On Friday, 12 August 2016 at 15:35:50 UTC, sldkf wrote:

On Friday, 12 August 2016 at 02:09:21 UTC, Engine Machine wrote:

On Thursday, 11 August 2016 at 21:25:20 UTC, sldkf wrote:

On Thursday, 11 August 2016 at 20:27:01 UTC, Engine Machine


issue solved using a "template this parameter":

°°
template Cow()
{
void soundImpl() { writeln("moo"); }
}

template Cat()
{
mixin AnimalSound;
void soundImpl() { writeln("meaow"); }
}

template Duck()
{
mixin Cat;
void soundImpl() { writeln("quack"); }
}

template AnimalSound()
{
void emittSound(this T)() { (cast(T) this).soundImpl(); }
// would also work with "this.soundImpl()"
}

struct Animal
{
mixin Duck;
}

void main()
{
Animal a;
a.emittSound;
}
°°

https://dlang.org/spec/template.html#TemplateThisParameter


This is not the solution to the original problem.

template X(T)
{
  int _len = 0;
  int Length() { return _len; }
  int length(this T)() { return (cast(T)this).Length(); }
}

template Y(T)
{
  mixin X!T;
  int Length() { return 3; }
}


Then calling length returns 0, while calling Length returns 3. 
But we obviously want length to "follow" Length, yet it doesn't 
due to D resolving length in X before it is mixed in Y!T.





if static member then call

2016-08-13 Thread Engine Machine via Digitalmars-d-learn

auto ref foo(T, Args...)(args)
{
static if (hasStaticMember!(T, "foo"))
return T.foo!(T)(args);
}

Basically I want to forward the *static* call to T if possible(if 
foo exists in T). The main problem is actually calling T.foo as 
the syntax here doesn't work. I also need to be able to check to 
see if a method is static, since I have no object.





Re: Passing Structs to function like in C

2016-08-13 Thread Engine Machine via Digitalmars-d-learn

On Friday, 12 August 2016 at 18:23:55 UTC, Cauterite wrote:

Thanks colon-nazis, I'll take that into consideration ¬_¬


Be careful! They will cauterize your testicles and rape your 
children! Those semi-clone, I mean semi-colon-nazis are the worse 
kind!  It's a life and death matter! After all, `proper`(by 
section 8.043 of the penile nazile book of the dead) use of ';' 
is more important than your testicles anyways, right?








Re: Passing Structs to function like in C

2016-08-13 Thread Engine Machine via Digitalmars-d-learn

On Friday, 12 August 2016 at 17:53:12 UTC, ag0aep6g wrote:

On 08/12/2016 07:33 PM, Cauterite wrote:

Why would I not terminate a declaration with a semi-colon?
Why should a declaration not end in a semi-colon just because 
the last

token is a brace?
Why should I not tell the lexer precisely where my declaration 
ends
instead of relying on whatever other tokens floating around it 
not

interfering?


The semicolon is just noise. You're not helping the lexer at 
all. It goes by the braces, and doesn't see the semicolon as 
belonging to the function declaration. The semicolon creates 
another, empty declaration.


Then it should error if it doesn't accept ';'. If it accepts it 
then it is legal. Your post is noise since it also is relatively 
meaningless and just takes up space. Why is it no ok for him to 
add a noisy ';' but it is ok for you to add noise to noise by 
adding a noisy post?



This is accepted as well, and means the same:


;;;
void main() {}
;;;


Why must every thread in this forum contain more posts 
regarding some

irrelevant tangent than posts responding to the original topic?


This is a common mistake - more for structs, though, because of 
C syntax. So I point it out so that you can learn that there's 
no point to it in D, and so that others don't get the 
impression that it's the proper syntax.



It is not a mistake... only in your mind. If it was a mistake D 
wouldn't allow it. Somewhere you picked up the mistake that 
adding a semicolon to the end of a struct is a mistake. Maybe you 
should unlearn that mistake?


There is no point in a lot of things, but pretending that life 
depends on such trivial things is a much worse mistake, IMO.





Re: if static member then call

2016-08-13 Thread Engine Machine via Digitalmars-d-learn

On Saturday, 13 August 2016 at 18:42:50 UTC, Cauterite wrote:
On Saturday, 13 August 2016 at 18:34:43 UTC, Engine Machine 
wrote:

static if (hasStaticMember!(T, "foo"))


Here I suspect you're looking for this:
__traits(isStaticFunction, __traits(getMember, T, "foo"))


Thanks.

It needs to be something like

static if (hasMemeber!(T, "foo") && __traits(isStaticFunction, 
__traits(getMember, T, "foo")))





How to add nogc to delegate

2016-08-10 Thread Engine Machine via Digitalmars-d-learn

void foo(@nogc void delegate())

doesn't work.

But declaring an alias does, but too verbose. Surely we should be 
able to add the attribute directly?




Re: callback craziness

2016-08-07 Thread Engine Machine via Digitalmars-d-learn

On Sunday, 7 August 2016 at 23:02:26 UTC, ag0aep6g wrote:

On 08/08/2016 12:08 AM, Engine Machine wrote:

On Sunday, 7 August 2016 at 20:48:29 UTC, ag0aep6g wrote:

[...]
Delegates don't necessarily need a GC allocation. They only 
need it
when they need a closure. Delegates of methods don't need 
closures.
And when you pass the delegate in a `scope` parameter, no 
closure is

needed, either.


Well, one can't pick the case the delegate is passed. When I 
use a

delegate in the nogc context it errs.


Not exactly. When you do something that requires a closure, it 
errors out. As I said, a delegate doesn't always require the 
allocation of a closure.


This works just fine, and it uses a delegate parameter:


@nogc void foo(void delegate(int x) @nogc f) {}

void main() @nogc
{
foo((int x) {});

struct S
{
int y;
void f(int x) @nogc { this.y = x; }
}
S s;
foo();
}


But this doesn't compile, because the delegate here would need 
a closure:



@nogc void foo(void delegate(int x) @nogc f) {}

void main() @nogc
{
int y;
foo((int x) { y = x; });
}


Also note that it's main's @nogc that makes this fail, not 
foo's or the parameter's. Remove main's @nogc and it works.


[...]
You're missing an argument there. The second parameter of foo 
is

`args` which is `string` here. This call works:

foo!string((int x, string s) { }, "", 1);



Yeah, that was just a typeo obvious. That's not the reason it 
fails.


No. It's exactly the reason it fails. Add a string argument and 
it works:



alias callback(Args) = @nogc void function(int x, Args);
@nogc void foo(Args...)(callback!Args f, auto ref Args args, 
int extra = 0) {}


void main() @nogc
{
foo!string((int x, string s) { }, "", 1);
}


[...]
One thing you need to fix: The `callback` template needs a 
template
sequence parameter (i.e. `Args...`). Otherwise it takes 
exactly one type.


I did try that first and it didn't work. it works without ..., 
and I
figured that it is a template parameter and can also represent 
a

sequence?


No, without `...`, the template parameter only accepts exactly 
one type, not more than one, not none.



So, what about passing in the lambda verses the temp variable?

I tried the ... same problem as I said.

f!()(...) doesn't work.

Everything works find as long as I pass more than one variable.


My code is as follows and I cannot get 0 parameters working nor 
passing the function in directly. These were my original 
questions to begin with and haven't been answered. Here is the 
code I am using.


alias callback(Args...) = @nogc void function(string, int, Args);
@nogc public void foo(Args...)(callback!Args c, Args args, int x) 
{ }


foo((string s, int i) { }, 1);

does not work

nor does

foo!()((string s, int i) { }, 1);


Ultimately it would also be nice if the template parameters were 
deduced automatically instead of having to specify them. The 
compiler should be able to figure out the types supplied 
parameters.


e.g.,

foo((string s, int i, T x) { }, someT, 1);

instead of

foo!(T)((string s, int i, T x) { }, someT, 1);

should it not?







Cannot distinguish between template function wtih 0 args and 1 arg

2016-08-07 Thread Engine Machine via Digitalmars-d-learn

This really makes no sense

Error: template Mem cannot deduce function from argument types 
!(cast(eException)1280L, "main.d", 38u, "main.WinMain")(int), 
candidates are:
Mem(T, B = eX, string file = __FILE__, uint line = __LINE__, 
string func = __FUNCTION__)(size_t bytes)
Mem(T, B = eX, string file = __FILE__, uint line = __LINE__, 
string func = __FUNCTION__)()


Shouldn't these template functions be completely distinguished?

I tried to calling it with and without a value but same error. It 
is the only error.


This only occurs when I call it with the non-default template 
values:


I call it simply like Mem!(T, B, file, line, func)(34).

It seems if the template parameters match, that the compiler 
doesn't test the arguments.


Mem!T(34) works fine.






Re: callback craziness

2016-08-07 Thread Engine Machine via Digitalmars-d-learn

On Sunday, 7 August 2016 at 20:48:29 UTC, ag0aep6g wrote:

On 08/07/2016 10:01 PM, Engine Machine wrote:

@nogc void foo(void delegate(int x) @nogc f);

fails with the @nogc.


Compiles just fine for me.


2nd, I cannot use a delegate because of the @nogc context,


Delegates don't necessarily need a GC allocation. They only 
need it when they need a closure. Delegates of methods don't 
need closures. And when you pass the delegate in a `scope` 
parameter, no closure is needed, either.


Well, one can't pick the case the delegate is passed. When I use 
a delegate in the nogc context it errs.



[...]
So, to get around these problems, I have to do something like 
this:


alias callback(Args) = @nogc void function(int x, Args);
@nogc void foo(Args...)(callback!Args f, auto ref Args args, 
int extra = 0)


The problem with this is that I can't seem to add f inline:

foo!string((int x, string s) { }, 1);

this fails with template mismatch.


You're missing an argument there. The second parameter of foo 
is `args` which is `string` here. This call works:


foo!string((int x, string s) { }, "", 1);



Yeah, that was just a typeo obvious. That's not the reason it 
fails.



But if I define the lambda outside it works:

auto f = (int x, string s) { };
foo!string(f, 1);


Doesn't work for me. Still missing the string argument.



Yes, same typo.


The problem with this is that when I want to pass no arguments,

auto f = (int x) { };
foo(f, 1);

fails. It seems that Args... requires at least one argument to 
match the

template? This may be a bug?


One thing you need to fix: The `callback` template needs a 
template sequence parameter (i.e. `Args...`). Otherwise it 
takes exactly one type.


I did try that first and it didn't work. it works without ..., 
and I figured that it is a template parameter and can also 
represent a sequence? But I only tried with one argument so it 
worked.


I added ... but same problems.

That doesn't make it work, though. You also need to add empty 
template instantiation parentheses (i.e. `foo!()`), and you 
need to remove `auto ref` from the `args` parameter.


No idea why it doesn't work with `auto ref`. At least that part 
looks like a bug to me.



Yeah, so, this is typically what happens. One bug makes me change 
my tail for two hours ;/


callback craziness

2016-08-07 Thread Engine Machine via Digitalmars-d-learn

I use callbacks a lot and have trouble with D in a nogc context.

First, I cannot declare the parameters with a nogc or I get a 
compile time error.


@nogc void foo(void delegate(int x) @nogc f);

fails with the @nogc.

2nd, I cannot use a delegate because of the @nogc context,

@nogc void foo(void function(int x) f);

Works, but f then cannot access the context.

So, to get around these problems, I have to do something like 
this:


alias callback(Args) = @nogc void function(int x, Args);
@nogc void foo(Args...)(callback!Args f, auto ref Args args, int 
extra = 0)


The problem with this is that I can't seem to add f inline:

foo!string((int x, string s) { }, 1);

this fails with template mismatch.

But if I define the lambda outside it works:

auto f = (int x, string s) { };
foo!string(f, 1);

The problem with this is that when I want to pass no arguments,

auto f = (int x) { };
foo(f, 1);

fails. It seems that Args... requires at least one argument to 
match the template? This may be a bug?



alias callback(Args) = @nogc void function(string, int, Args);
@nogc public void foo(Args...)(callback!Args c, auto ref Args 
args, int extra = 0)

{
   ...
}

auto f = (string s, int l) @nogc
{
printf("%s\n", s.ptr);
};
foo(f, 1);

or

auto f = (string s, int l, string x) @nogc
{
printf("%s\n", x.ptr);
};
foo!string(f, "Test string", 1);

which is the case that work sin mine code. But I don't always 
want to have to pass stuff.


Any ideas? I realize the code is messy. You'll have to read 
between the lines.




So, the two problems I have is that I would like to be able to 
add a @nogc callback inline and to be able to pass no arguments.





I thought mixins didn't override?

2016-08-09 Thread Engine Machine via Digitalmars-d-learn
I try to use a mixin template and redefine some behaviors but D 
includes both and then I get ambiguity. I was sure I read 
somewhere that when one uses mixin template it won't include what 
is already there?


mixin template X
{
   void foo() { }
}

struct s
{
   mixin template
   void foo() { }
}

I was pretty sure I read somewhere that D would not include the 
foo from the template since it already exists.





Sequence separation

2016-08-16 Thread Engine Machine via Digitalmars-d-learn

alias x = AliasSeq!(a, b, AliasSeq!(c, d));

results in a flat sequence. I would like to be able to keep them 
separate so I can have sub sequences.


x.length == 4;




Re: Template type reduction

2016-08-16 Thread Engine Machine via Digitalmars-d-learn
On Tuesday, 16 August 2016 at 17:39:14 UTC, Lodovico Giaretta 
wrote:

On Monday, 15 August 2016 at 19:31:14 UTC, Engine Machine wrote:

Suppose I have a templated type like

struct S(T) { int x; static if (T is Y) int y; }

I would like to be able to create a reference to S(T) for any 
T,


struct Q
{
  S!* s; // Can hold any type of S.
}

and be able to access s.x, since it is common to all S.

Can D do anything like this? It is sort of like runtime 
inheritance, but at the compile time level.


I do not want to have to cast to S!T every time just to access 
x, e.g.,


struct Q
{
   Object s;
}

which is too general as s can be things that are not of type 
S!*.



Is this possible?


I don't know if this is exactly what you want:

=
import std.traits: hasMember;

struct Q(T)
if (hasMember!(T, "x"))
{
T s;

@property auto x() { return s.x; }
}
auto makeQ(T)(auto ref T val)
{
return Q!T(val);
}

auto s = myTypeWithFieldX();
auto q = makeQ(s);
assert(q.x == s.x);
=

`Q` can store any type with an `x` field and gives access to 
it. The auxiliary function `makeQ` acts as a constructor for 
`Q` with template parameter deduction.


The only problem is Q is still defined by T. Your makeQ then 
requires the type implicitly, which I don't necessarily have. 
You've simply added complexity to the problem but the issue is 
still there.


I realize now that D simply cannot do what I ask directly because 
It's type parameters are part of the type. It can't be told that 
in some cases they are not. Any use of the parameters, as I am 
using them, will result in this issue.


I'm now trying a different method which builds the based types 
using partial oop and partial CT code. The CT code is only for 
performance and convenience anyways.







Re: Heterogeneous CT array like structure

2016-08-16 Thread Engine Machine via Digitalmars-d-learn

On Tuesday, 16 August 2016 at 15:56:18 UTC, Adam D. Ruppe wrote:
On Tuesday, 16 August 2016 at 15:40:19 UTC, Engine Machine 
wrote:
How can I actually store this data for runtime use that 
doesn't require the GC?


The indexing set is fixed at compile time.


Just create an ordinary struct...


You could even create one  from code flow at compile time.



string magic(string structName) {
import std.conv;
struct Value {
string name;
string type;
string value;
}
struct Magic {
Value[] values;
void opDispatch(string name, T)(T value) {
values ~= Value(name, T.stringof, to!string(value));
}

string toCodeString() {
string s;
s ~= "struct " ~ structName ~ " {\n";

foreach(value; values) {
s ~= "\t";

s ~= value.type;
s ~= " ";
s ~= value.name;
s ~= " = ";
if(value.type == "string")
s ~= "`" ~ to!string(value.value) ~ "`";
else
s ~= to!string(value.value);

s ~= ";\n";
}

s ~= "}";
return s;
}
}

Magic magic;

magic.a = 10;
magic.b = "cool";

return magic.toCodeString();
}

pragma( msg, magic("MagicStruct"));
mixin(magic("MagicStruct"));

void main() {
MagicStruct ms;
import std.stdio;
writeln(ms.a);
writeln(ms.b);
}


This seems like a long winded way of just creating a struct in 
the first place, which might bet the simplest way anyways.


What I am trying to do is create preferences for my app:

if (Preferences.EnableHQ)
 ...

But I don't want to have to define EnableHQ at the point of use! 
This may be impossible since D doesn't know the type, although I 
could do if (Preferences.EnableHQ!bool) or something like that.


Anyways, I want to just be able to create preferences on the fly 
in the code when I feel like I need one without having to do 
anything else like go edit a struct, etc. Then, later, I can go 
deal with that.


What I was thinking I could do is, is use opDispatch, write any 
calls to it to a file. Then use import to import that file in to 
the struct. It would be the data(like static bool EnableHQ = 
false).


Eventually opDispatch should never be called, which can easily be 
checked and I can import the file by handle and make changes if 
necessary.


The problem with this method is it requires multiple passes and 
not extensible.


Have any better ideas?

All this is just trying to be lazy. I could just edit a struct 
and add the variables as I create them.









Re: Template type reduction

2016-08-15 Thread Engine Machine via Digitalmars-d-learn
On Monday, 15 August 2016 at 19:40:37 UTC, Steven Schveighoffer 
wrote:

On 8/15/16 3:31 PM, Engine Machine wrote:

Suppose I have a templated type like

struct S(T) { int x; static if (T is Y) int y; }

I would like to be able to create a reference to S(T) for any 
T,


struct Q
{
  S!* s; // Can hold any type of S.
}

and be able to access s.x, since it is common to all S.

Can D do anything like this? It is sort of like runtime 
inheritance, but

at the compile time level.


I don't think so. You'd have to cast, as the compiler doesn't 
have any understanding that all S instantiations will have an x 
member.


This is a problem. How can I cast to something I don't know?



I do not want to have to cast to S!T every time just to access 
x, e.g.,


struct Q
{
   Object s;
}

which is too general as s can be things that are not of type 
S!*.


This seems odd. You will lose the type information for s if you 
were to succeed. Might as well just store an int.


Seems like what you want is a variant or some other kind of 
tagged union.


No, what I want is a type that is the intersection of all the 
types it can be.


The problem is I cannot cast because the type is complex and I 
don't know the exact signature, but I do know that it has a basic 
type embedded in it.


enum Types
{
   Int, Word, Complex
}

struct MyType(string name, Types type, Args...)
{
string Name = name;
Types Type = type;
static if (type == Int) int val;
static if (type == word) ushort val;
static if (type == Complex) { ... };
}


So, how can I get val? I know if it is an int or a word, val 
exists. But I can't specify the name or type at runtime to get at 
the innards of the type.


Object o = MyType!("test", Types.Int);

Useless! I can never retrieve anything from o. I can't cast it 
back. Yet I know that o has a name and a type and possibly a val 
if I know the type... and I know all this at compile time. Yet D 
doesn't seem to allow me to use this information.


I know one will say use either oop or constructors, but neither 
of these are appropriate(although constructors are close). What I 
need is a type constructor, which bridges the gap. This is how I 
am using the data above, to construct the object, but D treats it 
as part of the type, which I don't what.


I guess I will have to use string mixins to construct the types 
properly ;/ What a pain in the ass ;/








Template type reduction

2016-08-15 Thread Engine Machine via Digitalmars-d-learn

Suppose I have a templated type like

struct S(T) { int x; static if (T is Y) int y; }

I would like to be able to create a reference to S(T) for any T,

struct Q
{
  S!* s; // Can hold any type of S.
}

and be able to access s.x, since it is common to all S.

Can D do anything like this? It is sort of like runtime 
inheritance, but at the compile time level.


I do not want to have to cast to S!T every time just to access x, 
e.g.,


struct Q
{
   Object s;
}

which is too general as s can be things that are not of type S!*.


Is this possible?



Re: Sequence separation

2016-08-17 Thread Engine Machine via Digitalmars-d-learn
On Wednesday, 17 August 2016 at 08:37:32 UTC, Lodovico Giaretta 
wrote:

On Tuesday, 16 August 2016 at 23:18:28 UTC, Adam D. Ruppe wrote:
On Tuesday, 16 August 2016 at 19:17:27 UTC, Engine Machine 
wrote:

alias x = AliasSeq!(a, b, AliasSeq!(c, d));

results in a flat sequence. I would like to be able to keep 
them separate so I can have sub sequences.


wrap them in a struct.


You mean something like:

struct MySequence(Args...)
{
enum length = Args.length;
alias args = Args;
}

alias x = MySequence!(a, b, MySequence!(c, d));

static assert(x.length == 3)
static assert(x.args[2].length == 2);


Thanks, basically works.

How can I test, though, if a argument uses a MySequence? I can't 
do if (Args[0] == MySequence) because MySequence is templated. 
While I could test for a length, that doesn't work because some 
types have a length. I could add another enum to MySequence, but 
again, not safe.


I could do some string tests, but that doesn't work.

in your exmaple,

if (x.args[2] == MySequence) ??

I simply need to differentiate between a parameter/arg being a 
MySequence and not.






Static CT Factory

2016-08-18 Thread Engine Machine via Digitalmars-d-learn
I have a template that is suppose to create a type based on a 
template parameter


static if (T == "int")
{
   auto x = New!int();
}
else static if (T == "double")
{
   auto x = New!double();
}

x = 1.234;


This is just an example, I use custom types.

The static if's prevent x's scope from being after them, even 
though it should work perfectly fine. I can't declare x before 
because I don't know the type.


The point is that I don't want to have to put x = 1.234; in each 
static if block when I should be able to do it perfectly fine 
afterwards.


My types that I'm creating all have a name field and I want to 
set it once after the object is created.


Luckily, all of them inherit from the same type and I can declare 
that before the static if block, but in general, that won't work.


I feel that in this case I feel that the scope of the static if 
should allow things to escape since, well, they are static if's. 
It would be similar to #ifdef.


I realize that D doesn't work this way, I'm asking for a nicer 
solution than having to duplicate the same code(x = 1.234 in this 
example) or having use a base class.




Re: Rebind template(bug?)

2016-08-21 Thread Engine Machine via Digitalmars-d-learn

On Sunday, 21 August 2016 at 06:28:25 UTC, Jack Applegame wrote:

On Sunday, 21 August 2016 at 00:06:07 UTC, Engine Machine wrote:

On Saturday, 20 August 2016 at 22:21:00 UTC, ag0aep6g wrote:

On 08/21/2016 12:11 AM, Engine Machine wrote:

Is there a way to rebind the arguments of a template?

template foo(X)
{
   // X is like A!(a,b,c)
   Y = Rebind!(X,d,e,f);
   // Y is like A!(d,e,f);
}

foo(A!(a,b,c));

?


template Rebind(alias instance, newArgs...)
{
import std.traits: TemplateOf;
alias tmpl = TemplateOf!instance;
alias Rebind = tmpl!newArgs;
}


This doesn't work because the rebound type is of type tmpl and 
not the original


e.g.,

Rebind!(T!b, a)

is tmpl!a not T!a.


You are wrong. tmpl is just alias of template T. So tmpl!a and 
T!a are the same type.


alias X = T!(int, short, char);
alias Y = Rebind!(X, short, char, int);
static assert(is(Y == T!(short, char, int))); // passes


I know you like to play the right or wrong game, but did you ever 
learn that a single example does not prove the truth of something?


How about something more complex?

import std.stdio;
import std.meta, std.traits;

class base { }

template Rebind(alias instance, newArgs...)
{
import std.traits: TemplateOf;
alias tmpl = TemplateOf!instance;
static if (newArgs.length > 0)
alias Rebind = tmpl!newArgs;
else
alias Rebind = base;
}

template EraseLast(A...)
{
static if (A.length > 0)
alias EraseLast = Erase!(A[$-1], A);
else
alias EraseLast = base;
}



class T(A...) : Rebind!(T!A, EraseLast!A)
{
int x;
static if (A.length > 0 && A[0] == "Animal")
{
int y;
static if (A.length > 1 && A[1] == "Dog")
{
int z;
static if (A.length > 2 && A[2] == "Pug")
int s;
}

}
}


pragma(msg, is(T!("Animal", "Dog", "Pug") : T!("Animal", "Dog")));
pragma(msg, is(T!("Animal", "Dog", "Pug") : T!("Animal")));
pragma(msg, is(T!("Animal", "Dog", "Pug") : base));
pragma(msg, is(T!("Animal", "Dog") : T!("Animal")));
pragma(msg, is(T!("Animal", "Dog") : base));
pragma(msg, is(T!("Animal") : base));

// all true



void main()
{
auto t = new T!("Animal", "Dog", "Pug")();
T!("Animal", "Dog") q = t;
//T!("Animal", "Dog", "Pug") q = t; works but then q is 
not the super of t

t.x = 3;
t.y = 4;
t.z = 6;
t.s = 123;

q.y = 1;
writeln(t, ", ", typeof(t).stringof);
writeln(q, ", ", typeof(q).stringof);
writeln("---");
writeln(t.x);
writeln(t.y);
writeln(t.z);
writeln(t.s);
writeln("---");
writeln(q.x);
writeln(q.y);
writeln(q.z);
writeln("---");
writeln(t.y);
writeln("---");
writeln();
writeln();

}

Since the pragma's are true, it is obvious that the inheritance 
should work chain works. Yet q is not a reference to t as it 
should be, why is this? If aliases were truly aliases as you 
think(your generic response) then it should work because rebind 
and erase only use aliases.













Re: Rebind template(bug?)

2016-08-21 Thread Engine Machine via Digitalmars-d-learn
On Sunday, 21 August 2016 at 19:42:08 UTC, Lodovico Giaretta 
wrote:

On Sunday, 21 August 2016 at 19:29:26 UTC, Engine Machine wrote:

[...]


The problem of this code has nothing to do with aliases. They 
work correctly. The problem is variable shadowing. In the 
following code, Child has two x variables, one of which is only 
accessible from a Parent reference, the other only from a Child 
reference.


class Parent
{
int x;
}
class Child: Parent
{
int x; // this shadows Parent.x
int y;
}

void main()
{
Child child = new Child();
Parent parent = child;

child.x = child.y = 3;
parent.x = 2;

assert(child.x == 3);
assert((cast(Child)parent).x == 3);
assert((cast(Parent)child).x == 2);

assert(parent is child); // same object (remember that a 
class is already a pointer);
assert( != ); // but there are two different 
pointers on the stack (pointing to the same object)

}


You're right. I didn't realize that variables could be shadowed 
in classes. Seems dangerous. D doesn't allow shadowing in a 
normal context and gives an error so I don't know why it wouldn't 
do that in classes. (since it wasn't giving an error I thought it 
wasn't shadowing)







Re: Rebind template(bug?)

2016-08-21 Thread Engine Machine via Digitalmars-d-learn

On Sunday, 21 August 2016 at 21:11:37 UTC, ag0aep6g wrote:

On 08/21/2016 09:29 PM, Engine Machine wrote:
I know you like to play the right or wrong game, but did you 
ever learn

that a single example does not prove the truth of something?


But you can show in a single example that something doesn't 
work. You tried to do that, and you did it with a simple 
example, which is always appreciated. But apparently, you were 
wrong. Happens to the best. And when the compiler prints 
"tmpl!a" that's indeed a little misleading.


You being wrong there doesn't mean that the Rebind template as 
I posted it works correctly, of course. But Jack didn't claim 
that. He just said that your example for how it doesn't work is 
wrong. And as far as I see, Rebind does work as expected. But I 
wouldn't be surprised if there is some edge case where things 
fall apart.


Also, if you're looking for help or civil discussion, I suggest 
you try a less antagonistic approach. Things like "I know you 
like to [play games]" and "did you ever learn [whatever]" do 
not set the tone for that.



How about something more complex?

import std.stdio;
import std.meta, std.traits;

class base { }


Style nitpick: Class names in PascalCase, please.


template Rebind(alias instance, newArgs...)
{
import std.traits: TemplateOf;
alias tmpl = TemplateOf!instance;
static if (newArgs.length > 0)
alias Rebind = tmpl!newArgs;
else
alias Rebind = base;
}

template EraseLast(A...)
{
static if (A.length > 0)
alias EraseLast = Erase!(A[$-1], A);


This line can be simplified: alias EraseLast = A[0 .. $ - 1];


else
alias EraseLast = base;


This is quite surprising for a template that's called 
"EraseLast". I renamed it to "EraseLastOrBase" for myself when 
looking at this.



}



class T(A...) : Rebind!(T!A, EraseLast!A)


The core idea of Rebind isn't needed here, is it? You've got T, 
so you can just pass it directly. No need to extract it from 
T!A.


So, instead of using some form of Rebind, you can use a simpler 
template:



/* Instantiates tmpl with args, or if no args given, returns 
base. */

template InstantiateOrBase(alias tmpl, args ...)
{
static if (args.length == 0) alias InstantiateOrBase = base;
else alias InstantiateOrBase = tmpl!args;
}

class T(A...) : InstantiateOrBase!(T, EraseLast!A)



{
int x;


Note that this means that every instantiation of T brings its 
own x. That is, T!foo declares an x, and T!(foo, bar) which 
inherits from T!foo adds another x. The same happens with y, z, 
and s, of course.



static if (A.length > 0 && A[0] == "Animal")
{
int y;
static if (A.length > 1 && A[1] == "Dog")
{
int z;
static if (A.length > 2 && A[2] == "Pug")
int s;
}

}
}


pragma(msg, is(T!("Animal", "Dog", "Pug") : T!("Animal", 
"Dog")));

pragma(msg, is(T!("Animal", "Dog", "Pug") : T!("Animal")));
pragma(msg, is(T!("Animal", "Dog", "Pug") : base));
pragma(msg, is(T!("Animal", "Dog") : T!("Animal")));
pragma(msg, is(T!("Animal", "Dog") : base));
pragma(msg, is(T!("Animal") : base));


Asserts are great to show that something holds. When someone 
like me makes changes to your code in order to understand it, 
the complier throws a nice loud error in their face when they 
mess up. So I changed these to static asserts for myself.



// all true



void main()
{
auto t = new T!("Animal", "Dog", "Pug")();
T!("Animal", "Dog") q = t;
//T!("Animal", "Dog", "Pug") q = t; works but then q 
is not the

super of t
t.x = 3;
t.y = 4;
t.z = 6;
t.s = 123;

q.y = 1;
writeln(t, ", ", typeof(t).stringof);
writeln(q, ", ", typeof(q).stringof);
writeln("---");
writeln(t.x);
writeln(t.y);
writeln(t.z);
writeln(t.s);
writeln("---");
writeln(q.x);
writeln(q.y);
writeln(q.z);
writeln("---");
writeln(t.y);
writeln("---");
writeln();
writeln();

}

Since the pragma's are true, it is obvious that the 
inheritance should
work chain works. Yet q is not a reference to t as it should 
be, why is

this?


It would help a lot if you would point out what parts of the 
output are surprising to you. If you let the reader figure it 
out themselves, chances are 1) people are not going to bother, 
and 2) if they do bother, they might miss your point.


Labeling the output also helps. By that I mean, if you write 
`writeln("t.x: ", t.x);`, the output can be read much more 
easily. I also think that you could have made your point with 
less output, which would again make it easier to follow. That 
is, just looking t.x/q.x would have been enough, no?


I guess you expect q.x and friends to be the same as t.x and 
friends. And since you put it there, you may also expect  to 
be the same as 


About the members being different: That's because every 
instantiation brings its own x/y/z, as mentioned above. 
Lodovico has 

Re: Rebind template(bug?)

2016-08-21 Thread Engine Machine via Digitalmars-d-learn

On Monday, 22 August 2016 at 00:22:48 UTC, ag0aep6g wrote:

On 08/22/2016 12:06 AM, Engine Machine wrote:

T!()'s "data" is specified in the class just like all the other
derivations. I don't want to have to specify an external base 
class as
in your InstaniateOrBase. Why? Because!!! (There should be no 
need to,
and if one goes this route of creating classes, it should be 
all or

nothing, else there is no real benefit)


You make it sound like I came up with the external base class, 
but I just took that from your code.


No, what I meant was I don't want a base. I only added it in my 
code so it would compile/do what I want.



[...]
It seems that when one uses `class T(A...) : X`, one can't, 
for some X,
not have inheritance. The compiler expects X to be something 
inheritable

from no matter what.


I didn't know it, but your code shows that X can also be an 
empty compile time list (Seq). I have no idea if this is in the 
spec, or if it just happens to work with dmd.


If it's valid D, you just need a template that goes from T and 
A to T!(A[0 .. $ - 1]), or if A is already empty, to the empty 
Seq.


Like so:


template InstantiateOrEmptySeq(alias tmpl, args...)
{
alias Seq(T...)=T;
static if (args.length > 0)
alias InstantiateOrEmptySeq = tmpl!(args[0 .. $ - 1]);
else
alias InstantiateOrEmptySeq = Seq!();
}

class T(A...) : InstantiateOrEmptySeq!(T, A)
{
...
}



Yes! I though I tried that from Timon's original solution.

The following code works and does what I want!

template InstantiateOrEmptySeq(alias tmpl, args...)
{
alias Seq(T...)=T;
static if (args.length > 0)
alias InstantiateOrEmptySeq = tmpl!(args[0 .. $-1]);
else
alias InstantiateOrEmptySeq = Seq!();
}


class T(A...) : InstantiateOrEmptySeq!(T, A)
{   
static if (A.length == 0)
{
// Base class
int x;
} else  
static if (A[$-1] == "Animal")
{
int y;
} else
static if (A[$-1] == "Dog")
{
int z;
} else
static if (A[$-1] == "Pug")
{
int s;
	} else static assert(A[$-1]~" not a defined class of 
"~this.stringof);

}

The only down side is that the static if's are flat. They don't 
show the relationship between, say, Dog an Animal, that a nested 
set of static if's would show, but I think this is not possible 
due to the recursion and shadowing(I imagine one could test if 
the variables exist but that is messy).


Anyways, Thanks for the help.

I think this is just Timons answer anyways. What the original 
confusion was, was the shadowing, which I thought would not 
happen(or at least expected an error), Lodovico solved that.







Re: Static CT Factory

2016-08-18 Thread Engine Machine via Digitalmars-d-learn

On Friday, 19 August 2016 at 01:25:10 UTC, Anonymouse wrote:

On Friday, 19 August 2016 at 01:10:42 UTC, Engine Machine wrote:
I have a template that is suppose to create a type based on a 
template parameter


static if (T == "int")
{
   auto x = New!int();
}
else static if (T == "double")
{
   auto x = New!double();
}

x = 1.234;


This is just an example, I use custom types.

The static if's prevent x's scope from being after them, even 
though it should work perfectly fine. I can't declare x before 
because I don't know the type.


I'm not sure I understand. static if shouldn't introduce a new 
scope that way.


https://dpaste.dzfl.pl/7b63a6e52309

Mind that x might be a pointer.


Ok, well, I guess the error comes from something else.


Re: Static CT Factory

2016-08-18 Thread Engine Machine via Digitalmars-d-learn

On Friday, 19 August 2016 at 02:54:48 UTC, Basile B. wrote:

On Friday, 19 August 2016 at 01:53:22 UTC, Engine Machine wrote:

On Friday, 19 August 2016 at 01:25:10 UTC, Anonymouse wrote:

On Friday, 19 August 2016 at 01:10:42 UTC, Engine Machine

x = 1.234;

Ok, well, I guess the error comes from something else.


*x = 1.234 for when T verifies is(T == int*) produces an error.

You can put an aditional argument in the function header:

void foo(T)(auto ref T t = T.init)
{
static if (is(T == int))
auto x = new Thing!int;
else static if (is(T == double))
auto x = new Thing!double;
else
static assert(false, "incorrect type");
*x = t;
}


It was because I had a added a new type that I didn't account for 
in the static if chain ;/ The static assert is sort of required. 
We sort of need a static switch with required default so 
forgetting this stuff doesn't break later on(in strange ways) 
when new types are added.








Re: Static CT Factory

2016-08-18 Thread Engine Machine via Digitalmars-d-learn

On Friday, 19 August 2016 at 01:18:28 UTC, Adam D. Ruppe wrote:

On Friday, 19 August 2016 at 01:10:42 UTC, Engine Machine wrote:
I feel that in this case I feel that the scope of the static 
if should allow things to escape since, well, they are static 
if's.



They do.

What, exactly, did you do and what, exactly did you see as the 
error?


I get undefined identifier, but when create the variable outside 
it works.


I used Anonymouse code and it works so I guess the issue stems 
from something else.


My code is more complex and the stuff is in a foreach. I don't 
know why it isn't working since the simplified code is nearly 
identical. Maybe a branch wasn't being taken, I thought I covered 
them all.







Heterogeneous CT array like structure

2016-08-16 Thread Engine Machine via Digitalmars-d-learn

struct Storage
{   
  // Getter
  static auto ref opDispatch(string name)()
  {

  }

  // Setter
  static auto ref opDispatch(string name, T)(T val)
  {
  }
}

auto y = Storage.Data;
Storage.Data = "x";
Storage.Foo = 3;

How can I actually store this data for runtime use that doesn't 
require the GC?


The indexing set is fixed at compile time. In fact, it could come 
from an enum(my first thought). The values for each index can 
have a different type, though, and I'd like them to be the proper 
types(no casting or variant).


Is there a simple way to add to Storage at compile time?

e.g., add

static string Data = "x";
static int Foo = 3;

The assignments are for default values, they will only occur once 
in program execution, what is important is the getter, which will 
create the data if it doesn't exist and set it to some default 
value initially if it needs to.




















CT Inheritence structures

2016-08-19 Thread Engine Machine via Digitalmars-d-learn
I am trying to get Timon Gehr's code working, with some 
modifications:




public template TypeParent(P)
{   
import std.traits;
alias T = TemplateArgsOf!P;
alias Seq(T...) = T;
static if (T.length == 0 || is(typeof(T[0]) == typeof(null)))
{
alias TypeParent = Seq!();  
}
else
{
alias TypeParent = Seq!(P!(T[0..T.length-1]));
}
}


class Type(T...) : TypeParent!(Type!T)
{
int x;
static if (T.length >= 1 && T[0] is "Animal")
{
int y;
static if (T.length >= 2 && T[1] is "Dog")
{
int z;
static if (T.length >= 3&& T[2] is "Pug")
{
int s;
}
}

}
}


void main()
{

import std.traits;

auto a = new Type!("Animal", "Dog", "Pug")();
Type!("Animal", "Dog") b = a;   
Type!("Animal") c = b;

a.s = 1;
b.z = 2;
c.y = 3;
}

The problem is that b and c are of type P!

Type!("Animal", "Dog", "Pug")
P!("Animal", "Dog")
P!"Animal"

Of course, P should be Type and b.z and c.y should change a's 
variables.


I don't know why

alias TypeParent = Seq!(P!(T[0..T.length-1]));

is returning P but I guess I'm doing it wrong. What I want is for 
it to return Type!(T[0],...,T[n-1]);


Any ideas?




Re: CT Inheritence structures

2016-08-20 Thread Engine Machine via Digitalmars-d-learn

On Saturday, 20 August 2016 at 09:42:08 UTC, Jack Applegame wrote:
On Saturday, 20 August 2016 at 00:46:15 UTC, Engine Machine 
wrote:

Any ideas?

Something like this?

mixin template TypeData(string type: "Animal") {
int y;
}
mixin template TypeData(string type: "Dog") {
int z;
}
mixin template TypeData(string type: "Pug") {
int s;
}

template Type(string type, ARGS...) {
static if(ARGS.length == 0) {
class Type {
mixin TypeData!type;
}
} else {
class Type : Type!ARGS {
mixin TypeData!type;
}
}
}

void main() {
auto a = new Type!("Pug", "Dog", "Animal")();
Type!("Dog", "Animal") b = a;   
Type!("Animal") c = b;

a.s = 1;
b.z = 2;
c.y = 3;

pragma(msg, typeof(a));
pragma(msg, typeof(b));
pragma(msg, typeof(c));
}

See result - https://dpaste.dzfl.pl/1a76490aaf55


No, this is just standard inheritance that has been complexified. 
The point is to have a single class that encapsulates it's own 
derived types. You have a type constructor. It also doesn't solve 
the original problem.






Re: CT Inheritence structures

2016-08-20 Thread Engine Machine via Digitalmars-d-learn

On Saturday, 20 August 2016 at 06:28:47 UTC, Enamex wrote:
On Saturday, 20 August 2016 at 00:46:15 UTC, Engine Machine 
wrote:
I am trying to get Timon Gehr's code working, with some 
modifications:


void main()
{

import std.traits;

auto a = new Type!("Animal", "Dog", "Pug")();
Type!("Animal", "Dog") b = a;   
Type!("Animal") c = b;

a.s = 1;
b.z = 2;
c.y = 3;
}



Also:

alias T1 = TemplateOf!(typeof(a));
alias T2 = TemplateOf!(typeof(c));
pragma(msg, "\n", T1!"As", " -- ", T2!"As", "\n"); // 
T1!"As" -- T1!"As"


That's extremely weird. It looks like template instantiations 
carry as their printable name (and comparison identifier, 
because `is(templateAlias == templateAlias2)` doesn't work) the 
name they were first instantiated through.


So even doing:

pragma(msg, T1!("Animal", "Dog"))

would print `PT!("Animal", "Dog")` given that it had been 
instantiated already through another Type with ("Animal", 
"Dog") in the beginning of its tuple.


So I guess this method simply won't work ;/ Or somehow TypeParent 
will have to construct the proper type indirectly, which may be 
impossible ;/ I'll try and work on it a little and see what 
happens.





Rebind template

2016-08-20 Thread Engine Machine via Digitalmars-d-learn

Is there a way to rebind the arguments of a template?

template foo(X)
{
   // X is like A!(a,b,c)
   Y = Rebind!(X,d,e,f);
   // Y is like A!(d,e,f);
}

foo(A!(a,b,c));

?


Re: Rebind template

2016-08-20 Thread Engine Machine via Digitalmars-d-learn

On Saturday, 20 August 2016 at 22:11:40 UTC, Engine Machine wrote:

Is there a way to rebind the arguments of a template?

template foo(X)
{
   // X is like A!(a,b,c)
   Y = Rebind!(X,d,e,f);
   // Y is like A!(d,e,f);
}

foo(A!(a,b,c));

?


I'd also be happy if I could just remove the last element from A.

template EraseLast(X)
{
// returns A!(a,b) when X = A!(a,b,c)
}


Re: Rebind template

2016-08-20 Thread Engine Machine via Digitalmars-d-learn

On Saturday, 20 August 2016 at 22:21:00 UTC, ag0aep6g wrote:

On 08/21/2016 12:11 AM, Engine Machine wrote:

Is there a way to rebind the arguments of a template?

template foo(X)
{
   // X is like A!(a,b,c)
   Y = Rebind!(X,d,e,f);
   // Y is like A!(d,e,f);
}

foo(A!(a,b,c));

?


template Rebind(alias instance, newArgs...)
{
import std.traits: TemplateOf;
alias tmpl = TemplateOf!instance;
alias Rebind = tmpl!newArgs;
}


This doesn't work because the rebound type is of type tmpl and 
not the original


e.g.,

Rebind!(T!b, a)

is tmpl!a not T!a.



Re: Sequence separation

2016-08-17 Thread Engine Machine via Digitalmars-d-learn
On Wednesday, 17 August 2016 at 18:38:48 UTC, Engine Machine 
wrote:
On Wednesday, 17 August 2016 at 08:37:32 UTC, Lodovico Giaretta 
wrote:
On Tuesday, 16 August 2016 at 23:18:28 UTC, Adam D. Ruppe 
wrote:

[...]


You mean something like:

struct MySequence(Args...)
{
enum length = Args.length;
alias args = Args;
}

alias x = MySequence!(a, b, MySequence!(c, d));

static assert(x.length == 3)
static assert(x.args[2].length == 2);


Thanks, basically works.

How can I test, though, if a argument uses a MySequence? I 
can't do if (Args[0] == MySequence) because MySequence is 
templated. While I could test for a length, that doesn't work 
because some types have a length. I could add another enum to 
MySequence, but again, not safe.


I could do some string tests, but that doesn't work.

in your exmaple,

if (x.args[2] == MySequence) ??

I simply need to differentiate between a parameter/arg being a 
MySequence and not.


I guess I'll go with something like

static if ((a.Args[2]).stringof[0..11] == "MySequence!")

Doesn't feel entirely safe but probably will work without issue.

Maybe there is a better way?


Re: Sequence separation

2016-08-17 Thread Engine Machine via Digitalmars-d-learn

On Wednesday, 17 August 2016 at 19:15:48 UTC, ag0aep6g wrote:

On 08/17/2016 08:38 PM, Engine Machine wrote:

[...]

[...]

[...]


With MySequence being a type, you can do this:


static if (is(x.args[2] == MySequence!Args, Args ...))
{
  ...
}



It works! Nifty that you can do that with is.

Aside from this check, there is probably not much use for 
MySequence being a type. So I'm be tempted to find a way to do 
the check with a raw template MySequence.


As you said, another enum alone doesn't cut it. The faker can 
just add the same enum.


But a private enum of a private type might do it:


template MySequence(Args ...)
{
/* ... length and args ... */
private enum id = Id();
}

private struct Id {}

enum isMySequence(alias seq) =  is(typeof(seq.id) == Id);


Other modules can't use the Id type directly, because it's 
private. And they can't use typeof(MySequence!foo.id), because 
the id member is private, too.


However, I wouldn't be surprised if this can be circumvented 
too.


Well, the is does work and that probably is the best solution. I 
don't mind the extra type at this point. Of course, a library 
solution for this type of stuff would be nice. I'd rather not 
have to even use a type but rather use arrays:

[a,b,[c,d]].



Re: Sequence separation

2016-08-17 Thread Engine Machine via Digitalmars-d-learn
On Wednesday, 17 August 2016 at 19:21:57 UTC, Lodovico Giaretta 
wrote:

On Wednesday, 17 August 2016 at 19:15:48 UTC, ag0aep6g wrote:



[...]


import std.traits: TemplateOf;
static if (__traits(isSame, TemplateOf!(x.args[2]), MySequence))
{
...
}

std.traits.TemplateOf extracts the symbol representing the 
uninstantiated template.


__traits(isSame, symbol1, symbol2) evaluates at compile time to 
true if and only if the two symbols represent the same thing 
(be it a type, an uninstantiated template, an instantiated one 
or whatever else).


Thanks!

To note, it error's if there is no match ;/


Re: Rebind template(bug?)

2016-08-22 Thread Engine Machine via Digitalmars-d-learn

On Monday, 22 August 2016 at 22:52:28 UTC, ag0aep6g wrote:

On Monday, 22 August 2016 at 21:46:35 UTC, Engine Machine wrote:

I'm sorry if it confuses you... it doesn't confuse me.


You needed quite some help to get this thing to work. And you 
made some mistakes and wrong statements in the process. That's 
perfectly fine, but please don't act as if Jack is the 
simpleton while you're the brainiac.




Um, please don't be an arrogant prick. I never said anything 
about that. He says it confuses him, I said it doesn't confuse 
me. Getting it to work in D has nothing to do with understanding 
the structure. It's like saying that because you can't understand 
English that you must be an imbecile.



I do not know why you have to try and prove something that is 
a preference.


Jack showed a version which he thinks is "cleaner". And since 
this is a discussion board about code, it makes perfect sense 
for him to do that. If you don't care about it, you don't have 
to engage in discussion, of course.




So? I am the one that asked the question how to do X. He brings 
up Y, then you try to justify Y. It is illogical and insane to do 
so.


Do you often get in to arguments with people about how ford is 
better than chevy or blonds are better than brunettes?


Please don't take this to a personal level. Jack was talking 
about the code, and you start questioning his character. Not 
cool.


No, Jack is talking about Y and people that try to change topics, 
like you have done, is insane and do the same thing with what I 
have stated. Keep it up though.


If you're happy with what you got, and you don't want to 
discuss other versions, you can say so without setting the 
stage for a shouting match. Simply not replying is an option, 
too. It may be a bit less polite, but it's better than 
escalating things.


True, but then you should also take your own advice. But if a 
person can't be direct, honest, and talk specifically what is 
asked about, then it is already the well is already poisoned. But 
which will you option will you choose?







Virtual Classes?

2016-08-17 Thread Engine Machine via Digitalmars-d-learn

https://en.wikipedia.org/wiki/Virtual_class

Can D do stuff like this naturally?



Re: Rebind template(bug?)

2016-08-22 Thread Engine Machine via Digitalmars-d-learn

On Monday, 22 August 2016 at 19:09:34 UTC, Jack Applegame wrote:

On Monday, 22 August 2016 at 18:04:43 UTC, Engine Machine wrote:

How do you seriously think this is cleaner/simpler?

1. No extra encrypted things, such as InstantiateOrEmptySeq
2. Much more understandable.


You have two classes.
No. I have one template with two specializations. Class 
template and class is not the same thing.



Their is no uniformity between them.

They have the same name. This is the best uniformity.

You have uniformity between all the derived classes then have 
a special case for the base class. A certain easy to follow 
pattern is set up but needlessly break it for one case. Why?
Because it is the base class. It has no parent. Also this is 
the standard and well known pattern in template metaprogramming.


I'm sorry if it confuses you... it doesn't confuse me. I do not 
know why you have to try and prove something that is a 
preference. Do you often get in to arguments with people about 
how ford is better than chevy or blonds are better than brunettes?


Re: Rebind template(bug?)

2016-08-22 Thread Engine Machine via Digitalmars-d-learn

On Monday, 22 August 2016 at 18:48:12 UTC, ag0aep6g wrote:

On 08/22/2016 08:04 PM, Engine Machine wrote:
How do you seriously think this is cleaner/simpler? You have 
two
classes. Their is no uniformity between them. You have 
uniformity
between all the derived classes then have a special case for 
the base
class. A certain easy to follow pattern is set up but 
needlessly break

it for one case. Why?


It avoids the relatively obscure (and badly named, by me) 
InstantiateOrEmptySeq template.


You can take this further with template constraints. Gives it a 
more uniform appearance at the price of some repetition:



class T()
{
int x;
}

class T(A...) : T!(A[0..$-1])
if (A.length > 0 && A[$-1] == "Animal")
{
int y;
}

class T(A...) : T!(A[0..$-1])
if (A.length > 0 && A[$-1] == "Dog")
{
int z;
}

class T(A...) : T!(A[0..$-1])
if (A.length > 0 && A[$-1] == "Pug")
{
int s;
}


I wouldn't say that this is obviously, objectively, 
significantly better than the version with the helper template, 
though.




Yeah, but a name means nothing. Change it if you want ;)


By the way, it's not obvious to me what this whole thing 
achieves in practice. And whatever benefit there is, it has to 
be weighed against the cost of the added complexity.


What it achieves is a uniform way to create a hierarchical 
relationship without excessive verbosity. Now, the static ifs are 
probably the most verbose part, a static switch would help:


static switch (A)
{
   case "Animal":
   return;
   ...
}


But only slightly.

I don't mean to say that this is not worth pursuing. Just a 
friendly reminder that over-engineering is something to look 
out for, from someone who is prone to over-engineering himself.



Ultimately it is just syntax, it does nothing over what D already 
does. It doesn't create anything new. In some cases it 
simplifies. If it does, then great, if it doesn't then don't use 
it. While I would prefer a totally different syntax, I also like 
to keep things organized. Having multiple classes floating around 
for certain things is just not needed so there should be an 
option.





Re: Rebind template(bug?)

2016-08-22 Thread Engine Machine via Digitalmars-d-learn

On Monday, 22 August 2016 at 07:54:36 UTC, Jack Applegame wrote:

On Monday, 22 August 2016 at 00:43:00 UTC, Engine Machine wrote:

The following code works and does what I want!

template InstantiateOrEmptySeq(alias tmpl, args...)
{
alias Seq(T...)=T;
static if (args.length > 0)
alias InstantiateOrEmptySeq = tmpl!(args[0 .. $-1]);
else
alias InstantiateOrEmptySeq = Seq!();
}


class T(A...) : InstantiateOrEmptySeq!(T, A)
{   
static if (A.length == 0)
{
// Base class
int x;
} else  
static if (A[$-1] == "Animal")
{
int y;
} else
static if (A[$-1] == "Dog")
{
int z;
} else
static if (A[$-1] == "Pug")
{
int s;
	} else static assert(A[$-1]~" not a defined class of 
"~this.stringof);

}


Why don't you like a cleaner (in my opinion) solution?

class T() {
// Base class
int x;
}

class T(A...) : T!(A[0..$-1]) { 
static if (A[$-1] == "Animal")
{
int y;
} else
static if (A[$-1] == "Dog")
{
int z;
} else
static if (A[$-1] == "Pug")
{
int s;
	} else static assert(A[$-1]~" not a defined class of 
"~this.stringof);

}


How do you seriously think this is cleaner/simpler? You have two 
classes. Their is no uniformity between them. You have uniformity 
between all the derived classes then have a special case for the 
base class. A certain easy to follow pattern is set up but 
needlessly break it for one case. Why?













Re: Float values are wrong in union

2016-08-22 Thread Engine Machine via Digitalmars-d-learn

On Monday, 22 August 2016 at 05:02:41 UTC, jkpl wrote:

On Monday, 22 August 2016 at 04:52:40 UTC, Cauterite wrote:

[...]


That's a 32 bit codegen issue then because DMD64 's disasm 
shows that SSE regs are used:



void foo()
{
union test { int i; float f; }
test t = { i : 0x7fb0};
float t2 = t.f;
test t3 = { f : t2 };
}
===

yields to

===
004586D0h  push rbp
004586D1h  mov rbp, rsp
004586D4h  sub rsp, 10h
004586D8h  mov dword ptr [rbp-10h], 7FB0h
004586DFh  movss xmm0, dword ptr [rbp-10h]
004586E4h  movss dword ptr [rbp-0Ch], xmm0
004586E9h  movss xmm1, dword ptr [rbp-0Ch]
004586EEh  movss dword ptr [rbp-08h], xmm1
004586F3h  leave
004586F4h  ret
===


x86 give 7FF and x64 gives 7FB in win.