Re: Is this a bug?
Ok, thanks a lot.. About dynamic arrays: I haven't found any information about internal representation of the D structures. E.g. do dynamic arrays have reference counter? Nevermind, I'm gonna use Type2[0] syntax.
Re: Pointer to template types?
On Monday, 28 April 2014 at 10:40:49 UTC, Chris wrote: Person!(string) *pptr; Just wanted to point out, the above is C style and not recommended. Person!(string)* pptr, pptr2, pptr3; In D the pointer is part of the type not the variable (all three are pointers, unlike C where only the first would be a pointer). By placing the pointer on the variable I do not describe the types correctly. Person!(string) *pptr, pptr2, pptr3; This should help when wanting to use more complex types: Person!(string)*[string][][char]* papp; //:) used like :(I don't know my precedence): *((*papp)['c'][1]["hello"])
Re: logging
On 04/28/2014 01:16 PM, xtimoner wrote: > synchronized class EventLog{ > void opCall(string s){ > std.file.append("logfile.txt", s); > } > } > > shared EventLog eventLog; > > Pleas, is it multithread safe and prefered way? Only if there is only one EventLog object. A synchronized class means that there can be only one member function executed on the same object at a given time. Your code is the equivalent of the following: class EventLog{ void opCall(string s){ synchronized (this) {// <-- NOTE (this) std.file.append("logfile.txt", s); } } } So, opCall (and other member functions) is synchronized on a particular object. If you have more than one EventLog, then they can write to the same file at the same time and that would be a problem. Ali
logging
synchronized class EventLog{ void opCall(string s){ std.file.append("logfile.txt", s); } } shared EventLog eventLog; Pleas, is it multithread safe and prefered way?
Re: How to use the result of __traits( allMembers , T ) with string mixins ?
On Mon, Apr 28, 2014 at 8:20 PM, Dicebot via Digitalmars-d-learn wrote: > You can do the same iterating directly over allMembers list, why would you > prefer array here? Hmm, indeed. One advantage would be to get a range, and thus the power and filtering, mapping and co.
Re: How to use the result of __traits( allMembers , T ) with string mixins ?
On Monday, 28 April 2014 at 17:40:54 UTC, Philippe Sigaud via Digitalmars-d-learn wrote: On Mon, Apr 28, 2014 at 5:45 PM, Andrej Mitrovic via Digitalmars-d-learn wrote: If you need to store the tuple as an array to some variable, then you would use that syntax. It all depends on what you're trying to do from the call site. Ultimately it won't matter much once we finally get a proper 'static foreach' feature in D. I guess a common use case is to create an array with [__traits(...)], and use it inside a function, iterating on it and creating a string with the elements. The string is then mixed in with a CTFE call. string makeCode(...) { enum members = [ __traits(allMembers, MyStruct) ]; string result; foreach (m; members) { result ~= "writeln( `" ~ m ~ "` , \" : \" , ( MyStruct." ~ m ~ ".offsetof ) );"); } return result; } mixin(makeCode()); I don't know what I used it for in the tutorial, though :-) You can do the same iterating directly over allMembers list, why would you prefer array here?
Re: How to use the result of __traits( allMembers , T ) with string mixins ?
On Mon, Apr 28, 2014 at 5:45 PM, Andrej Mitrovic via Digitalmars-d-learn wrote: > If you need to store the tuple as an array to some variable, then you > would use that syntax. It all depends on what you're trying to do from > the call site. Ultimately it won't matter much once we finally get a > proper 'static foreach' feature in D. I guess a common use case is to create an array with [__traits(...)], and use it inside a function, iterating on it and creating a string with the elements. The string is then mixed in with a CTFE call. string makeCode(...) { enum members = [ __traits(allMembers, MyStruct) ]; string result; foreach (m; members) { result ~= "writeln( `" ~ m ~ "` , \" : \" , ( MyStruct." ~ m ~ ".offsetof ) );"); } return result; } mixin(makeCode()); I don't know what I used it for in the tutorial, though :-)
Re: 'auto' with AA
On 04/28/2014 12:12 AM, David Held wrote: > Here is a compilable example which fails: > > void main() > { > double[int][string] nestedAA; > nestedAA["test"] = null; I think I see what's going on. The line above has almost no effect. For example, it does not populate "test" with an empty double[int] AA. I think there is conceptually an entry but that entry will be created lazily when an element is added to it. > auto innerAA = nestedAA["test"]; That line is not a reference to "test" but another null: assert(innerAA is null); > innerAA[42] = 3.14; That entry populates the local AA. The "test" entry is still null. > assert(42 in nestedAA["test"]); And that line fails. Ali
Re: Is this a bug?
On Monday, 28 April 2014 at 14:02:33 UTC, Steven Schveighoffer wrote: On Mon, 28 Apr 2014 06:04:53 -0400, John Colvin wrote: On Monday, 28 April 2014 at 09:36:08 UTC, Andrey wrote: not a bug. b.f[10] is indexing the pointer to the array, not the array itself. b.f[0][10] is indexing the array (with the 10), but I would argue it is better to write *(b.f)[10] so as to be clear that f is not an array. thank you, John. compiler said that '*(b.f)[10]' is deprecated, and I should write like this void foo() { Type3 b; Type1 d; d = *(b.f[10]).ptr; } struct T { int[10]* f; } void main() { int[10] test; T t = T(&test); T* b = &t; auto d = (*(b.f))[4]; //ugly but clear. d = b.f[0][4]; //prettier but less clear. } note the extra brackets on the ugly one, I forgot them before. You don't need them. (*b.f)[4] works. '.' has precedence over '*'. -Steve The extra ones I referred to were the outer ones. Nonetheless, you're example is correct.
Re: import with renaming and public import inside module
On Monday, 28 April 2014 at 00:52:50 UTC, ketmar wrote: module my.module; public import other.module; … module mainprogram; import my.module; now i can access other.module symbols without qualifiers and another case: module mainprogram; import zmod = my.module; now i CAN'T access other.module symbols without qualifiers. the only way to access 'em is to use horrible 'zmod.other.module.symbol', which completely defeats my purposes for public imports in my.module. `zmod.symbol` works, too. can i use import renaming, but still access my.module public imports as if there was no renaming? I don't think so. The point of the renamed import is that you have to use the new name. If you want the new name to be optional, import the module twice: import my.module; import zmod = my.module; This way both `symbol` and `zmod.symbol` work. [...] the question is: is such behaviour of 'import' intentional, or this is just bug and it will be fixed eventually? As far as I can see, everything works as intended.
Re: How to use the result of __traits( allMembers , T ) with string mixins ?
On 4/28/14, ParticlePeter via Digitalmars-d-learn wrote: > I found the code with parenthesis in the dlang __traits docs and > also Philippe Sigauds "D Templates", and I haven't seen any other > example which works without them. So, when to use which syntax ( > for which purpose ) ? If you need to store the tuple as an array to some variable, then you would use that syntax. It all depends on what you're trying to do from the call site. Ultimately it won't matter much once we finally get a proper 'static foreach' feature in D.
Re: How to use the result of __traits( allMembers , T ) with string mixins ?
On Monday, 28 April 2014 at 13:57:56 UTC, Andrej Mitrovic wrote: On Monday, 28 April 2014 at 13:52:52 UTC, ParticlePeter wrote: DMD tells me "Error: variable m cannot be read at compile time", but why ? Because 'static foreach' is not an explicit feature yet, so it depends on the context. When you wrap the trait via: [__traits(allMembers, MyStruct)] You're creating an array, and foreach will *not* by default attempt to become a static foreach, even if the array is known at compile-time. If you remove the parentheses it will work. You've had a few bugs in the mixin code though, anyway here's the working sample: - import std.stdio; struct MyStruct { float float_value = 0.0f; ubyte ubyte_value = 2; } enum members = __traits(allMembers, MyStruct); void main() { foreach (m; members) { mixin("writeln( `" ~ m ~ "` , \" : \" , ( MyStruct." ~ m ~ ".offsetof ) );"); } } - Thank you very much, it works. I never came so far to see those mixin errors at all :-) I found the code with parenthesis in the dlang __traits docs and also Philippe Sigauds "D Templates", and I haven't seen any other example which works without them. So, when to use which syntax ( for which purpose ) ? Is this clarified somewhere ? Regards, ParticlePeter
Re: Is this a bug?
On Mon, 28 Apr 2014 06:04:53 -0400, John Colvin wrote: On Monday, 28 April 2014 at 09:36:08 UTC, Andrey wrote: not a bug. b.f[10] is indexing the pointer to the array, not the array itself. b.f[0][10] is indexing the array (with the 10), but I would argue it is better to write *(b.f)[10] so as to be clear that f is not an array. thank you, John. compiler said that '*(b.f)[10]' is deprecated, and I should write like this void foo() { Type3 b; Type1 d; d = *(b.f[10]).ptr; } struct T { int[10]* f; } void main() { int[10] test; T t = T(&test); T* b = &t; auto d = (*(b.f))[4]; //ugly but clear. d = b.f[0][4]; //prettier but less clear. } note the extra brackets on the ugly one, I forgot them before. You don't need them. (*b.f)[4] works. '.' has precedence over '*'. -Steve
Re: How to use the result of __traits( allMembers , T ) with string mixins ?
On Monday, 28 April 2014 at 13:52:52 UTC, ParticlePeter wrote: DMD tells me "Error: variable m cannot be read at compile time", but why ? Because 'static foreach' is not an explicit feature yet, so it depends on the context. When you wrap the trait via: [__traits(allMembers, MyStruct)] You're creating an array, and foreach will *not* by default attempt to become a static foreach, even if the array is known at compile-time. If you remove the parentheses it will work. You've had a few bugs in the mixin code though, anyway here's the working sample: - import std.stdio; struct MyStruct { float float_value = 0.0f; ubyte ubyte_value = 2; } enum members = __traits(allMembers, MyStruct); void main() { foreach (m; members) { mixin("writeln( `" ~ m ~ "` , \" : \" , ( MyStruct." ~ m ~ ".offsetof ) );"); } } -
How to use the result of __traits( allMembers , T ) with string mixins ?
DMD tells me "Error: variable m cannot be read at compile time", but why ? [code] struct MyStruct { float float_value = 0.0f ; ubyte ubyte_value = 2 ; } enum members = [ __traits( allMembers , MyStruct ) ] ; foreach( m ; members ) { mixin( "writeln( " ~ m ~ " , \" : \" , ( MyStruct." ~ m ~ ".offsetof ) ;" ) ; } [\code] I also tried ref m and foreach( i ; 0..members.length ) with m[i]. A simple writeln( m or m[i] ) always worked. I read the limitation of "String Mixins and Compile Time Function Execution" here: http://dlang.org/function.html#interpretation But it doesn't make sense to me as members are enum values and known at compile time. What am I doing wrong, and how could it be done ? Regards, ParticlePeter
Re: Is this a bug?
Andrey: alias short Type1; The "alias X Y;" syntax is going to be deprecated, so use "alias Y = X;" if your compiler already supports it. alias Type1[100]* Type2; // if I take out '*' I will have to type it everywhere, because arrays in D2 always 'by value' Adding the * everywhere could be a good thing, because it makes the code more explicit. Even in Linux kernel typedefs that just mask out a pointer are not appreciated a lot. D code that uses pointers to fixed size arrays is very uncommon in D, so adding a * there is not going to cause troubles. struct Type3 { Type1 key; int flags; int arrLen; Type2 f; // this struct can be *optionally* extended by the array } The common way to create a variable length struct in D is to use a zero length fixed size array (and no pointers): struct Type3 { Type1 key; int flags; int arrLen; Type1[0] f; } But if you don't mind the double indirection using a dynamic array is simpler: struct Type3 { Type1 key; int flags; Type1[] f; } Bye, bearophile
Re: Is this a bug?
bearophile, John, probably, my example was not clear... The code below works. alias short Type1; alias Type1[100]* Type2; // if I take out '*' I will have to type it everywhere, because arrays in D2 always 'by value' struct Type3 { Type1 key; int flags; int arrLen; Type2 f; // this struct can be *optionally* extended by the array } void foo(Type3* b) { Type1 d; d = (*(*b).f)[10]; } Thank you, I appreciate your help!!
Re: Pointer to template types?
On Monday, 28 April 2014 at 11:04:17 UTC, bearophile wrote: Chris: So there is no way of filling an array with something like Person!(string) *pptr; foreach(person; people) { buf ~= &person; } So you want an array filled with instances of the same instantiation, sorry, I misunderstood your problem for a more complex one :-) Bye, bearophile No worries. I didn't make it clear either that it was about syntax.
Re: Pointer to template types?
Chris: So there is no way of filling an array with something like Person!(string) *pptr; foreach(person; people) { buf ~= &person; } So you want an array filled with instances of the same instantiation, sorry, I misunderstood your problem for a more complex one :-) Bye, bearophile
Re: Pointer to template types?
On Monday, 28 April 2014 at 10:44:18 UTC, Rene Zwanenburg wrote: On Monday, 28 April 2014 at 10:40:49 UTC, Chris wrote: So there is no way of filling an array with something like Person!(string) *pptr; foreach(person; people) { buf ~= &person; } Person!(string)*[] arr; Like this? Exactly, just tried it, this works. I tried various types of syntax and just couldn't get it right. Thanks a million.
Re: Pointer to template types?
On Monday, 28 April 2014 at 10:40:49 UTC, Chris wrote: So there is no way of filling an array with something like Person!(string) *pptr; foreach(person; people) { buf ~= &person; } Person!(string)*[] arr; Like this?
Re: Pointer to template types?
On Monday, 28 April 2014 at 10:32:18 UTC, bearophile wrote: Chris: I need an array that contains pointers to types created via template. To stick to my usual example: Person!(string) How can I make an array with pointers to concrete "instances" of Person!(string)? Every template creates a new type, so you can't put them as they are in an array. There are various solutions, none nice. You can try with a wrapper that performs type erasure, or simpler you can make all the same type giving them the string at run-time. Another solution is use OOP, something like (untested and I am not sure): abstract class APerson {} class Person(string name) : APerson {} Bye, bearophile So there is no way of filling an array with something like Person!(string) *pptr; foreach(person; people) { buf ~= &person; }
Re: Pointer to template types?
On Monday, 28 April 2014 at 10:32:18 UTC, bearophile wrote: Chris: I need an array that contains pointers to types created via template. To stick to my usual example: Person!(string) How can I make an array with pointers to concrete "instances" of Person!(string)? Every template creates a new type, so you can't put them as they are in an array. There are various solutions, none nice. You can try with a wrapper that performs type erasure, or simpler you can make all the same type giving them the string at run-time. Another solution is use OOP, something like (untested and I am not sure): abstract class APerson {} class Person(string name) : APerson {} Bye, bearophile So there is no way of filling an array with something like Person!(string) *pptr; foreach(person; people) { buf ~= &person; }
Re: Pointer to template types?
Chris: I need an array that contains pointers to types created via template. To stick to my usual example: Person!(string) How can I make an array with pointers to concrete "instances" of Person!(string)? Every template creates a new type, so you can't put them as they are in an array. There are various solutions, none nice. You can try with a wrapper that performs type erasure, or simpler you can make all the same type giving them the string at run-time. Another solution is use OOP, something like (untested and I am not sure): abstract class APerson {} class Person(string name) : APerson {} Bye, bearophile
Pointer to template types?
I need an array that contains pointers to types created via template. To stick to my usual example: Person!(string) How can I make an array with pointers to concrete "instances" of Person!(string)? Something like this only with pointers, i.e. buf holds pointers to concrete Person!(string)s: Appender!(Person!(string)[]) buf = appender!(Person!(string)[]); Thanks in advance.
Re: Is this a bug?
Andrey: Could anyone please explain to me, why do I have error message on this piece of code? In this thread you are doing some mistakes. This code seems OK: alias TData = short; alias TArray = TData[100]; struct MyStruct { TArray* arrPtr; } void main() { MyStruct* t3 = new MyStruct(new TArray[1].ptr); TData data0 = (*t3.arrPtr)[99]; } D is working as designed. (The only small problem is that you can't "new" a fixed size array, so I have had to allocate a dynamic array of TArray of length 1 and take the pointer to its first item. Another alternative solution is to wrap TArray into a struct.) Such kind of code is possible in D, but it should be quite uncommon in library code (and it can't be marked safe). There are usually simpler ways to do similar things in D. So perhaps there are ways to simplify your data structure (here I have kept the same structure you have used in the example). Bye, bearophile
Re: Is this a bug?
On Monday, 28 April 2014 at 09:36:08 UTC, Andrey wrote: not a bug. b.f[10] is indexing the pointer to the array, not the array itself. b.f[0][10] is indexing the array (with the 10), but I would argue it is better to write *(b.f)[10] so as to be clear that f is not an array. thank you, John. compiler said that '*(b.f)[10]' is deprecated, and I should write like this void foo() { Type3 b; Type1 d; d = *(b.f[10]).ptr; } struct T { int[10]* f; } void main() { int[10] test; T t = T(&test); T* b = &t; auto d = (*(b.f))[4]; //ugly but clear. d = b.f[0][4]; //prettier but less clear. } note the extra brackets on the ugly one, I forgot them before.
Re: Is this a bug?
not a bug. b.f[10] is indexing the pointer to the array, not the array itself. b.f[0][10] is indexing the array (with the 10), but I would argue it is better to write *(b.f)[10] so as to be clear that f is not an array. thank you, John. compiler said that '*(b.f)[10]' is deprecated, and I should write like this void foo() { Type3 b; Type1 d; d = *(b.f[10]).ptr; } which looks completely weird for me... What is the reason you are using a pointer to a struct containing a pointer to a static array? It's often not necessary to work like that. it is just a sample... in real code the struct contains a lot of fields
Re: Is this a bug?
On Monday, 28 April 2014 at 08:58:41 UTC, Andrey wrote: Could anyone please explain to me, why do I have error message on this piece of code? alias short Type1; alias Type1[100]* Type2; // pointer to an array struct Type3 { Type2 f } void foo() { Type3* b; Type1 d; d = b.f[10]; // compilation error: cannot implicitly convert expression ((*b).f[10]) of type short[100] to short d = b.f[0][10]; // ok } Thank you in advance not a bug. b.f[10] is indexing the pointer to the array, not the array itself. b.f[0][10] is indexing the array (with the 10), but I would argue it is better to write *(b.f)[10] so as to be clear that f is not an array. What is the reason you are using a pointer to a struct containing a pointer to a static array? It's often not necessary to work like that.
Is this a bug?
Could anyone please explain to me, why do I have error message on this piece of code? alias short Type1; alias Type1[100]* Type2; // pointer to an array struct Type3 { Type2 f } void foo() { Type3* b; Type1 d; d = b.f[10]; // compilation error: cannot implicitly convert expression ((*b).f[10]) of type short[100] to short d = b.f[0][10]; // ok } Thank you in advance
Re: 'auto' with AA
On 4/27/2014 9:32 PM, Ali Çehreli wrote: fOn 04/27/2014 06:00 PM, David Held wrote: > I would like to do something like this: > > Foo[Bar][Baz] nestedAA; > auto innerAA = nestedAA[someBaz]; > innerAA[someBar] = someFoo; > assert(someFoo in nestedAA[someBaz]); in operator uses a key, not a value. This should work: assert(someBar in nestedAA[someBaz]); Sorry, that is what I meant to say. That is, modifying nestedAA through innerAA does not seem to work, which is why I assumed it was a copy. However, I'm pretty sure that if I use auto on an array, I will get a reference: int[][] matrix = [[1, 2, 3, 4]]; auto array = matrix[0]; array[3] = 42; assert(matrix[0][3] == 42); This works just fine. I assumed that AAs were like arrays, and thus, would work like references. Here is a compilable example which fails: void main() { double[int][string] nestedAA; nestedAA["test"] = null; auto innerAA = nestedAA["test"]; innerAA[42] = 3.14; assert(42 in nestedAA["test"]); } Note that I can even assign 'null' to the nested AA, which implies to me that it's a reference type! Now, the problem may be that null is exactly what gets assigned to innerAA. But then, why am I able to happily index it on the very next line? And what exactly does it mean for an AA to be assigned 'null'? This is perfectly legal, but I don't know what it means: double[int] aa = null; It appears to be a NOP, and indistinguishable from: double[int] aa; In fact, this appears to be the source of the problem. If I change the null assignment above to: nestedAA["test"] = [1:1.0]; then everything works as expected, which means that innerAA really is a reference. What is really bizarre is this idea that it starts out as a presumed null reference, and becomes instantiated through use. Note that this is inconsistent with arrays: double[] a = null; a[0] = 3.14;// Range violation I suppose the difference is that naming an invalid key in an AA inserts the key, but naming an invalid index in an array does not. What is peculiar is that the above is a *range violation* and not an *access violation*. It seems to me that the real problem is that a doesn't *refer to an actual array*. So how can an index into 'a' violate its range? The problem I have with the AA solution above is that I have to create some mapping to "instantiate" the nested AA. I thought I would be clever and create a default initializer, like so: nestedAA["test"] = (double[int]).init; Unfortunately, this appears to be equivalent to assigning null, which I assume is the actual value of .init above[1]. Of course, arrays and AAs are "magical" types in D, but it is a little frustrating that an empty initializer is reduced to the null initializer, even though the empty state is not the same as the null state: double[int][string] nestedAA; nestedAA["test"] = null; auto innerAA = nestedAA["test"]; assert(innerAA.length == 0);// empty assert(innerAA is null);// null innerAA[42] = 3.14; assert(innerAA !is null); // not null innerAA.remove(42); assert(innerAA.length == 0);// empty assert(innerAA !is null); // still not null! If there were an initializer which put the AA in the final state above, then I would be happy. I'm sure that .init == null for performance reasons, but I don't see why there isn't some initializer syntax which creates a truly empty-but-not-null state, other than that not enough people needed it. I propose something like: double[int] aa = [void:void]; assert(aa.length == 0); assert(aa !is null); Unfortunately, this is exactly backwards. This *should* be the syntax to make a "null" AA, and .init should make the empty one. But history has prevented that solution. Anything I'm missing? Dave [1] Unfortunately, .init is not documented here: http://dlang.org/hash-map.html even though it is documented for arrays