Re: Initalizing complex array types or some other problem ;/

2015-09-15 Thread Prudence via Digitalmars-d-learn

On Tuesday, 15 September 2015 at 20:54:49 UTC, anonymous wrote:

On Tuesday 15 September 2015 22:09, Prudence wrote:


The code below doesn't work.


Please be more specific in how it doesn't work. Mention the 
error message if there is one, or say how the code behaves 
differently from what you'd expect.


Trying to compile the code (after kicking getch out), I get 
this error:

core.exception.RangeError@test.d(103): Range violation

Line 103 is: writeln(MyStore.Store[k].length);

I can't find where you set Store[k]. Maybe you forgot that or 
deleted it accidentally?


I made a guess and added this line in SingleStore.New:
o.Store[k] ~= tuple(v, o);

It still throws a range error with this. That's because 
associative arrays are a little weird, unfortunately.


An AA is effectively initialized on the first assignment. So 
(with my addition) the first SingleStore.New call initializes 
the AA. But it only initializes o.Store, not the original 
variable s (i.e. ObjectStore.Store). s is left empty.


Possible solutions/workarounds:
* Append to s[k], then assign s to o.Store.
* Initialize ObjectStore.Store in a static constructor:

static this()
{
Store[TKey.init] = [];
Store.remove(TKey.init);
}


Maybe. Seems to work without it. The code below should compile on 
your system and work(and prints 1 2 3 4, 4 3 2 1). The getch is 
required on windows if I want to see the output, so I don't know 
why you even bothered mention replacing it.






import std.stdio;
import std.concurrency;



extern (C) int getch();
import std.string;
import std.concurrency;
import core.time;
import core.thread;
import std.container.array;
import std.typecons;







public class SingleStore(TKey, TValue)
{
public TValue Value;
public TKey Key;
public Tuple!(TValue, SingleStore!(TKey, TValue))[][TKey] Store;


	// Duplicate entries will be removed together as there is no way 
to distinguish them

public auto Remove()
{
import std.algorithm;
if (Value == null || Key == null) return;
int count = 0;
for(int i = 0; i < Store[Key].length; i++)
{
if (Store[Key][i][0] == Value && Store[Key][i][1] == 
this)
{
count++;
	Store[Key][i] = tuple(null, null); // Set to null to release 
any references if necessary
	swap(Store[Key][i], Store[Key][max(0, Store[Key].length - 
count)]);

i = i - 1;
}

}
if (count == 1 && Store[Key].length == 1)
{
Store[Key] = null;
Store.remove(Key);
} else
//Store[Key] = 
Store[Key][0..max(0,Store[Key].length-count)];
Store[Key].length = Store[Key].length - count;

Value = null;
Key = null;

}

	public static auto New(TKey k, TValue v, ref Tuple!(TValue, 
SingleStore!(TKey, TValue))[][TKey] s)

{
auto o = new SingleStore!(TKey, TValue)();  // GC
o.Key = k;
o.Value = v;
s[k] ~= tuple(v, o);
o.Store = s;

return o;
}

}


// Creates a static Associative Array that stores multiple values 
per key. The object returned by New can then be used to remove 
the key/value without having to remember specifically them.

public mixin template ObjectStore(TKey, TValue)
{
	// The object store. It is static. Mixin the template into it's 
different types to create different types of stores. All objects 
of that type are then in the same store.
	public static Tuple!(TValue, SingleStore!(TKey, TValue))[][TKey] 
Store;


public static auto New(TKey k, TValue v)
{
auto r =  SingleStore!(TKey, TValue).New(k, v, Store);
return r;
}

}

//alias dg = int delegate(int);
alias dg = string;

public class cMyStore(TKey, TValue)
{
//mixin ObjectStore!(string, dg);
mixin ObjectStore!(string, string); 
}



void main()
{
alias MyStore = cMyStore!(string, string);
auto k = "x";

auto r = 

/*
dg d1 = (int x) { return x; };
dg d2 = (int x) { return x; };
dg d3 = d1;
dg d4 = (int x) { return 3*x; };
*/

dg d1 = "a1";
dg d2 = "a2";
dg d3 = "a3";
dg d4 = "a4";



auto s = MyStore.New(k, d1);
writeln(MyStore.Store[k].length);
auto s1 = MyStore.New(k, d2);
writeln(MyStore.Store[k].length);
auto s2 = MyStore.New(k, d3);
writeln(MyStore.Store[k].length);
auto s3 = MyStore.New(k, d4);
writeln(MyStore.Store[k].length);   


//auto x = MyStore.Store[k][0](3);
  

Initalizing complex array types or some other problem ;/

2015-09-15 Thread Prudence via Digitalmars-d-learn
How does one initialize a tuple type and are arrays initialized 
by default?



The code below doesn't work. I recently converted to use a tuple 
and that seemed to have broke it and I don't know why, when I 
changed the New function to use a ref, that made it worse cause 
now the array is all ways null. Debugging doesn't help much 
because, for some reason, VD won't show object information inside 
the mixin ObjectStore.



	alias StoreType = Tuple!(TValue, SingleStore!(TKey, 
TValue))[][TKey];

public static StoreType Store;

I thought using the alias would help but it doesn't. Trying to 
init it in the static this doesn't seem to help me, as I can't 
get it to new propertly. e.g., new StoreType(); fails.


Any ideas?






import std.stdio;
import std.concurrency;



extern (C) int getch();
import std.string;
import std.concurrency;
import core.time;
import core.thread;
import std.container.array;
import std.typecons;







public class SingleStore(TKey, TValue)
{
public TValue Value;
public TKey Key;
public Tuple!(TValue, SingleStore!(TKey, TValue))[][TKey] Store;


public auto Remove()
{
import std.algorithm;
if (Value == null || Key == null) return;
int count = 0;
for(int i = 0; i < Store[Key].length; i++)
{
if (Store[Key][i][0] == Value && Store[Key][i][1] == 
this)
{
count++;
Store[Key][i] = tuple(null, null);
	swap(Store[Key][i], Store[Key][max(0, Store[Key].length - 
count)]);

i = i - 1;
}


}
if (count == 1 && Store[Key].length == 1)
{
Store[Key] = null;
Store.remove(Key);
} else
//Store[Key] = 
Store[Key][0..max(0,Store[Key].length-count)];
Store[Key].length = Store[Key].length - count;

Value = null;
Key = null;

}

	public static auto New(TKey k, TValue v, ref Tuple!(TValue, 
SingleStore!(TKey, TValue))[][TKey] s)

{
auto o = new SingleStore!(TKey, TValue)(k, v);  // GC
o.Store = s;
return o;
}

private this(TKey k, TValue v)
{
Key = k;
Value = v;
}
}


// Creates a static Associative Array that stores multiple values 
per key. The object returned by New can then be used to remove 
the key/value without having to remember them specifically.

public mixin template ObjectStore(TKey, TValue)
{
	alias StoreType = Tuple!(TValue, SingleStore!(TKey, 
TValue))[][TKey];

public static StoreType Store;

public static auto New(TKey k, TValue v)
{
auto r =  SingleStore!(TKey, TValue).New(k, v, Store);
return r;
}
}

alias dg = int delegate(int);

class MyStore
{
mixin ObjectStore!(string, dg);
}

void main()
{

auto k = "x";

dg d1 = (int x) { return x; };
dg d2 = (int x) { return x; };
dg d3 = d1;
dg d4 = (int x) { return 3*x; };

auto s = MyStore.New(k, d1);
writeln(MyStore.Store[k].length);
auto s1 = MyStore.New(k, d2);
writeln(MyStore.Store[k].length);
auto s2 = MyStore.New(k, d3);
writeln(MyStore.Store[k].length);
auto s3 = MyStore.New(k, d4);
writeln(MyStore.Store[k].length);   

s1.Remove();
writeln(MyStore.Store[k].length);
s2.Remove();
writeln(MyStore.Store[k].length);
s.Remove();
writeln(MyStore.Store[k].length);
s3.Remove();



getch();
}


Convert array to tupled array easily?

2015-09-14 Thread Prudence via Digitalmars-d-learn
I created the following code that some of you have already seen. 
It's sort of a multiple value AA array with self tracking.


The problem is, that for some type values, such as delegates, the 
comparison is is identical. (basically when the delegate is the 
same)


To solve that problem, I'd like to try and turn the Value into 
Tuples of the Value and the address of the SingleStore 
wrapper(which should be unique).


e.g.,
public Tuple!(TValue, void*)[][TKey] Store;

then I'll simply compare the value and address stored with the 
this(inside single store) instead of just this.


Of course, this requires somewhat of a rewrite of the code(trying 
it produced all kinds of errors(I tried to fix up all the 
references and correlated variables but still a mess, specially 
with D's error codes).


It shouldn't be that much trouble though. Essentially where ever 
I access the value, I want to instead of use value from the 
tuple(a single indirection).


Probably not that easy though?



import std.stdio;
import std.concurrency;



extern (C) int getch();
import std.string;
import std.concurrency;
import core.time;
import core.thread;
import std.container.array;
import std.typecons;







public class SingleStore(TKey, TValue)
{
public TValue Value;
public TKey Key;
public TValue[][TKey] Store;


	// Duplicate entries will be removed together as there is no way 
to distinguish them

public auto Remove()
{
import std.algorithm;
if (Value == null || Key == null) return;
int count = 0;
for(int i = 0; i < Store[Key].length;i++)
{
auto c = Store[Key][i];
if (c == Value)
{
count++;
	Store[Key][i] = null; // Set to null to release any 
references if necessary
	swap(Store[Key][i], Store[Key][max(0, Store[Key].length - 
count)]);

i = i - 1;
}


}
if (count == 1 && Store[Key].length == 1)
{
Store[Key] = null;
Store.remove(Key);
} else
Store[Key] = 
Store[Key][0..max(0,Store[Key].length-count)];

Value = null;
Key = null;

}

public static auto New(TKey k, TValue v, ref TValue[][TKey] s)
{
auto o = new SingleStore!(TKey, TValue)(k, v);  
o.Store = s;
return o;
}

private this(TKey k, TValue v)
{
Key = k;
Value = v;
}
}


// Creates a static Associative Array that stores multiple values 
per key. The object returned by New can then be used to remove 
the key/value without having to remember specifically them.

public mixin template ObjectStore(TKey, TValue)
{
	// The object store. It is static. Mixin the template into it's 
different types to create different types of stores. All objects 
of that type are then in the same store.

public static TValue[][TKey] Store;

public static auto New(TKey k, TValue v)
{
(Store[k]) ~= v;
auto o = SingleStore!(TKey, TValue).New(k, v, Store);
return o;
}

public string ToString()
{
return "asdf";
}


}

alias dg = int delegate(int);
//alias dg = string;

class MyStore
{
mixin ObjectStore!(string, dg);
//mixin ObjectStore!(string, string);

}

void main()
{

auto k = "x";


dg d1 = (int x) { return x; };
dg d2 = (int x) { return x; };
dg d3 = d1;
dg d4 = (int x) { return 3*x; };

/*
dg d1 = "a1";
dg d2 = "a2";
dg d3 = "a3";
dg d4 = "a4";
*/


auto s = MyStore.New(k, d1);
writeln(MyStore.Store[k].length);
auto s1 = MyStore.New(k, d2);
writeln(MyStore.Store[k].length);
auto s2 = MyStore.New(k, d3);
writeln(MyStore.Store[k].length);
auto s3 = MyStore.New(k, d4);
writeln(MyStore.Store[k].length);   

//auto x = MyStore.Store[k][0](3);
//writeln("-" ~ x);

s1.Remove();
writeln(MyStore.Store[k].length);
s2.Remove();
writeln(MyStore.Store[k].length);
s.Remove();
writeln(MyStore.Store[k].length);
s3.Remove();



getch();
}


Re: shared array?

2015-09-13 Thread Prudence via Digitalmars-d-learn
On Sunday, 13 September 2015 at 16:58:22 UTC, Ola Fosheim Grøstad 
wrote:
On Sunday, 13 September 2015 at 15:35:07 UTC, Jonathan M Davis 
wrote:
the GC heavily. And the reality of the matter is that the vast 
majority of programs will have _no_ problems with using the GC 
so long as they don't use it heavily. Programming like you're 
in Java and allocating everything on the heap will kill 
performance, but idiomatic D code doesn't do that, and Phobos 
doesn't do that. Far too many programmers freak out at the 
thought of D even having a GC and overreact thinking that they 
have to root it out completely, when there really is no need 
to. Plenty of folks how written highly performant code in D 
using the GC. You just have to avoid doing a lot of allocating 
and make sure you track down unwanted allocations when you 
have a performance problem.


I don't understand this argument. Even if the GC heap only 
contains a single live object, you still have to scan ALL 
memory that contains pointers.


So how does programming like you do in Java affect anything 
related to the GC?


Or are you saying that finalization is taking up most of the 
time?


The problem is that these people arguing that the GC is the holy 
grail simply use statistics for their reasoning. They pigeon 
everyone in the same box they exist in, and you find out it's 
useless to argue with them because their logic is flawed.


What if I happen to write a RT app that happens to use a part of 
phobo's that happens to heavily rely on the GC? Am I suppose to 
use -vgs all the time to avoid that? Do I avoid phobo's because 3 
functions in it use the GC? Am I suppose to memorize a table of 
all the places phobo's uses the GC and then roll my own to avoid 
them?


The fact is, that the proponents of the GC such as JMD do not 
write RT apps and could care less bout that aspect. This is why 
they make such easy claims. For them, RT is just theoretical 
mumbo jumbo that doesn't exist in the real world. The GC is, 
also, for them, a safety blanket so they can be lazy and not have 
to keep track of all the things they should be. This type of 
mentality seems to run rampet in the contributors of D. They 
simply cannot understand the perspective of the other side(or 
refuse to).


Statistics has nothing to do with facts. The fact is, for a hard 
real time app, the GC and it's stop the world behavior is a no 
go. As long as the mentality exists that the GC is good enough 
because it 99% of phobo's doesn't use it or 99% of apps don't 
need RT, or whatever, D will never be as powerful as it can be.


Basically, I know you need your snotty safety blanket and it 
works for you, but I don't want to use it! Don't force me! I 
won't force you to give up your blanket but don't force me to use 
it. The road goes both ways, stop trying to make it one way.
(The argument is fundamentally different. They want to exclude, I 
want to include)


Of course, the real issue is, that it will take someone that has 
the opposite point of view from them to actually do anything 
about it, because it's obvious they won't work the direction they 
think is a waste. So, ultimately, it's people like me that have 
to step up and actually do the work. I am hesitant because it's 
always an uphill battle with such people. Instead of working 
together, they have to make it a struggle. (it's always "Why are 
you trying to take my safety blanket away!!! wa, wa wa" and tears 
follow)










Re: shared array?

2015-09-13 Thread Prudence via Digitalmars-d-learn

On Sunday, 13 September 2015 at 17:16:02 UTC, ponce wrote:
On Sunday, 13 September 2015 at 17:00:30 UTC, Ola Fosheim 
Grøstad wrote:

On Sunday, 13 September 2015 at 16:53:20 UTC, ponce wrote:
GC is basically ok for anything soft-realtime, where you 
already spend a lot of time to go fast enough. And if you 
want hard-realtime, well you wouldn't want malloc either.


It's a non-problem.


If this was true then Go would not have a concurrent collector.


I was speaking of the D language.


Of course, that makes it make sense!


Re: Mixin templates accessing mixed out scope

2015-09-12 Thread Prudence via Digitalmars-d-learn

On Saturday, 12 September 2015 at 17:11:04 UTC, anonymous wrote:

On Saturday 12 September 2015 16:30, Ali Çehreli wrote:


Reduced:

[...]

Error: type SingleStore is not an expression


Reduced further:


class MyStore
{
class SingleStore
{
static void New() // Removing 'static' compiles
{
new SingleStore();
}
}
}


And now the problem can be spotted:

SingleStore is a nested class. That means, instances of it are 
bound to MyStore instances. But New is static, so it doesn't 
have a MyStore to which it could attach the `new SingleStore`.


That error message is pretty awful. I filed an issue: 
https://issues.dlang.org/show_bug.cgi?id=15049


like most D errors ;/ it's the #1 problem I'm struggling with in 
D. Remember there's another error with remove, that isn't 
releated to SingleStore.


As for a fix: I guess SingleStore isn't supposed to be a nested 
class. Mark it static then.


NO! That is the whole point!

SingleStore is a momento that wraps the key value pair, e.g.,

auto t = DeleteStore.New("mycooldelegate", (int x) { return true; 
});


t is suppose to be a single store.

then

t.Remove();

removes the delegate from the store.

Note I don't have to know the actual key or delegate!! Which is 
the whole point!


Else it would lool like this:

store[][string] mydelegatestore;

auto dg = (int x) { return true; };
mydelegatestore["mycooldelegate"] ~= dg;

then

mydelegatestore["mycooldelegate"].remove(d => dg == d);

which requires remembering both the key and the delegate, which 
makes using inline lambdas infeasible(because you'll never be 
able to remove them).


I see no reason why SingleStore has to be static. The mixin 
template should insert all that stuff into the class, which, by 
the way, works...


I've also used that New pattern all that time and it works, maybe 
not for nested classes. Moving SingleStore outside the template 
works.




I've fixed the issue with that, it's not as pretty but works. 
Still have the remove error:









import std.stdio;
import std.concurrency;



extern (C) int getch();
import std.string;
import std.concurrency;
import core.time;
import core.thread;
import std.container.array;
import std.typecons;







public class SingleStore(TKey, TValue)
{
public TValue Value;
public TKey Key;
public TValue[][TKey] Store;
public auto Remove()
{
import std.algorithm;
		remove!(c => Value == c")(Store[this.Key], 
SwapStrategy.unstable);	 // Not working, can't disambiguate

}

public static auto New(TKey k, TValue v, ref TValue[][TKey] s)
{
auto o = new SingleStore!(TKey, TValue)(k, v);  
o.Store = s;
return o;
}

private this(TKey k, TValue v)
{
Key = k;
Value = v;
}
}

public mixin template ObjectStore(TKey, TValue)
{
public static TValue[][TKey] store;

public static auto New(TKey k, TValue v)
{
(store[k]) ~= v;
auto o = SingleStore!(TKey, TValue).New(k, v, store);
o.store = store;
return o;
}


}


class MyStore
{
mixin ObjectStore!(string, bool delegate(int));


}

void main()
{
	auto s = MyStore.New("x", (int x) { return true; }); // works, 
stores delegate in MyStore


	s.Remove();  // Doesn't work because std.algorithm's remove 
isn't working


getch();
}

(The whole point of nesting was so I wouldn't have to explicitly 
create a pointer to the store in SingleStore. Should have worked, 
probably another one of D's bugs)








Re: Mixin templates accessing mixed out scope

2015-09-12 Thread Prudence via Digitalmars-d-learn

On Saturday, 12 September 2015 at 14:30:16 UTC, Ali Çehreli wrote:

On 09/12/2015 06:37 AM, Prudence wrote:


Says the creating new SingleStore is not an expression


Reduced:

mixin template ObjectStore(TKey)
{
class SingleStore
{
static void New()// Removing 'static' compiles
{
new SingleStore();
}
}
}

class MyStore
{
mixin ObjectStore!(int);
}

void main()
{
auto s = new MyStore();
}

Error: type SingleStore is not an expression

Ali


Are you saying this is a bug or something else? The only 
alternative I can think of is to use string mixins but this 
method should work?


Re: Better lambdas!!!!!!!!!!

2015-09-12 Thread Prudence via Digitalmars-d
On Saturday, 12 September 2015 at 10:44:05 UTC, Pierre Krafft 
wrote:

On Saturday, 12 September 2015 at 03:32:51 UTC, Prudence wrote:
On Saturday, 12 September 2015 at 02:13:11 UTC, Pierre Krafft 
wrote:
On Saturday, 12 September 2015 at 01:03:54 UTC, Prudence 
wrote:
On Thursday, 10 September 2015 at 18:02:36 UTC, Ali Çehreli 
wrote:

On 09/10/2015 10:55 AM, Prudence wrote:
> How bout this:
>
> void myfunc(double delegate(int i, int z, float f)) {}
>
>
> myfunc((int i, int z, float f) { return i*z*f; } }
>
> vs
>
> myfunc({ return i*z*f; })   // Names of parameters are
inferred from
> signature.

Considering other features of the language, that's pretty 
much impossible in D. What if there is another i in scope:


int i;
myfunc({ return i*z*f; });

Now, should it call another overload of myfunc that takes 
(int z, int f) because i is something else?


Should the compiler analyze the body of the code and decide 
which symbols could be parameters? And then go through all 
overloads of myfunc? etc.?


Ali


As I said, it could throw a warning or error. It, in some 
sense, is already a a problem with nested blocks that hide 
outside variables, is it not?


The compiler doesn't need to scan anything. It knows the 
which parameters from the definition!



-> void myfunc(double delegate(int i, int z, float f))  <- 
Compiler knows to use the names here as the default names in 
for the parameters when.



when used:

myfunc({ return i*z*f; }); <- Oh, there are the names, we 
know what they are because the signature is tells us. The 
compiler does the following:



1. Sees we have a block without any parameters defined. 
i.e., a lambda.


2. It looks up the signature of myfunc to find out what the 
names are


3. It sees that they are i z and f

4. Now it knows and it effectively rewrites the code as

myfunc((i,z,f) { return i*z*f; });

Surely this is not difficult, 4 steps?


You're making your code more brittle for a small gain. The 
suggestion makes parameter usage order important and the 
compiler can't warn about my typos.

Consider:
myfunc({return "x:"~x~"y:"-y;}) getting changed to 
myfunc({return "y:"~y~"x:"~x;});

Or the typo in
myfunc({return i*z+f*j;});

Lambdas are already very concise. This proposal doesn't give 
any benefits outside of very simple lambdas. Such lambdas are 
already so simple that they could use some standard functions 
instead (like sum, to!T, and bind).



What does this have to do with my proposal? Those issues exist 
regardless of the simplification.


myfunc({return "x:"~x~"y:"-y;}) getting changed to
myfunc({return "y:"~y~"x:"~x;});

huh? What do you mean the suggestion makes parameter usage 
order important? They are important, it has nothing to do with 
the suggestion? Are you saying that you want to reserve the 
right to do something like


myfunc(string delegate(string x, string y));

and

myfunc((y,x){ "y:"~y~"x:"~x; })

? If so, or unless I'm missing something, that's bad no matter 
what. Changing the order and reversing the names is more than 
just confusing, it's hard to read and most people will gloss 
over that fact. Be consistent with your parameters and maybe 
you'll have less bugs?




Or the typo in

myfunc({return i*z+f*j;});

Again, what does this have to do with anything? A typo is a 
typo and is always a mistake. The above example has the same 
effect regardless if the parameters are explicit or deduced.



myfunc((i,z,f) {return i*z+f*j;});

j is still a problem. If j is defined outside the lambda then 
regardless of specific or implicit parameter names, it will 
not cause any problems.


In either case, the compiler can see that j is either 
referenced outside the scope or undefined. It has nothing to 
do with the parameters used.



Of course maybe I'm missing something, but essentially are not 
almost all uses of lambda's simply copying the parameter 
signature of the delegate. It already infers types... you 
could say that leads to typo's too...


 myfunc({return "x:"~x~"y:"-y;});
is infered to mean myfunc((x,y){return "x:"~x~"y:"-y;});
while
 myfunc({return "y:"~y~"x:"~x;});
is infered to mean myfunc((y,x){return "y:"~y~"x:"~x;});
which is not what I expect since the lambda I want is 
myfunc((x,y){return "y:"~y~"x:"~x;});

This can lead to subtle bugs which are very hard to see.

In the typo example there could be two overloaded functions 
differing only in that one takes a delegate having 3 parameters 
and one taking a delegate having 4 parameters. If we explicitly 
write the lambda parameters the typo will be found since j is 
undefined. But when parameters are inferred the compiler will 
see that {return i*z + f*j;} matches the function taking a 
lambda with 4 parameters.


Inferred parameter types are on the brink of what I can allow. 
They can risk typos, but not as easily since you write the 
parameters twice (declaration and usage). They can also 
silently change if the function taking the delegate has the 
parameter type changed. I don't want 

Does a synchronization yield on waiting thread?

2015-09-12 Thread Prudence via Digitalmars-d-learn

It would seem to be the logical thing to do?

That is, suppose two threads are sharing a resource. Thread A has 
it locked. B is "waiting". Is B in a loop burning cycles running 
in the background(regardless of thread.sleep, which only 
alleviates the problem) or does it yield completely and somehow 
inform the lock to resume it when A has unlocked the resources?


The first one burns cycles and can have timing problems. I.e., 
What if A locks and unlocks at the same rate that B checks? (I 
suppose a random sleep time would help with this) (


"Yielding", OTOH, has B burn no cycles waiting in a loop. This 
can lead to optimization and prioritization and all that(after an 
unlock, all the threads waiting can be called, but in what order).


Obviously yielding is more complex and requires the threads kept 
track of(an array for each lock/unlock pair) but far more 
efficient.


I'm hoping D does this, but not holding my breath.





Re: shared array?

2015-09-12 Thread Prudence via Digitalmars-d-learn
On Saturday, 12 September 2015 at 06:23:12 UTC, Jonathan M Davis 
wrote:
On Friday, September 11, 2015 23:29:05 Laeeth Isharc via 
Digitalmars-d-learn wrote:
On Friday, 11 September 2015 at 21:58:28 UTC, Adam D. Ruppe 
wrote:

> [...]

Seems to be quite a lot of FUD wrt use of standard library and 
GC, which means also perhaps we don't communicate this point 
very well as a community.  Making Phobos GC-optional perhaps 
is an ultimate answer.  But people seem to think that you're 
back to C without the GC.


Aside from the few classes in Phobos, its GC usage is almost 
entirely restricted to when it allocates arrays or when it has 
to allocate a closure for a delegate, which can happen in some 
cases when passing predicates to range-based algorithms. 
Avoiding functions that need to allocate arrays avoids that 
source of allocation, and using functors or function pointers 
as predicates avoids having to allocate closures. So, you _can_ 
end up with GC allocations accidentally in Phobos if you're not 
careful, but on the whole, the assertion that Phobos uses the 
GC heavily is FUD - or at least a misunderstanding. But as we 
make more of the functions use lazy ranges rather than arrays 
(particularly with regards to strings), and we make more of the 
code @nogc, it becomes even clearer that the GC isn't involved. 
Also, improvements to how lambdas are handled should reduce how 
often closures have to be allocated for them.




I don't think it's that simple.

Saying that it doesn't use it most of the time is not an 
answer/solution. Using it at all is a problem because one doesn't 
know when and where. I realize there is a switch now(-vgc), and 
maybe that is the solution, but you say "well, phobos only uses 
0.01% on the GC", yet since you either don't, can't, or won't 
know where that is, then it might as well be 100% if you would 
like to potentially get off the GC one day.


It's like playing Russian roulette. It doesn't matter if only 1/6 
times will kill you. It's totally different than 0/6.






Mixin templates accessing mixed out scope

2015-09-12 Thread Prudence via Digitalmars-d-learn


The following code simply does not work, it might be buggy now 
after fiddling with it but basically remove and the 
SingleStore.New are not working(Says the creating new SingleStore 
is not an expression, which makes no sense to me).



Essentially I'm creating a mixin template so I can have different 
"object stores", which is just an associative array of arrays. 
The SingleStore wraps the key, value pair added to the store so 
that I can keep track of and remove the added object easily 
without having to explicitly remember everything(e.g., what if 
TValue is a delegate? Then it get's messy).


Why remove can't disambiguate is beyond me... Why I can't create 
a SingleStore!(int, double)() is beyond me! It would be nice if 
D's errors were a little more helpful!



Error		Error: type SingleStore!(int, double) is not an 
expression		Test.d	56


auto o = new SingleStore!(TKey, TValue)(k, v);  

huh??? Have I just lost it or is this how one is suppose to 
create such an object?


(I do realize that I do not have to parameterize SingleStore. It 
is irrelevant here though)


import std.stdio;
import std.concurrency;



extern (C) int getch();
import std.string;
import std.concurrency;
import core.time;
import core.thread;
import std.container.array;
import std.typecons;








// Creates a static Associative Array that stores multiple values 
per key. The object returned by New can then be used to remove 
the object without having to remember the object specifically.

public mixin template ObjectStore(TKey, TValue)
{
	// The object store. It is static. Mixin the template into it's 
different types to create different types of stores. All objects 
of that type are then in the same store.

public static TValue[][TKey] store;

public static auto New(TKey k, TValue v)
{
(store[k]) ~= v;
auto o = SingleStore!(TKey, TValue).New(k, v);
return o;
}

public static auto Remove(SingleStore!(TKey, TValue) o)
{
import std.algorithm;
		//remove!(c => (this.Value == c))(store[o.Key], 
SwapStrategy.unstable);

}


public class SingleStore(TKey, TValue)
{
public TValue Value;
public TKey Key;

public auto Remove()
{
import std.algorithm;
			//remove!("c => (this.Value == c)")(store[this.Key], 
SwapStrategy.unstable);

//super.Remove(this);
}

public static auto New(TKey k, TValue v)
{
auto o = new SingleStore!(TKey, TValue)(k, v);  
return o;
}

private this(TKey k, TValue v)
{
Key = k;
Value = v;
}
}

}


class MyStore
{
mixin ObjectStore!(int, double);
}

void main()
{
auto s = new MyStore();


getch();




Re: shared array?

2015-09-11 Thread Prudence via Digitalmars-d-learn

On Friday, 11 September 2015 at 16:04:22 UTC, Kagamin wrote:

On Friday, 11 September 2015 at 14:54:00 UTC, Prudence wrote:
But in this case it is static, so why does it matter? Do you 
have any ideas how to wrap it or fix this?


It matters exactly because it is static. A code written for 
single-threaded environment may not work correctly in shared 
context. It simply wasn't written for it. The way to fix it is 
to write code for shared context.


I don't care about "maybe" working. Since the array is hidden 
inside a class I can control who and how it is used and deal with 
the race conditions.


What I want is to be able to use Array so I don't have to rely on 
the GC. but since it complains about the ~this destruction, how 
can I fix that? If I wrap Array, and use a non-shared array 
inside it, I'll  still have the same problem because it will be 
thread local to the object? or is shared applied to all sub types 
of a class?


e.g.,

class MySharedArrayWrapper
{
static Array!(int) a;

}

and instead I use

static shared MySharedArrayWrapper;

But a isn't marked shared, so will it be TLS, which put's me back 
at square one. Or it it marked shared, which then still complains?


Again, I'm asking how, not why.


Re: shared array?

2015-09-11 Thread Prudence via Digitalmars-d-learn

On Friday, 11 September 2015 at 19:27:49 UTC, Adam D. Ruppe wrote:

On Friday, 11 September 2015 at 17:29:47 UTC, Prudence wrote:
I don't care about "maybe" working. Since the array is hidden 
inside a class I can control who and how it is used and deal 
with the race conditions.


You could use __gshared instead of shared. It means put it in 
non-tls storage, just like shared, but the compiler will not 
attempt to help you use it correctly; you're on your own for 
synchronization, etc.


What I want is to be able to use Array so I don't have to rely 
on the GC.


But, again, built-in slices do NOT rely on the GC. Only 
specific methods on them do and you can use your own 
implementation for them.


Really?

Can you back up this claim? Not saying your lying, I'd just like 
to know it's true for a fact?


Ho wan you use "specific methods"? Do you mean I do not use new 
to allocate and use malloc(more or less)?


In that case, am I not essentially just re-creating Array? 
Obviously I can write my own array type and I can even write my 
own compiler, but that's no that the point, is it?








Re: shared array?

2015-09-11 Thread Prudence via Digitalmars-d-learn

On Friday, 11 September 2015 at 20:30:37 UTC, Adam D. Ruppe wrote:

On Friday, 11 September 2015 at 20:06:53 UTC, Prudence wrote:
Can you back up this claim? Not saying your lying, I'd just 
like to know it's true for a fact?


The list of things that trigger the GC is pretty short. See the 
bottom of this page:


http://dlang.org/garbage.html

Basically, the three things that can do a gc allocation in a 
built in array are: increasing the length, the ~= and ~ 
operators, and the [a,b,c] literal syntax.


Slicing, indexing, etc, the other basic operations do not.

If you do: ubyte[] a = (cast(ubyte*) malloc(4)[0..4];, it will 
compile... and create a slice from the malloced memory. That's 
one way to create an array without GCing it.



In that case, am I not essentially just re-creating Array?


Array does a lot of other stuff too... you only really need 
append and maybe shrink for a static variable, since tracking 
ownership doesn't matter (it is never disappearing since it is 
global)


Oh really?!?! I thought slicing used the GC? Is this a recent 
development or always been that way?


ok, so if I just use a shared [], and create it using malloc(as 
you've done above) then release and remalloc when I need to 
append(not efficient but ok in my senario), then it won't use the 
GC?


If so, then I can handle that! I guess [] doesn't have a capacity 
field so I'll have to keep track of that. Other wise, it should 
be pretty simple.


Of course, I still feel like I'm trying to implement array 
because everything turns in to "lots of stuff" at some point ;/





Multidimension AA's and remove

2015-09-11 Thread Prudence via Digitalmars-d-learn
Error: template std.algorithm.mutation.remove cannot deduce 
function from argument types !()(bool delegate(void*, uint, uint, 
int)[], void), candidates are:
std.algorithm.mutation.remove(SwapStrategy s = 
SwapStrategy.stable, Range, Offset...)(Range range, Offset 
offset) if (s != SwapStrategy.stable && 
isBidirectionalRange!Range && hasLvalueElements!Range && 
hasLength!Range && Offset.length >= 1)
std.algorithm.mutation.remove(SwapStrategy s = 
SwapStrategy.stable, Range, Offset...)(Range range, Offset 
offset) if (s == SwapStrategy.stable && 
isBidirectionalRange!Range && hasLvalueElements!Range && 
Offset.length >= 1)
std.algorithm.mutation.remove(alias pred, SwapStrategy s = 
SwapStrategy.stable, Range)(Range range) if 
(isBidirectionalRange!Range && hasLvalueElements!Range)



coming from

static TValue[][TKey] s;

(s[key]).remove(c => value == c);

How to disambiguate or do what I'm trying to do:

I'm trying to create an associative array with multiple values 
per key. Hence the AA with an extra dynamic array on it.


I've tried

TValue[TKey][] s;

and other stuff without success(essentially same error about not 
being able to deduce remove)


I would expect (s[key]) to return the normal array.

I've tried this too.
remove!(c => this.Value == c)(store[this.Key], 
SwapStrategy.unstable);




At the very least: Is T[][S] an associative array with keys of 
type S and values of an array of type T or is it backwards? Also, 
how to disabmiguate


Thanks.



Re: Better lambdas!!!!!!!!!!

2015-09-11 Thread Prudence via Digitalmars-d

On Thursday, 10 September 2015 at 18:02:36 UTC, Ali Çehreli wrote:

On 09/10/2015 10:55 AM, Prudence wrote:
> How bout this:
>
> void myfunc(double delegate(int i, int z, float f)) {}
>
>
> myfunc((int i, int z, float f) { return i*z*f; } }
>
> vs
>
> myfunc({ return i*z*f; })   // Names of parameters are
inferred from
> signature.

Considering other features of the language, that's pretty much 
impossible in D. What if there is another i in scope:


int i;
myfunc({ return i*z*f; });

Now, should it call another overload of myfunc that takes (int 
z, int f) because i is something else?


Should the compiler analyze the body of the code and decide 
which symbols could be parameters? And then go through all 
overloads of myfunc? etc.?


Ali


As I said, it could throw a warning or error. It, in some sense, 
is already a a problem with nested blocks that hide outside 
variables, is it not?


The compiler doesn't need to scan anything. It knows the which 
parameters from the definition!



-> void myfunc(double delegate(int i, int z, float f))  <- 
Compiler knows to use the names here as the default names in for 
the parameters when.



when used:

myfunc({ return i*z*f; }); <- Oh, there are the names, we know 
what they are because the signature is tells us. The compiler 
does the following:



1. Sees we have a block without any parameters defined. i.e., a 
lambda.


2. It looks up the signature of myfunc to find out what the names 
are


3. It sees that they are i z and f

4. Now it knows and it effectively rewrites the code as

myfunc((i,z,f) { return i*z*f; });

Surely this is not difficult, 4 steps?




Re: Better lambdas!!!!!!!!!!

2015-09-11 Thread Prudence via Digitalmars-d
On Saturday, 12 September 2015 at 02:13:11 UTC, Pierre Krafft 
wrote:

On Saturday, 12 September 2015 at 01:03:54 UTC, Prudence wrote:
On Thursday, 10 September 2015 at 18:02:36 UTC, Ali Çehreli 
wrote:

On 09/10/2015 10:55 AM, Prudence wrote:
> How bout this:
>
> void myfunc(double delegate(int i, int z, float f)) {}
>
>
> myfunc((int i, int z, float f) { return i*z*f; } }
>
> vs
>
> myfunc({ return i*z*f; })   // Names of parameters are
inferred from
> signature.

Considering other features of the language, that's pretty 
much impossible in D. What if there is another i in scope:


int i;
myfunc({ return i*z*f; });

Now, should it call another overload of myfunc that takes 
(int z, int f) because i is something else?


Should the compiler analyze the body of the code and decide 
which symbols could be parameters? And then go through all 
overloads of myfunc? etc.?


Ali


As I said, it could throw a warning or error. It, in some 
sense, is already a a problem with nested blocks that hide 
outside variables, is it not?


The compiler doesn't need to scan anything. It knows the which 
parameters from the definition!



-> void myfunc(double delegate(int i, int z, float f))  <- 
Compiler knows to use the names here as the default names in 
for the parameters when.



when used:

myfunc({ return i*z*f; }); <- Oh, there are the names, we know 
what they are because the signature is tells us. The compiler 
does the following:



1. Sees we have a block without any parameters defined. i.e., 
a lambda.


2. It looks up the signature of myfunc to find out what the 
names are


3. It sees that they are i z and f

4. Now it knows and it effectively rewrites the code as

myfunc((i,z,f) { return i*z*f; });

Surely this is not difficult, 4 steps?


You're making your code more brittle for a small gain. The 
suggestion makes parameter usage order important and the 
compiler can't warn about my typos.

Consider:
myfunc({return "x:"~x~"y:"-y;}) getting changed to 
myfunc({return "y:"~y~"x:"~x;});

Or the typo in
myfunc({return i*z+f*j;});

Lambdas are already very concise. This proposal doesn't give 
any benefits outside of very simple lambdas. Such lambdas are 
already so simple that they could use some standard functions 
instead (like sum, to!T, and bind).



What does this have to do with my proposal? Those issues exist 
regardless of the simplification.


myfunc({return "x:"~x~"y:"-y;}) getting changed to
myfunc({return "y:"~y~"x:"~x;});

huh? What do you mean the suggestion makes parameter usage order 
important? They are important, it has nothing to do with the 
suggestion? Are you saying that you want to reserve the right to 
do something like


myfunc(string delegate(string x, string y));

and

myfunc((y,x){ "y:"~y~"x:"~x; })

? If so, or unless I'm missing something, that's bad no matter 
what. Changing the order and reversing the names is more than 
just confusing, it's hard to read and most people will gloss over 
that fact. Be consistent with your parameters and maybe you'll 
have less bugs?




Or the typo in

myfunc({return i*z+f*j;});

Again, what does this have to do with anything? A typo is a typo 
and is always a mistake. The above example has the same effect 
regardless if the parameters are explicit or deduced.



myfunc((i,z,f) {return i*z+f*j;});

j is still a problem. If j is defined outside the lambda then 
regardless of specific or implicit parameter names, it will not 
cause any problems.


In either case, the compiler can see that j is either referenced 
outside the scope or undefined. It has nothing to do with the 
parameters used.



Of course maybe I'm missing something, but essentially are not 
almost all uses of lambda's simply copying the parameter 
signature of the delegate. It already infers types... you could 
say that leads to typo's too...






Re: shared array?

2015-09-11 Thread Prudence via Digitalmars-d-learn

On Friday, 11 September 2015 at 13:12:14 UTC, Adam D. Ruppe wrote:

On Friday, 11 September 2015 at 04:28:52 UTC, Prudence wrote:
I thought about that but then I have to rely on the GC for 
some simple things. Doesn't seem like the right way to go.


Since it is static, it will never be collected anyway, so you 
could just use it and it'll work for convenience and probably 
lose nothing, or very trivially write an append function that 
uses any scheme you want instead of doing ~= on it without even 
worrying about freeing it.


And that makes it worse!! If it's never collected and the GC 
scans it every time, it means it adds a constant overhead to the 
GC for absolutely no reason, right? It also then makes every 
dependency on it GC dependent(@nogc can't be used)? It just seems 
like it's the wrong way to go about it.







Re: shared array?

2015-09-11 Thread Prudence via Digitalmars-d-learn

On Friday, 11 September 2015 at 07:41:10 UTC, Kagamin wrote:

I get only one error:
Error: non-shared method std.container.array.Array!(void 
delegate()).Array.~this is not callable using a shared object.


It will try to destruct the array on program termination, but 
it requires the destructor to be aware of the shared context.


But in this case it is static, so why does it matter? Do you have 
any ideas how to wrap it or fix this?


Better lambdas!!!!!!!!!!

2015-09-10 Thread Prudence via Digitalmars-d

How bout this:

void myfunc(double delegate(int i, int z, float f)) {}


myfunc((int i, int z, float f) { return i*z*f; } }

vs

myfunc({ return i*z*f; })   // Names of parameters are inferred 
from signature.



by specifying the parameter names in the signature, we don't have 
to specify them in the lamba creation. This doesn't replace the 
original way, just adds the ability to infer the names if they 
are not specified.


Of course, this hides the names outside the lambda, but a warning 
could be issued(no different than if one does it explicitly.





Version for windows/console compilation?

2015-09-10 Thread Prudence via Digitalmars-d-learn
Is there a flag for knowing when a project is compiling for 
windows(Uses WinMain) vs a console(normal main)?


version(Windows) is always valid for a console app, so it is 
useless to disambiguate between a console app and a windows app. 
(Say I have both a main and a winmain in my code, I need to 
select between them(it's a bit more complex than this but)).





shared array?

2015-09-10 Thread Prudence via Digitalmars-d-learn

I can't create a shared array:

static Array!(bool delegate(int, WPARAM, LPARAM)) callbacks;

(prepending shared produce a ton of errors with the Array class)

I've tried making it a pointer and other things.


The array must be static and must be shared. Without shared 
everything works but I don't get, obviously, a useful array(it's 
empty because all the updating goes on in the main thread).


1. How do I create a shared array?
2. Why prepending shared produces any problems? I thought shared 
simply made a variable global to all threads?


Re: Version for windows/console compilation?

2015-09-10 Thread Prudence via Digitalmars-d-learn

On Friday, 11 September 2015 at 01:36:31 UTC, Mike Parker wrote:
On Thursday, 10 September 2015 at 18:10:43 UTC, Adam D. Ruppe 
wrote:


BTW it is pretty rare that you should actually write a WinMain 
in D. The right thing to do in most cases is to write a normal 
main function. You can still get the windows gui subsystem 
with a linker flag.


Specifically, add the following when using the Microsoft linker 
(compiling with -m64 or -m32mscoff):


-L/SUBSYSTEM:windows,6.00 -L/ENTRY:mainCRTStartup

And this when using OPTLINK:

-L/SUBSYSTEM:windows,5.01

The version numbers are optional. I use 6.00 with the MS linker 
because it covers both 32-bit and 64-bit apps on Vista and 
later, and is the default for the VS 2015 linker.


[1] https://msdn.microsoft.com/en-us/library/fcc1zstk.aspx

I don't think I've written a WinMain in D in 10 years.


I'm using Visual D and I assume it takes care of all this. It 
works so that's not a huge problem.


I'm simply creating my own version flags in VD properties. Not 
the best way because I'll have to remember to set the flags every 
time I use the library or I'll get errors about stuff missing. I 
was hoping D had a flag to disambiguate console and windows 
apps(or some type to CT way to check).





Re: shared array?

2015-09-10 Thread Prudence via Digitalmars-d-learn

On Friday, 11 September 2015 at 00:50:15 UTC, Adam D. Ruppe wrote:

On Friday, 11 September 2015 at 00:48:28 UTC, Prudence wrote:

static Array!(bool delegate(int, WPARAM, LPARAM)) callbacks;


Try just using a regular array instead of the library Array.


static bool delegate(int, WPARAM, LPARAM)[] callbacks;

my guess is the Array library thing isn't marked as shared 
internally.


I thought about that but then I have to rely on the GC for some 
simple things. Doesn't seem like the right way to go.




Re: Member function pointers

2015-09-09 Thread Prudence via Digitalmars-d

On Tuesday, 27 May 2014 at 12:21:40 UTC, d coder wrote:

https://github.com/D-Programming-Language/dmd/pull/3181

Daniel asked me to use this. And it works.

Use something like:

union U
{
  void delegate(int) dg;
  struct
  {
void* ptr;
void function(int) funcptr;
  }
}
U u;
u.dg = dg;
u.funcptr = ...;
u.ptr = ...;

Regards
- Puneet


What's the current state of this? I'm in need of such behavior 
for win32 interop.


I'm thinking that one can make the above code more general by 
using it in a mixin and automatically generating the funcptr 
signature:



import std.stdio;
import std.concurrency;

extern (C) int getch();
import std.string;


template FancyDelegate(O, D)
{
	const char[] FancyDelegate = "union "~O.stringof~"Delegate { 
"~D.stringof~" dg; struct { "~O.stringof~"* ptr; 
"~D.stringof.replace("delegate(", 
"function("~O.stringof~",").replace(",)", ")")~" funcptr; } }";	
	//const char[] FancyDelegate = "union "~O.stringof~"Delegate { 
"~D.stringof~" dg; struct { "~O.stringof~"* ptr; 
"~D.stringof.replace("delegate(", "function(")~" funcptr; } }";	

}

class X
{
public int z = 2;
public void foo(int x)
{
//writeln(this.z*x);
writeln(x);
}
}

void delegate(int) dg;

mixin(FancyDelegate!(X, typeof(dg)));


void main()
{

auto xX = new X();
XDelegate x;
x.dg = 

//x.dg(3);
x.ptr = 
x.funcptr(xX, 5);
//x.funcptr(5);


getch();
}

Unfortunately this fails when entering the function. I've tried 
various things(passing , etc..., passing nothing(the comments, 
etc.)


I thought a delegate, when called, was called like a member 
function? It seems that a delegate is some magic black box that 
we can't emulate in any way shape or form due to the calling 
conventions used?


Concurency wtf?

2015-09-08 Thread Prudence via Digitalmars-d-learn


I can't seem to receive certain messages, my code is very simple 
and it all works except for receiving:



in one thread I do


locate("MyMonitor").send(cast(shared)pt);

which sends the message(pt is a windows POINT structure).

In the MyMonitor spawned thread, I have


while (true)
{
POINT y;
receiveTimeout(100.msecs,
(POINT p)
{
y = p;
}
);


Thread.sleep(100.msecs);
continue;
}


Note that everything works except the matching in receiveTimeout. 
(I've tired various things and simplifications to no avail).


I can send simple types like int and bool. e.g., sending a 
literal works fine. My guess is the shared is causing problems 
but I've tried all common sense combinations. But I have to send 
shared, else send complains about sending unshared types.


Of course, the great thing is, all examples use literals and 
hence not real world examples(isn't that nice?).


Please don't ask me to provide source. The issue has nothing to 
do with the other code but specifically the TYPE that is being 
sent. Works for some types and not others. It is almost surely 
due to the shared issue, any ideas?





Win32 function vs delegate issues with api

2015-09-08 Thread Prudence via Digitalmars-d-learn

I have

hook = SetWindowsHookEx(WH_MOUSE, , NULL, ThreadID);   

Proc is the standard hook proc:

public extern (Windows) LRESULT Proc(int code, WPARAM wParam, 
LPARAM lParam)


I get a type mismatch because Proc is a delegate and 
SetWindowsHookEx expects a function. Making proc static works but 
not the behavior I want since all this stuff is wrapped in a 
class.


Is there any way to pass Proc to SetWindowsHookEx without issues 
of GB and such?




Error: function windows.winuser.SetWindowsHookExA (int, extern 
(Windows) int function(int, uint, int), void*, uint) is not 
callable using argument types (const(int), extern (Windows) int 
delegate(int code, uint wParam, int lParam), void*, uint)		


I could cast Proc to a function, obviously, but I'll loose the 
delegate behavior and create problems when I try to use this 
inside Proc?





Re: Windows Header consts

2015-09-07 Thread Prudence via Digitalmars-d-learn
On that note, is there also any generic translation software for 
code that you can program a set of simple "rules"(matching and 
arranging) to translate source code?


e.g., match("const WM_", ";")->WM.add(%1 + ",")).

The above should be obvious but essentially it matches the first 
string until the second is found, adds it to the WM 
container(which, we can specify it it's type). %1 is just what 
was found inbetween the two bookends in the match. We add a comma 
for the next enum.


(such a line would put all the const WM's into the enum, it 
doesn't handle the outer static versioning, so would break 
headers... hence a more robust solution is needed)





Windows Header consts

2015-09-07 Thread Prudence via Digitalmars-d-learn
Windows headers contain a ton of global const's for the various 
messages. Seems like a very bad way to go about this.


Could one not simply put all these in an enum? e.g., enum WM { 
WM_CREATE = 1, etc... }?


If so, because there are so many and so many references to them, 
this can't be done easily by hand. Surely there is a way to 
automate this? But because the headers are not consistently 
written, a simple search and replace won't work well?


e.g.,

const WM_* -> add to enum WM;
else WM_* -> WM.*

because there is code like

static if (_WIN32_WINNT >= 0x500) {

enum {
WM_CHANGEUISTATE=   0x0127,
WM_UPDATEUISTATE=   0x0128,
WM_QUERYUISTATE =   0x0129
}

// LOWORD(wParam) values in WM_*UISTATE*
enum {
UIS_SET =   1,
UIS_CLEAR   =   2,
UIS_INITIALIZE  =   3
}

// HIWORD(wParam) values in WM_*UISTATE*
enum {
UISF_HIDEFOCUS  =   0x1,
UISF_HIDEACCEL  =   0x2
}

}

static if (_WIN32_WINNT >= 0x501) {

// HIWORD(wParam) values in WM_*UISTATE*
enum {
UISF_ACTIVE =   0x4
}

}

(unless one can define partial enums or use static if in the 
enums directly(probably the case but parsing is more difficult))



I guessing one would need a D or C parser to deal with all this?



Re: Windows Header consts

2015-09-07 Thread Prudence via Digitalmars-d-learn

On Monday, 7 September 2015 at 20:55:25 UTC, Adam D. Ruppe wrote:

On Monday, 7 September 2015 at 19:06:48 UTC, Prudence wrote:
It's called encapsulation. It prevents namespace pollution and 
identifier collision.


This is already provided by the D module system. Even if you 
were to define a WM_CREATE in your code, it would not cause a 
major problem with the Win32 name because you can disambiguate 
via the imports. (That's also a minor hassle, but it is more 
rare for these long names than a short name like WM anyway!)


My editor already autocompletes WM_* names anyway, but again, 
the D module system can help with that too if you didn't want 
the keyword based completion I use for that.


I just don't see any advantage here to counterbalance the pain 
of changing it.


Again, it's called progress. Why keep using the same defunct 
system for endless years simply because that's the way it was 
done?


It's like saying we should never upgrade the space shuttle(not 
that it matters any more) simply because the previous one was 
working?


Do you seriously think that your logic is the best? If you could 
prove that Bill Gates designed the best OS ever possible, that is 
one thing... But changes are they shit all over themselves while 
doing it because they didn't learn from there mistakes(how could 
they, they go in to the future to see what kinda crap came out).


Do you think computers in 100 years are still going to be using 
windows? Do you think the designers will still use the same 
programming techniques? Do you think they will worship Bill Gates 
because think they the messaging model of Windows was the 
ultimate gift to humanity?


It's one thing to say: "I'm just too lazy to want to waste all 
that time changing stuff to make it work". That's a valid 
argument! But it's quite different to say "We don't need to 
change because this model works best and any modification of it 
will only produce a poorer result". If you are going to use the 
second argument, you need to prove it. If you are going to use 
the first, don't expect to get anywhere.


I just wish when people say stuff like you have done, you would 
be honest and say what you really mean so we don't have to waste 
time beating around the bush. A simple "I'm don't care what 
others want, I think we should keep it the same because I'm happy 
with it". I'm OK with such a statement. At least it's honest and 
direct. I might not like the selfishness that it implies, but to 
each his own, I suppose.


Oh, and who says you couldn't keep both systems? But I'll never 
understand why people think keeping a junker around and NOT allow 
something better is a good idea. You can keep your rusted ol' 
ElCamino that's missing a tire and has no hood if you want. But 
why stop me from having a Ferrari? Is it jealousy? Selfishness? 
There's enough gas to go around you know? And if we both arrive 
at the gas station we can take turns, if your willing?








Re: Windows Header consts

2015-09-07 Thread Prudence via Digitalmars-d-learn

On Monday, 7 September 2015 at 22:21:28 UTC, Adam D. Ruppe wrote:

On Monday, 7 September 2015 at 22:02:47 UTC, Prudence wrote:

Oh, and who says you couldn't keep both systems?


Nobody. There's absolutely nothing stopping you from defining 
your one constants and bindings. I think you should actually do 
it and see for yourself the pros and cons in practice.


Which is why I asked is there is an easy way to do it, and you 
replied that essentially that it shouldn't be changed because it 
would change things.


Re: Windows Header consts

2015-09-07 Thread Prudence via Digitalmars-d-learn

On Monday, 7 September 2015 at 17:59:43 UTC, Adam D. Ruppe wrote:

On Monday, 7 September 2015 at 17:44:54 UTC, Prudence wrote:

const WM_* -> add to enum WM;
else WM_* -> WM.*


I'm against that. The documentation all says WM_* and we 
shouldn't muck with it.




huh?
Are you saying you don't like to use

WM.Create

because it is confusing and hard for you to understand over

WM_Create?

Did you do a lot of win32 programming back in the day?




Re: Windows Header consts

2015-09-07 Thread Prudence via Digitalmars-d-learn

On Monday, 7 September 2015 at 18:58:08 UTC, Adam D. Ruppe wrote:

On Monday, 7 September 2015 at 18:42:59 UTC, Prudence wrote:

because it is confusing and hard for you to understand over


Nope, I'm saying it is a pointless change. If you do that, 
EVERY time you want to look something up, you need to rewrite 
WM.* into WM_* since that's what the docs say. And then EVERY 
time you copy/paste code from C or, again, the docs, you need 
to change it the other way. (and moreover, it won't even work, 
since like you pointed out, some enums have static if in part)



That's a big hassle... and what's the benefit? What do you 
actually gain by doing this?




It's called encapsulation. It prevents namespace pollution and 
identifier collision. It also makes intelligent easier, not to 
mention looks nicer, keeps everything tidy, and everything else 
that makes coding easier.


If you think mentally changing a . to a _ is a hassle then your 
in trouble! An apple a day simply won't help!


I understand porting code won't be as easy but a simple WM_ to WM 
replacement would fix 99% of the problems. Oh well, some people 
just don't like progress! Do you want to go back to using wooden 
wheels too? Is that better because it's easier to understand than 
the complexity of vulcanized rubber and carbon steel?




Did you do a lot of win32 programming back in the day?


Yup, and I still do. The documented names have worked for 
twenty years, why change them now?


That's what I figured! Get out of the dark ages!




Re: AST like coding syntax. Easy upgrade!

2015-09-06 Thread Prudence via Digitalmars-d

On Sunday, 6 September 2015 at 20:22:23 UTC, Zoadian wrote:

On Sunday, 6 September 2015 at 19:32:58 UTC, Prudence wrote:

template X(Y)
{
string X = Y.stringof;
}

[...]



as you'd have to write a parser for other languages why not 
just use strings? you can already do this:


template X(string Y)
{
enum X = Y;
}

auto s = X!q{int 3;};

obviously X has to be a compiletime js->d compiler.


Seriously? Is that all you got?


Re: AST like coding syntax. Easy upgrade!

2015-09-06 Thread Prudence via Digitalmars-d

On Sunday, 6 September 2015 at 20:38:44 UTC, Adam D. Ruppe wrote:

On Sunday, 6 September 2015 at 20:22:23 UTC, Zoadian wrote:

obviously X has to be a compiletime js->d compiler.


Just a fun fact: my script.d's interpreter is itself CTFEable 
in modern dmd!



import arsd.script;

void main() {
// script.d is similar to but not identical to 
javascript

// so run that code in the interpreter and fetch a D
// type right out all at compile time...
enum a = interpret("var a = 5; a += 2; a;").get!int;
pragma(msg, a);
}


$ dmd d ~/arsd/jsvar ~/arsd/script
7


jsvar.d and script.d can be found here:
https://github.com/adamdruppe/arsd



Yeah, but wouldn't it be so much nicer? (and probably debuggable 
inline)


interpret({
var a = 5;
a += 2;
a;
}

With full compiler error support? (if it's not D, the external 
parser could return the error, line and position info)


Or, maybe better yet, have the concept of "code strings". which 
are strings that are suppose to be interpreted as code. This then 
means the compiler just has to do a syntax check for errors 
before it does anything else with them(semantics will be checked 
lazy, which is already implemented).





Re: Interface "indexing"

2015-09-06 Thread Prudence via Digitalmars-d-learn

On Sunday, 6 September 2015 at 18:11:44 UTC, Kagamin wrote:

Well, you can have an array of event factories:

IEvent function()[2] factories = [ factory1, factory2 ];

IEvent factory1() { return new Event1(); }
IEvent factory2() { return new Event2(); }

Then use enum for indexing:
IEvent e = factories[NumEvent1]();


Yes, I suppose an array would work, but realize that since enum 
is a compile time construct, the dynamic array is not necessary. 
And since your factories are all the time and always will be(if 
you change anything you have to refactor a lot of stuff).


It seems all this stuff could be simplified a great deal. And no 
one said you wouldn't have a switch. I'm not talking about 
creating some tycheyon particles. I'm simply talking about some 
way to hide the details(which, could be done with a string mixin 
but at the cost of not being able to parse them and debug them 
well).





Re: Windows Resources

2015-09-06 Thread Prudence via Digitalmars-d-learn

On Sunday, 6 September 2015 at 10:28:59 UTC, Kagamin wrote:

On Sunday, 6 September 2015 at 02:37:21 UTC, Prudence wrote:
Obviously the issue is that I'm not using any resources yet it 
is giving me such an error.


You do. See docs for lpszMenuName field. GUI projects generated 
by Visual Studio include resource generation, that's why it 
works for them.


Thanks!

So how does one actually include resources such as menu's (rc 
files and all that) in a D project? Or am I stuff creating all 
that stuff programmatically?





AST like coding syntax. Easy upgrade!

2015-09-06 Thread Prudence via Digitalmars-d

template X(Y)
{
string X = Y.stringof;
}

auto s = X({int 3;})

Of course, doesn't work!!

But having the ability to pass code that isn't contained in a 
string is very useful!!



1. A new code keyword, similar to alias. Can only be used as 
template parameters. If you are worried about backwards 
compatibility, call it _code, or __code, or __code__... I don't 
care, only sticks and stones hurt me.


2. The argument is only checked for syntaxical errors as the 
argument. It obviously will be checked. If we allow for other 
types of code besides D, then this won't work. We could extend 
code to allow for other languages(which would require their 
syntax checking algorithms): code(python).


e.g.,

template PythonParser X(code(python) pythoncode)
{
// Parses pythoncode and coverts it into D or passes it to 
the python interpreter or whatever...

}

In this case, D will know it is python code, check for a python 
code parser and deal with it(use an external lib to check it or 
have built in grammars for such things).


No code is ever actually executed by this extension in the 
compiler, so it's somewhat of a trivial addition. All the 
processing is added by the programmer.


3. stringof returns the code as a string. e.g. 
pythoncode.stringof is simply the string representation of the 
block of code passed.



This complements D's mixin mechanisms by getting out of having to 
put code in strings, which are nearly a clusterfuck for complex 
code.




4. This opens the door to allow for one to migrate code easier to 
D. Suppose you have to transfer a large code base in, say, 
javascript. Instead of having to convert it all by hand, you 
could have something like



template IncludeJS(code(javscript))
{
   magiccookie(javscript.stringof);
}

... converts and integrates the javascript code into D or simply 
interprets it and returns the error code, or whatever. It's not 
unfeasible to think that someone could write the magiccookie that 
brings in all the objects, functions, and such into D to be 
consumed in D code. I've seen this done for several scripting 
languages such as lua and js.





Create a delegate function

2015-09-05 Thread Prudence via Digitalmars-d-learn
I have code setup in such a way that I call a user defined 
function, e.g.,


void myFunc(Data d)
{

}

myFunc has to be passed to the main code using something like

void SetFunc(void function(Data) func) { ... func(myData); }

What I would like to do is, instead of having to pass data to 
myFunc(and use the type Data in all the function types), is to 
sort of create a delegate:


what I want to do:

void myFunc()
{
  this.d;  // Ok, because somehow this = Data;
}

then, of course,

void SetFunc(void delegate() func) { func.context = myData; 
func(); }





void delegate() dg =
{
auto t = this;
return;
};

doesn't even work because this is not defined.


My guess this is impossible without compiler support.

effectively though, I don't see why we can't use this(because 
myFunc is being executed in a context, I simply want to set it to 
the right one so that the user can take advantage of it... 
instead of having to pass an argument instead.



Any ideas how to do this? It seems we can't actually create 
"delegate objects" but only delegate pointers? (simply because of 
the restrictions the compiler places on *this*. (can't be used 
outside of a context, even though we can always guarantee it is 
in a context)


How bout a new syntax for such concepts?

void delegate!T(...) dg
{

}

// identical to

void dg(T this, ...)
{

}


Hence, to call dg, we have to pass it a "this" object... hence it 
has a context. They can be called just like functions. dg(myData, 
...);





Windows Resources

2015-09-05 Thread Prudence via Digitalmars-d-learn
I'm trying to create a win32 window. I coped the code pretty much 
directly from msdn:


MSG msg;
BOOL bRet;
WNDCLASS wc;

// Register the window class for the main window.

if (!hPrevInstance)
{
wc.style = 0;
wc.lpfnWndProc = cast(WNDPROC)
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
//wc.hIcon = LoadIcon(cast(HINSTANCE) NULL, 
IDI_APPLICATION);
//wc.hCursor = LoadCursor(cast(HINSTANCE) NULL, 
IDC_ARROW);
wc.hIcon = NULL;
wc.hCursor = NULL;
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName =  "MainMenu";
wc.lpszClassName = "MainWndClass";

if (!RegisterClass())
return FALSE;
}

// Create the main window.
hwndMain = CreateWindow("MainWndClass", "Sample",

WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, 
CW_USEDEFAULT, cast(HWND) NULL,
cast(HMENU) 
NULL, hInstance, cast(LPVOID) NULL);
if (!hwndMain)
{
auto x = GetLastError();
return FALSE;
}


x is 1812 = ERROR_RESOURCE_DATA_NOT_FOUND

That's about as far as I can get. (what resource data? Where I do 
put it? How, who, when?)





Re: Windows Resources

2015-09-05 Thread Prudence via Digitalmars-d-learn

On Sunday, 6 September 2015 at 00:29:13 UTC, Adam D. Ruppe wrote:

On Saturday, 5 September 2015 at 19:06:15 UTC, Prudence wrote:
That's about as far as I can get. (what resource data? Where I 
do put it? How, who, when?)


Resource data in Windows is data compiled into your exe. It is 
stuff like icons, menus, or other arbitrary stuff you attach.


However, the code you posted doesn't access any of that so it 
shouldn't be an issue here... what import did you use to access 
the windows api? `import core.sys.windows.windows;` or 
something else? Also, are you building 32 bit (the default) or 
64 bit?


32-bit and I'm using the latest win32 wrappers distributed on 
github from someone. (suppose to be more complete than 
core.sys.windows)


Obviously the issue is that I'm not using any resources yet it is 
giving me such an error. (again, I pretty much copied the code 
directly from MSDN)






Re: Bug in logger

2015-09-04 Thread Prudence via Digitalmars-d

On Friday, 4 September 2015 at 01:00:24 UTC, Mike Parker wrote:

On Thursday, 3 September 2015 at 23:09:18 UTC, Prudence wrote:
\..\..\src\phobos\std\experimental\logger\core.d(1784): Error: 
static variable stdLoggerThreadLogger cannot be read at 
compile time


I'm trying to use the logger in a static this. It should work 
or, if it can't, quietly fail(not log anything)... and not 
break the program.


The error tells you you're trying to use something in a 
compile-time context that can't be used at compile time. You 
*should* get errors in that situation. Can you share the 
offending code?


Wait, that makes no sense... The error is in phobos... not my 
code. THAT specifically means that it is a phobos problem, 
irrespective of what I'm doing.




Abstractioning away main/winMain

2015-09-04 Thread Prudence via Digitalmars-d-learn

Standard and Win32 apps are so old school!

I'd like to hide WinMain by wrapping it in an application 
class(more or less).


Essentially I have an Application class

class Application
{
   public static Application New(void delegate() entry)
   {

   }
}


 Another module

extern (Windows) int WinMain(...)
{


}

 User Module:


const MyApp = Application.New({ std.stdio.writeln("MY APP IS 
COOL"); });



But the lamba runs into a problem because of the static nature of 
the program... much less figuring out how to hook WinMain up into 
it.


Essentially I don't want the user ever to have to know how there 
entry point came into being but there is this funkyness about it 
because Application never gets any control to call the user's 
Entry function. Whats worse is that D tries to evaluate the 
lambda at compile time. It's as if D only allows non-static data 
inside functions.



The idea is to have WinMain actually call the Entry lamba 
function once it gets ran(transfer control)... but this seems to 
be difficult or impossible with D and I'm not sure why or, if 
not, how to get it to work without having to make the user jump 
through hoops.


I suppose I could create the Application(Using New instead of 
new) inside of WinMain, but the issue still remains on how to get 
the user entry point(I suppose some compile time reflection could 
be used?).


Any ideas?

(The main reason for doing this is to make it easier for writing 
portable apps)







Re: Abstractioning away main/winMain

2015-09-04 Thread Prudence via Digitalmars-d-learn
On Saturday, 5 September 2015 at 01:49:22 UTC, Adam D. Ruppe 
wrote:

On Saturday, 5 September 2015 at 01:43:43 UTC, Prudence wrote:

extern (Windows) int WinMain(...)


If you use WinMain in D, you'll also have to initialize the D 
runtime yourself, which will call static constructors and such.


You'd be better off just using a regular main() function, then 
passing the `-L/SUBSYSTEM:WINDOWS:5.0` option to dmd when 
building (at least on 32 bit, not sure if it is the same on 64 
bit or not) so the linker makes a gui app - same as it does 
when it detects a WinMain in the program.



const MyApp = Application.New({ std.stdio.writeln("MY APP IS 
COOL"); });


Remember, gui apps don't necessarily have a console, so writeln 
may fail!


Maybe, but the error relates to be being called statically.



(The main reason for doing this is to make it easier for 
writing portable apps)



Just using a regular main function is the most portable 
solution. Then just offer helper functions or something to help 
with the boilerplate.


Essentially that is what I'm doing. I have divided the app into 
different types using versioning. The application class is a 
generic wrapper for the main possibilities(win32, Win64, mac, 
linux, etc).


Basically WinMain is used when version is Win32 or Win64 so it is 
not a problem with the stuff you have mentioned. At some point I 
will make it all work but I need to get off the ground first. I 
can always force the user to jump through some hoops but I'd like 
to avoid that as much as possible since I'm the user and I don't 
like hoops.







Re: Abstractioning away main/winMain

2015-09-04 Thread Prudence via Digitalmars-d-learn

If I use functions instead of delegates it works.

I suppose the problem then is that the delegate can't create a 
fat pointer when used in a static context. (i.e., why the 
functions work)


The question is, then, Can I construct a delegate manually and 
supply my own context pointer?


e.g.,
class X { }

void foo() { }

constructDelegate(, new X()) // Creates a void delegate() 
with context X




A better way of managing backwards compatibility?

2015-09-03 Thread Prudence via Digitalmars-d
Dealing with changes to standardized interfacing such as api 
function names, namespaces, file names/module names, etc is 
usually impossible to do because it severs the code written 
before the change from the new compiler. Most people think this 
is the way to do it and there is no, better, alternative.


Well, *NOW* there is:

One could completely change D(could replace it with a Fortran 
version, if desired) yet still keep backwards compatibility 
And it would be relatively easy.


"How can this be possible", you exclaim with relative disdain!!

Well, there are two distinct but compatible ways:


1. Essentially keep track of the version the compiler that is 
currently being used to compile the project, somewhere. (or one 
might be able to infer this from the dates, as long as one has a 
date to version mapping, but this is not accurate)


As long as those binaries of the compiler(and source would be 
nice) are somewhere, the user can be informed to download the 
correct version and/or have the D compiler automatically do this 
for it.


Note though, the requirement for D is only that it can do the 
checking and possibly downloading of another compiler. In fact, 
it could have it such delegating facilities to compile Fortran by 
similar means or it could be the D3 compiler that downloads D1 
for some ancient source code.



2. Write a translation process that essentially "updates" the 
source code to work.


Suppose D **wanted** to change a keyword for some reason or 
another. The compiler first runs the code through the translation 
process which mostly is just a token replacer but it could be 
more advanced and modify function differences(such as a swapping 
of two parameters).


The good news, is that such a feature is easy to implement as it 
is just a mapping of the token stream to another. The hard part 
is getting everyone on a high enough level to put such changes in 
the translation process when they modify the compiler or library 
or whatever.


For example, if we wanted to change "for" with "pour" then the 
parser just as an additional step. Instead of something like: 
parse(token[i]); we would have: parse(translate(token[i])); Where 
translate is just a string to string map, and we could make 
translate more complex by dealing with 
context(parse(translate(token, i)).


Again, one would have to know the version in some way.

We can think of 1 and 2 as different ends of the granular 
spectrum. 1 will get the correct version used and use it. It has 
to work, if not, then it wouldn't have worked anyways(user/setup 
issue) since this is sort of just automating what a user can do. 
I believe there are already tools that sort of emulate 
this(allows you to switch between versions easily but they are 
dumb(no memory and no automation)). 2 generally deals with simple 
changes.



The good news is that all this can come from just knowing the 
version to compile the source with. This then gives the compiler 
designer the freedom not to worry about naming stuff perfectly. 
Documentation is not a problem, as the same translation and 
versioning can be automated in the same way using the same data.


e.g., go to the docs, if you are using an old version, select the 
version, your correct documentation shows up.



What these two processes, together, do, is essentially gives a 
discrete "history" of the compiler. It would be like an 
continuous incremental backup of every change to a compiler, but 
since most changes do not effect source code backwards 
compatibility, One doesn't need every single change.


It also allows one to migrate to new versions seamlessly.

Imagine going from D1 to D2, but it's just D anyways because the 
versions "don't matter" anymore.


1. The compiler will try to translate the D1 source to the D2 
source through a series of micro translations(for each version we 
would have a translate). If it fails at some point, it will 
report to the user the "errors in translation" which can be due 
to a syntax change that is known to break versioning. (e.g., 
change for(i=0;i<10;i++) to for i=0,9,1, which breaks code 
because of semantics... although with a more intelligent 
translator this specific case can easily be handled)


2. If step one fails, which depends on how many times it has to 
be called, the further way the versions we are going between the 
more likely step 1 will fail. In that case we revert the "exact" 
compiler needed by finding and using the correct compiler that 
the source code was designed with.



Of course! We would want this to be build in to the compiler from 
day one. But step 2 saves us with D!! Since almost every version 
has been saved, we can pretty much use step 2 the whole time.


What to this do for everyone when implemented properly? Simply 
keep the versions with the source code somehow(embed in source in 
a comment at the bottom of a file or in a configuration file 
somewhere), and keep the translation changes up to don't on 
compiler 

Re: A better way of managing backwards compatibility?

2015-09-03 Thread Prudence via Digitalmars-d

On Thursday, 3 September 2015 at 21:03:05 UTC, qznc wrote:

On Thursday, 3 September 2015 at 17:48:23 UTC, Prudence wrote:
2. Write a translation process that essentially "updates" the 
source code to work.


Lucky you: https://github.com/Hackerpilot/dfix


There you go!! It seems someone just as intelligent as me 
realizes the power of such a thing!!


The only real problem is integrating it with the compiler to make 
it seamless. I know there are detractors who think it is too much 
work, but these people like to waste time, They think they have 
it to waste!


But even spending 1 hr on trying to compile source code with 
versioning issues is a terrible of time that could be better used 
on more productive things. DFix is obviously a step in the right 
direction... but a few more steps are required to save the many 
thousands of man hours that are wasted on versioning control.






Bug in logger

2015-09-03 Thread Prudence via Digitalmars-d
\..\..\src\phobos\std\experimental\logger\core.d(1784): Error: 
static variable stdLoggerThreadLogger cannot be read at compile 
time


I'm trying to use the logger in a static this. It should work or, 
if it can't, quietly fail(not log anything)... and not break the 
program.






Error reporting is terrible

2015-09-03 Thread Prudence via Digitalmars-d
After being away from D and deciding to test the idea of writing 
a commercial app in it, There were 2 big things that have jumped 
out at me:


1. The setup is a much compared to most modern day compilers and 
software. While VS is huge, obviously has a ton of money behind 
it, it installs without much fanfare. When installing VS you know 
that ones it's done after a few mins you can jump into 
programming and actually get something done.


2. The error messages in D are horrendous. They tend to be terse, 
point to places where the error actually doesn't occur, and 
almost always require one to loop up the error, if it's not 
obvious. This is a waste of time for the programmer. Usually the 
more complex code the more crypographic the errors are.


3. Since I use VS, I installed VD. It works up to a point. But is 
so ill-integrated into VS that it makes me want to just jump back 
into .NET.



D is like a Ferrari owned by someone who doesn't keep it clean, 
forgets to change the oil and filters. Sure, it's pretty powerful 
but it sure looks ugly and you might not trust it in a race.


VS.NET is like a sleep Lamborghini that's kept in a climate 
controlled show room and regularly tuned for performance.