Re: Initalizing complex array types or some other problem ;/
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 ;/
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?
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?
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?
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
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
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?
Does a synchronization yield on waiting thread?
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?
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
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?
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?
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?
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
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: shared array?
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?
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?
Version for windows/console compilation?
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?
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?
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?
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.
Concurency wtf?
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
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
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
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
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
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
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
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: Interface "indexing"
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
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?
Create a delegate function
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
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
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)
Abstractioning away main/winMain
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
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
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