inout, delegates, and visitor functions.
Hi all, I'm trying to get the following code to work. (This code is a simplified version of some algebraic type). Is it possible to only declare one version of the 'apply' function? Or should I declare the const version and the non-const version? I tried using "inout", but I got the following error: test.d(28): Error: inout method test.E.apply is not callable using a mutable object class E { void apply(void delegate(inout(E) e) f) inout { f(this); } int val; } void m() { void setToZero(E e) { e.val = 0; } void printValue(const E e) { import std.stdio; writefln("Value: %s", e.val); } E obj; obj.apply(&setToZero); obj.apply(&printValue); } Thanks!
Re: Converting Unicode Escape Sequences to UTF-8
On Thursday, 22 October 2015 at 21:52:05 UTC, anonymous wrote: On 22.10.2015 21:13, Nordlöw wrote: Hmm, why isn't this already in Phobos? Working first version at https://github.com/nordlow/justd/blob/master/conv_ex.d#L207 Next I'll make it a range.
Merging two named Tuples
I am trying to write a function to merge two named structs, but am completely stuck on how to do that and was wondering if anyone good provide any help. I know I can access the different names with tup.fieldNames, but basically can't work out how to use that to build the new return type. Below is an outline of what I am trying to do (with unittest). Any pointers would be greatly appreciated. /++ Merge two Aes structs If it has similar named types, then it uses the second one. Returns a new struct, with combined types. +/ import std.typecons : Tuple; template merge(T, U) { auto merge( T base, U other ) { // Go over other.fieldNames and collect them for new tuple // Go over base.fieldNames, ignoring the ones that other has as well // Build newTuple return newTuple; } } /// unittest { auto xs = ["a","b"]; auto ys = ["c","d"]; auto labels = ["e","f"]; auto aes = Tuple!(string[], "x", string[], "y", string[], "label")( xs, ys, labels ); auto nlAes = merge( aes, Tuple!(double[], "x", double[], "y" )( [0,1], [3,4] ) ); assertEqual( nlAes.x[0], 0 ); assertEqual( nlAes.label.front, "e" ); }
Re: inout, delegates, and visitor functions.
On Saturday, 24 October 2015 at 08:51:58 UTC, Sebastien Alaiwan wrote: Hi all, I'm trying to get the following code to work. (This code is a simplified version of some algebraic type). Is it possible to only declare one version of the 'apply' function? Or should I declare the const version and the non-const version? I tried using "inout", but I got the following error: test.d(28): Error: inout method test.E.apply is not callable using a mutable object class E { void apply(void delegate(inout(E) e) f) inout { f(this); } int val; } void m() { void setToZero(E e) { e.val = 0; } void printValue(const E e) { import std.stdio; writefln("Value: %s", e.val); } E obj; obj.apply(&setToZero); obj.apply(&printValue); } Thanks! Hi Sebastien, That was an interesting question and I didn't succeed with 'inout' either without duplicating apply. I have a partial solution here: http://dpaste.dzfl.pl/b5ec7f16b912 which templatizes the delegate type, but is probably not what you want. The qualifier is not carried on to the apply() function. When taking a const delegate it will still not be const.
Re: inout, delegates, and visitor functions.
Hi ponce, Thanks for your suggestion. I think I may have found the beginning of a solution: class E { import std.traits; void apply(this F, U)(void delegate(U e) f) if(is(Unqual!U == E)) { f(this); } int val; } int main() { void setToZero(E e) { e.val = 0; } void printValue(const E e) { import std.stdio; writefln("Value: %s", e.val); } E obj; obj.apply(&setToZero); obj.apply(&printValue); const(E) objConst; //objConst.apply(&setToZero); objConst.apply(&printValue); return 0; } Basically, I avoid the 'const'/'inout' attribute of the 'apply' function by using a 'this F' template argument. Then, I need a second template argument 'U', otherwise, I can't call 'printValue' on a non-const E instance.
Re: inout, delegates, and visitor functions.
On Saturday, 24 October 2015 at 11:28:17 UTC, Sebastien Alaiwan wrote: Hi ponce, Thanks for your suggestion. I think I may have found the beginning of a solution: class E { import std.traits; void apply(this F, U)(void delegate(U e) f) if(is(Unqual!U == E)) { f(this); } int val; } int main() { void setToZero(E e) { e.val = 0; } void printValue(const E e) { import std.stdio; writefln("Value: %s", e.val); } E obj; obj.apply(&setToZero); obj.apply(&printValue); const(E) objConst; //objConst.apply(&setToZero); objConst.apply(&printValue); return 0; } Clever. It works because of const inference on template functions. Didn't know you could use 'this' as a type.
Re: Converting Unicode Escape Sequences to UTF-8
On Saturday, 24 October 2015 at 08:54:40 UTC, Nordlöw wrote: Working first version at https://github.com/nordlow/justd/blob/master/conv_ex.d#L207 Next I'll make it a range. Made it a range: https://github.com/nordlow/justd/blob/master/conv_ex.d#L207
`clear`ing a dynamic array
Hello. I had first expected that dynamic arrays (slices) would provide a `.clear()` method but they don't seem to. Obviously I can always effectively clear an array by assigning an empty array to it, but this has unwanted consequences that `[]` actually seems to allocate a new dynamic array and any other identifiers initially pointing to the same array will still show the old contents and thus it would no longer test true for `is` with this array. See the following code: import std.stdio; void main() { int a[] = [1,2,3,4,5]; int b[] = a; writeln(a); writeln(b); //a.clear(); a = []; writeln(a); writeln(b); } which outputs: [1, 2, 3, 4, 5] [1, 2, 3, 4, 5] [] [1, 2, 3, 4, 5] How to make it so that after clearing `a`, `b` will also point to the same empty array? IOW the desired output is: [1, 2, 3, 4, 5] [1, 2, 3, 4, 5] [] [] ... and any further items added to `a` should also reflect in `b`. -- Shriramana Sharma, Penguin #395953
Re: `clear`ing a dynamic array
On 24.10.2015 15:18, Shriramana Sharma wrote: int a[] = [1,2,3,4,5]; Aside: `int[] a;` is the preferred style for array declarations. How to make it so that after clearing `a`, `b` will also point to the same empty array? IOW the desired output is: [1, 2, 3, 4, 5] [1, 2, 3, 4, 5] [] [] ... and any further items added to `a` should also reflect in `b`. You can't do that with built-in arrays. The length of a dynamic array is a value member of the array structure. So to update `b`'s length you need access to the actual `b`.
Re: `clear`ing a dynamic array
I'm afraid what you're asking for is impossible. Because 'a' and 'b' are both slices, they each have their own 'length' field. When you do 'a = []', you're effectively doing 'a.length = 0'. There's no way to change 'b.length' through 'a'. To get that effect, you'd have to do something like this: int[] a = [1,2,3,4,5]; int[]* b = &a; a = []; assert(*b == [] && b.length == 0); On Saturday, 24 October 2015 at 13:18:26 UTC, Shriramana Sharma wrote: Hello. I had first expected that dynamic arrays (slices) would provide a `.clear()` method but they don't seem to. Obviously I can always effectively clear an array by assigning an empty array to it, but this has unwanted consequences that `[]` actually seems to allocate a new dynamic array and any other identifiers initially pointing to the same array will still show the old contents and thus it would no longer test true for `is` with this array. See the following code: import std.stdio; void main() { int a[] = [1,2,3,4,5]; int b[] = a; writeln(a); writeln(b); //a.clear(); a = []; writeln(a); writeln(b); } which outputs: [1, 2, 3, 4, 5] [1, 2, 3, 4, 5] [] [1, 2, 3, 4, 5] How to make it so that after clearing `a`, `b` will also point to the same empty array? IOW the desired output is: [1, 2, 3, 4, 5] [1, 2, 3, 4, 5] [] [] ... and any further items added to `a` should also reflect in `b`.
Re: `clear`ing a dynamic array
On Saturday, 24 October 2015 at 13:18:26 UTC, Shriramana Sharma wrote: Hello. I had first expected that dynamic arrays (slices) would provide a `.clear()` method but they don't seem to. Obviously I can always effectively clear an array by assigning an empty array to it, but this has unwanted consequences that `[]` actually seems to allocate a new dynamic array and any other identifiers initially pointing to the same array will still show the old contents and thus it would no longer test true for `is` with this array. See the following code: import std.stdio; void main() { int a[] = [1,2,3,4,5]; int b[] = a; writeln(a); writeln(b); //a.clear(); a = []; writeln(a); writeln(b); } which outputs: [1, 2, 3, 4, 5] [1, 2, 3, 4, 5] [] [1, 2, 3, 4, 5] How to make it so that after clearing `a`, `b` will also point to the same empty array? IOW the desired output is: [1, 2, 3, 4, 5] [1, 2, 3, 4, 5] [] [] ... and any further items added to `a` should also reflect in `b`. D's arrays are not pure reference types, they work like `struct Array(T) { size_t length; T* ptr; }` with some extra methods and operators. If you think of them like that it should be clear what is/isn't possible. If you want to have two references to the same array, including the length, use T[]* or a ref argument to a function or wrap it in a class.
Re: `clear`ing a dynamic array
On Saturday, 24 October 2015 at 13:18:26 UTC, Shriramana Sharma wrote: Hello. I had first expected that dynamic arrays (slices) would provide a `.clear()` method but they don't seem to. Obviously I can always effectively clear an array by assigning an empty array to it, but this has unwanted consequences that `[]` actually seems to allocate a new dynamic array and any other identifiers initially pointing to the same array will still show the old contents and thus it would no longer test true for `is` with this array. See the following code: [...] use std.container.array
Array of templated classes or structs
Hi guys, Apart from deriving from the same class and declaring an array of that root class, is there a way to create an array of templates? This seems not possible since template are compile-time generated, but just to be sure. For example, it seems logical to get an array of complex numbers but Complex needs to be declared with a type. Thanks for any hint.
Re: How to install DMD 64bit on Windows?
On Thursday, 22 October, 2015 02:50 AM, Adam D. Ruppe wrote: Use the .exe installer and it will offer to download and install visual studio for you as part for its process. Sorry to ask this but could anyone please explain why Visual Studio is required by DMD 64-bit? (I have been away far too long than I should have) Thanks
Re: How to install DMD 64bit on Windows?
On Saturday, 24 October 2015 at 16:06:24 UTC, ric maicle wrote: On Thursday, 22 October, 2015 02:50 AM, Adam D. Ruppe wrote: Use the .exe installer and it will offer to download and install visual studio for you as part for its process. Sorry to ask this but could anyone please explain why Visual Studio is required by DMD 64-bit? (I have been away far too long than I should have) Thanks it's required for the standard C library (Digital Mars's one is 32 bit only) and to link COFF objects (Digital Mars linker is only for OMF objects, produced by default only by DMD32).
Re: Array of templated classes or structs
On Saturday, 24 October 2015 at 15:57:09 UTC, Dandyvica wrote: Hi guys, Apart from deriving from the same class and declaring an array of that root class, is there a way to create an array of templates? This seems not possible since template are compile-time generated, but just to be sure. For example, it seems logical to get an array of complex numbers but Complex needs to be declared with a type. Thanks for any hint. You can declare an array whose the element type matches to one of the template parameter: --- struct Foo(T) { Foo!T[] foos; // typeof(this)[] foos // equivalent } --- since it's an array (fixed size whatever is the element type: size_t len + size_t pointer) it doesn't matter if the template declaration is partial.
Re: Array of templated classes or structs
On Saturday, 24 October 2015 at 16:58:58 UTC, qsdfghjk wrote: On Saturday, 24 October 2015 at 15:57:09 UTC, Dandyvica wrote: Hi guys, Apart from deriving from the same class and declaring an array of that root class, is there a way to create an array of templates? This seems not possible since template are compile-time generated, but just to be sure. For example, it seems logical to get an array of complex numbers but Complex needs to be declared with a type. Thanks for any hint. You can declare an array whose the element type matches to one of the template parameter: --- struct Foo(T) { Foo!T[] foos; // typeof(this)[] foos // equivalent } --- since it's an array (fixed size whatever is the element type: size_t len + size_t pointer) it doesn't matter if the template declaration is partial. In that case, all elements have the same type right? I'd like different types, but with the same template.
Re: Array of templated classes or structs
On Saturday, 24 October 2015 at 17:06:13 UTC, Dandyvica wrote: On Saturday, 24 October 2015 at 16:58:58 UTC, qsdfghjk wrote: On Saturday, 24 October 2015 at 15:57:09 UTC, Dandyvica wrote: Hi guys, Apart from deriving from the same class and declaring an array of that root class, is there a way to create an array of templates? This seems not possible since template are compile-time generated, but just to be sure. For example, it seems logical to get an array of complex numbers but Complex needs to be declared with a type. Thanks for any hint. You can declare an array whose the element type matches to one of the template parameter: --- struct Foo(T) { Foo!T[] foos; // typeof(this)[] foos // equivalent } --- since it's an array (fixed size whatever is the element type: size_t len + size_t pointer) it doesn't matter if the template declaration is partial. In that case, all elements have the same type right? I'd like different types, but with the same template. Then no, it's not possible, although some ugly workaround may allow the thing (array of pointer and something used to cast the pointer at runtime, like an AliasSeq). But by definition if you have serveral type in an aray it's not array...it's an agregate.
Re: Array of templated classes or structs
On Saturday, 24 October 2015 at 15:57:09 UTC, Dandyvica wrote: Hi guys, Apart from deriving from the same class and declaring an array of that root class, is there a way to create an array of templates? This seems not possible since template are compile-time generated, but just to be sure. For example, it seems logical to get an array of complex numbers but Complex needs to be declared with a type. Thanks for any hint. Structs or classes that are templated will create new types each time they are instantiated. struct S(T) { /*stuff*/ } static assert(!is(S!int == S!double)); So you can create arrays of: S!int[] a; or S!double[] b; But you can't really create arrays of S!(int or double)[]. However it can be sort of done by using a variant(taged union). import std.variant; alias SIntOrDouble = Algebraic!(S!int, S!double); SIntOrDouble[] array; array ~= S!int(...); array ~= S!double(...); Now the array holds two items an S!int for the first item and an S!double for the second. You can use it like this. foreach(ref elem; array) { if(auto p = elem.peek!(S!int)) { //Do stuff with an S!int item } else if(auto p = elem.peek!(S!double)) { //Do stuff with an S!double. } } Or like this: foreach(ref elem; array) { elem.visit!( (S!int i) => /*something with ints*/, (S!double d) => /*something with doubles*/ ); } Take a look at std.variant if you are interested. A drawback to the Algebraic is that you must know all the different template instantiations that you will be using. If you don't know this I suggest you use a variant instead. The line: SIntOrDouble[] array; changes to Variant[] array; With this you can hold anything in the array. This is both an advantage and a drawback, the advantage is that you can just add more templpate instantiations to the program as is evolves. But you lose static typing information so the compiler will not be able to help you anymore. For example this would be valid: Variant[] array; array ~= S!int(...); array ~= S!double(...); array ~= S!long(...); array ~= "I am a string!"; And this is probably not what you want.
Re: Array of templated classes or structs
On Saturday, 24 October 2015 at 18:29:08 UTC, TheFlyingFiddle wrote: Variant[] array; array ~= S!int(...); array ~= S!double(...); array ~= S!long(...); array ~= "I am a string!"; And this is probably not what you want. You can do this if you want to ensure that items stored in the variant are of a specific template struct/class. import std.traits, std.variant; struct TemplateStruct(alias template_) { private Varint v; void opAssign(TemplateStruct!template_ other) { this.v = other.v; } void opAssing(T)(T t) if(isInstanceOf!(template_, T)) { this.v = t; } T* peek(T) { return v.peek!T; } auto visit(Handlers...) { return v.visit!handler; } //More variant stuff here. } This should work: (untested) TemplateStruct!(S)[] array; array ~= S!int(...); array ~= S!long(...); array ~= S!double(...); array ~= "I am a string!"; //This line should issue a compiler error. To complete TemplateStruct simply forward the remaing members of the variant. Or use something like proxy!T in std.typecons. Or use an alias this v. (I don't really recommend alias this it has all kinds of problems)
Re: Array of templated classes or structs
On Saturday, 24 October 2015 at 19:00:57 UTC, TheFlyingFiddle wrote: One thing about variant is that if the struct you are trying to insert is larger then (void delegate()).sizeof it will allocate the wrapped type on the gc heap. This is not a concern if you want to have class templates as they are on the heap anyways and have a fixed size.
Re: Array of templated classes or structs
On Saturday, 24 October 2015 at 18:40:02 UTC, TheFlyingFiddle wrote: To complete TemplateStruct simply forward the remaing members of the variant. Or use something like proxy!T in std.typecons. Or use an alias this v. (I don't really recommend alias this it has all kinds of problems) One thing about variant is that if the struct you are trying to insert is larger then (void delegate()).sizeof it will allocate the wrapped type on the gc heap. This might be detrimental to performance. So to help with this you could add an extra element on the TemplateStruct to sort of handle this. struct TemplateStruct(alias template_, size_t size = (void delegate).sizeof) { VariantN!(size) v; //Rest is the same. } Pick a good size for the template you want to make arrays of and it will lessen the stress on the gc heap. For example: struct vec4(T) { T[4] data; //stuff } alias Vector4 = TemplateStruct!(template_, vec4!(double).sizeof); Vector4[] array; Additionaly you might want to look into the (http://forum.dlang.org/thread/jiucsrcvkfdzwinqp...@forum.dlang.org) if your interested in some cool stuff that can be done to call methods on such variant structs.
Compilation time profiling
Hi, are there any tools for compilation time profiling? I'm trying to find what part of the code increases compilation time and don't want to stumble around.
Re: Compilation time profiling
On Saturday, 24 October 2015 at 21:56:05 UTC, tired_eyes wrote: Hi, are there any tools for compilation time profiling? I'm trying to find what part of the code increases compilation time and don't want to stumble around. There's this: https://github.com/CyberShadow/DBuildStat Example output: https://github.com/rejectedsoftware/vibe.d/issues/208#issuecomment-15875240
No shortcircuit for static if or template constraints?
Hi All, Given this code: --- import std.traits; import std.range; import std.stdio; enum isSupportedRange(T) = (isInputRange!T && isIntegral!(ForeachType!T)); void func(T)(T vals) { static if(isSupportedRange!T) { // Do something with a range } else { // Do something with a scalar } } void main() { int a1 = 0; int[] a2 = [1,2,3]; func(a1); func(a2); } --- I a compile error like so: ...std/traits.d(6136): Error: invalid foreach aggregate 0 hack.d(6): Error: template instance std.traits.ForeachType!int error instantiating hack.d(10):instantiated from here: isSupportedRange!int hack.d(22):instantiated from here: func!int However, if I remove the Foreach part the "isInputRange!T" clearly fails. I also tried overloading the function like so: --- enum isSupportedRange(T) = (isInputRange!T && isIntegral!(ForeachType!T)); void func(T)(T vals) if(isSupportedRange!T) { // Do something with a range } void func(T)(T vals) if(isNumeric!T) { // Do something with a scalar } --- Again, if I remove the Foreach part and ignore element type of the range it works OK. Am I doing something wrong? Thanks, stew
Re: No shortcircuit for static if or template constraints?
On Saturday, 24 October 2015 at 23:26:09 UTC, stewart wrote: Hi All, Given this code: --- import std.traits; import std.range; import std.stdio; enum isSupportedRange(T) = (isInputRange!T && isIntegral!(ForeachType!T)); void func(T)(T vals) { static if(isSupportedRange!T) { // Do something with a range } else { // Do something with a scalar } } void main() { int a1 = 0; int[] a2 = [1,2,3]; func(a1); func(a2); } --- I a compile error like so: ...std/traits.d(6136): Error: invalid foreach aggregate 0 hack.d(6): Error: template instance std.traits.ForeachType!int error instantiating hack.d(10):instantiated from here: isSupportedRange!int hack.d(22):instantiated from here: func!int However, if I remove the Foreach part the "isInputRange!T" clearly fails. I also tried overloading the function like so: --- enum isSupportedRange(T) = (isInputRange!T && isIntegral!(ForeachType!T)); void func(T)(T vals) if(isSupportedRange!T) { // Do something with a range } void func(T)(T vals) if(isNumeric!T) { // Do something with a scalar } --- Again, if I remove the Foreach part and ignore element type of the range it works OK. Am I doing something wrong? Thanks, stew Oh and the workaround I'm using is this: --- void func(T)(T vals) { static if(isInputRange!T) { static if(isIntegral!(ForeachType!T)) { // Do something with range } } else { // do something with scalar } } --- which is a bit ugly.
Re: No shortcircuit for static if or template constraints?
On Saturday, 24 October 2015 at 23:34:19 UTC, stewart wrote: On Saturday, 24 October 2015 at 23:26:09 UTC, stewart wrote: [...] Oh and the workaround I'm using is this: --- void func(T)(T vals) { static if(isInputRange!T) { static if(isIntegral!(ForeachType!T)) { // Do something with range } } else { // do something with scalar } } --- which is a bit ugly. Maybe this could work: --- enum isSupportedRange(T) = isInputRange!T && is(ForeachType!T) && (isIntegral!(ElementType!T)); --- ElementType() should return exactly what you excpeted with ForeachType().
Re: No shortcircuit for static if or template constraints?
On Saturday, 24 October 2015 at 23:59:02 UTC, qsdfghjk wrote: On Saturday, 24 October 2015 at 23:34:19 UTC, stewart wrote: On Saturday, 24 October 2015 at 23:26:09 UTC, stewart wrote: [...] Oh and the workaround I'm using is this: --- void func(T)(T vals) { static if(isInputRange!T) { static if(isIntegral!(ForeachType!T)) { // Do something with range } } else { // do something with scalar } } --- which is a bit ugly. Maybe this could work: --- enum isSupportedRange(T) = isInputRange!T && is(ForeachType!T) && (isIntegral!(ElementType!T)); --- ElementType() should return exactly what you excpeted with ForeachType(). Yep, that works, thanks! I also found I can do it with __traits, but I think your way is cleaner. enum bool isSupportedRange(T) = __traits(compiles, isInputRange!T && isIntegral!(ForeachType!T)); cheers, stew
Re: No shortcircuit for static if or template constraints?
On Saturday, 24 October 2015 at 23:59:02 UTC, qsdfghjk wrote: On Saturday, 24 October 2015 at 23:34:19 UTC, stewart wrote: On Saturday, 24 October 2015 at 23:26:09 UTC, stewart wrote: [...] Oh and the workaround I'm using is this: --- void func(T)(T vals) { static if(isInputRange!T) { static if(isIntegral!(ForeachType!T)) { // Do something with range } } else { // do something with scalar } } --- which is a bit ugly. Maybe this could work: --- enum isSupportedRange(T) = isInputRange!T && is(ForeachType!T) && (isIntegral!(ElementType!T)); --- ElementType() should return exactly what you excpeted with ForeachType(). Oh no! there's been a copy & paste error. I actually meant: --- enum isSupportedRange(T) = isInputRange!T && (isIntegral!(ElementType!T));
Re: `clear`ing a dynamic array
rsw0x wrote: > use std.container.array Thanks all for all the recommendations. When would one use std.array.appender with a built-in array vs std.container.array.Array? What are the pros and cons on either side? -- Shriramana Sharma, Penguin #395953
Does D's GC release memory back to the OS?
Just wondering if D's GC release memory back to the OS? The documentation for the GC.minimize (http://dlang.org/phobos/core_memory.html#.GC.minimize) seems to imply that it does, but watching my OS's memory usage for various D apps doesn't support this.
Re: `clear`ing a dynamic array
On Saturday, 24 October 2015 at 13:18:26 UTC, Shriramana Sharma wrote: Hello. I had first expected that dynamic arrays (slices) would provide a `.clear()` method but they don't seem to. Obviously I can always effectively clear an array by assigning an empty array to it, but this has unwanted consequences that `[]` actually seems to allocate a new dynamic array and any other identifiers initially pointing to the same array will still show the old contents and thus it would no longer test true for `is` with this array. See the following code: import std.stdio; void main() { int a[] = [1,2,3,4,5]; int b[] = a; writeln(a); writeln(b); //a.clear(); a = []; writeln(a); writeln(b); } which outputs: [1, 2, 3, 4, 5] [1, 2, 3, 4, 5] [] [1, 2, 3, 4, 5] How to make it so that after clearing `a`, `b` will also point to the same empty array? IOW the desired output is: [1, 2, 3, 4, 5] [1, 2, 3, 4, 5] [] [] ... and any further items added to `a` should also reflect in `b`. If you don't want to mess with pointers (as sugggested in the first answer) you can also use std.typecons.RefCounted: --- import std.stdio; import std.typecons; RefCounted!(int[]) b; void main() { int[] a = [1,2,3,4,5]; b = a; writeln(a); writeln(b); a = []; writeln(a); writeln(b); }