Re: GC and void[N] in struct
On Monday, 6 August 2018 at 21:23:36 UTC, Paul Backus wrote: On Monday, 6 August 2018 at 20:22:36 UTC, vit wrote: On Monday, 6 August 2018 at 19:56:03 UTC, Steven Schveighoffer wrote: BTW, is there a reason you aren't just using Algebraic? https://dlang.org/phobos/std_variant.html#.Algebraic -Steve primarily visit for Algebraic isn't pure, @nogc, @safe, nothrow. I wrote the 'sumtype' package to solve this exact problem: https://code.dlang.org/packages/sumtype I'm using simpler (and less powerful) version with different visit/visitor syntax: struct Foo{ string foo; } struct Bar1{ string bar; } struct Bar2{ string bar; } void main()pure nothrow @safe @nogc{ Variant!(true, Foo, Bar1, Bar2) var; ///Nullable == true static visit(T)(auto ref const(T) x, string def = ""){ import std.experimental.all; static if(is(T == Foo)){ return x.foo; } else static if(false || is(T == Bar1) || is(T == Bar2) ){ return x.bar; } else static if(is(T == typeof(null))){ return def; } else static assert(0, "no impl"); } assert(var.isa!null); assert(var.visitor!visit("null") == "null"); var = Foo("foo"); assert(var.isa!Foo); assert(var.visitor!visit == "foo"); var = Bar1("bar1"); assert(var.isa!Bar1); assert(var.visitor!visit == "bar1"); var = Bar2("bar2"); assert(var.isa!Bar2); assert(var.visitor!visit == "bar2"); var = null; assert(var.isa!null); auto var2 = Variant!(false, Foo, Bar1, Bar2)(Foo("foo"));///Nullable == false assert(var2.visitor!visit == "foo"); assert(var2.as!Foo.foo == "foo"); ///var2 = null; //error, variant is not null } full code: https://dpaste.dzfl.pl/d83ecca23694
Re: GC and void[N] in struct
On Monday, 6 August 2018 at 20:22:36 UTC, vit wrote: On Monday, 6 August 2018 at 19:56:03 UTC, Steven Schveighoffer wrote: BTW, is there a reason you aren't just using Algebraic? https://dlang.org/phobos/std_variant.html#.Algebraic -Steve primarily visit for Algebraic isn't pure, @nogc, @safe, nothrow. I wrote the 'sumtype' package to solve this exact problem: https://code.dlang.org/packages/sumtype
Re: scope variable values assigned to non-scope this.placeholder
On Monday, 6 August 2018 at 20:29:29 UTC, Alexandru Ermicioi wrote: Hi Dlang community! I've been playing with dip1000 and scope storage class and stumbled upon a strange error that I can't to understand yet. Here is minimized version of code that generates the error: [...] Parameter values must be `return scope` and this need to be in compiler: https://issues.dlang.org/show_bug.cgi?id=19097
scope variable values assigned to non-scope this.placeholder
Hi Dlang community! I've been playing with dip1000 and scope storage class and stumbled upon a strange error that I can't to understand yet. Here is minimized version of code that generates the error: The link: https://run.dlang.io/is/rg2Odu -- import std.stdio; import std.range; import std.algorithm; @safe: class C { const int*[] placeholder; this(scope int*[] values) { this.placeholder = values; } } void main() { auto array = iota(0, 20).map!((int i) => new int(i)).array; auto c = new C(array); writeln(c.placeholder.map!(p => *p)); } -- I'm not sure what I'm doing wrong, but from what I understand it should check 'this' lifetime to lifetime of scoped 'values' and error only in case when passed value has shorter lifetime than the container itself. I'll be thankful if someone could explain what is wrong with this example. Regards, Alexandru.
Re: GC and void[N] in struct
On Monday, 6 August 2018 at 19:56:03 UTC, Steven Schveighoffer wrote: BTW, is there a reason you aren't just using Algebraic? https://dlang.org/phobos/std_variant.html#.Algebraic -Steve primarily visit for Algebraic isn't pure, @nogc, @safe, nothrow.
Re: GC and void[N] in struct
On 8/6/18 3:43 PM, Steven Schveighoffer wrote: On 8/6/18 2:59 PM, vit wrote: On Monday, 6 August 2018 at 18:28:11 UTC, Steven Schveighoffer wrote: On 8/6/18 2:22 PM, vit wrote: Hello, I have this struct: struct S{ uint kind; void[N] data_; define "N" } Instances of struct S are allocated by standard GC new and S.data_ can contain pointers/ranges to GC allocated data. If is GC disabled then program run fine. But when is GC enabled then it fail randomly. how does it fail? private auto sizeOf(T)(){return T.sizeof;} Hm... wouldn't enum sizeOf(T) = T.sizeof work better? struct ExprImpl(Ts...){ enum N = max(staticMap!(sizeOf, Ts)); This is clever! invariant(kind_ != 0); uint kind_ = 0; void[N] data_; this(T)(auto ref T x){/+emplace T to data_ and change kind_ to something != 0+/} } Ts == structs data change without triggering invariant after allocation in other part of program. Most definitely this is alignment problem. Here is what I *think* is happening: 1. You are constructing one of these structs, and storing a pointer as the T type. 2. You are on a 64-bit CPU. 3. The pointer is misaligned on the CPU, so when the GC scans this struct to see if it's pointing at anything, it sees one half as the kind_ value, and the other half is half of the pointer. 4. It misses the object being pointed at by the T inside the struct, and collects it, leaving a dangling pointer. 5. Memory corruption. when you put the void[N] member *first*, it can properly align the item (most cases where the compiler is placing data, it starts out aligned) but this does not guarantee you have proper alignment, as void[N] has no alignment constraints. I'd recommend instead, changing the uint kind_ to a size_t. This not only aligns the void[N] to size_t size, which should put any pointers in the right place, but it also makes sure the entire struct is aligned. BTW, is there a reason you aren't just using Algebraic? https://dlang.org/phobos/std_variant.html#.Algebraic -Steve
Re: GC and void[N] in struct
On 8/6/18 2:59 PM, vit wrote: On Monday, 6 August 2018 at 18:28:11 UTC, Steven Schveighoffer wrote: On 8/6/18 2:22 PM, vit wrote: Hello, I have this struct: struct S{ uint kind; void[N] data_; define "N" } Instances of struct S are allocated by standard GC new and S.data_ can contain pointers/ranges to GC allocated data. If is GC disabled then program run fine. But when is GC enabled then it fail randomly. how does it fail? private auto sizeOf(T)(){return T.sizeof;} Hm... wouldn't enum sizeOf(T) = T.sizeof work better? struct ExprImpl(Ts...){ enum N = max(staticMap!(sizeOf, Ts)); This is clever! invariant(kind_ != 0); uint kind_ = 0; void[N] data_; this(T)(auto ref T x){/+emplace T to data_ and change kind_ to something != 0+/} } Ts == structs data change without triggering invariant after allocation in other part of program. Most definitely this is alignment problem. Here is what I *think* is happening: 1. You are constructing one of these structs, and storing a pointer as the T type. 2. You are on a 64-bit CPU. 3. The pointer is misaligned on the CPU, so when the GC scans this struct to see if it's pointing at anything, it sees one half as the kind_ value, and the other half is half of the pointer. 4. It misses the object being pointed at by the T inside the struct, and collects it, leaving a dangling pointer. 5. Memory corruption. when you put the void[N] member *first*, it can properly align the item (most cases where the compiler is placing data, it starts out aligned) but this does not guarantee you have proper alignment, as void[N] has no alignment constraints. I'd recommend instead, changing the uint kind_ to a size_t. This not only aligns the void[N] to size_t size, which should put any pointers in the right place, but it also makes sure the entire struct is aligned. -Steve
Re: GC and void[N] in struct
On Monday, 6 August 2018 at 19:17:58 UTC, nkm1 wrote: On Monday, 6 August 2018 at 18:22:24 UTC, vit wrote: Hello, I have this struct: struct S{ uint kind; void[N] data_; } Instances of struct S are allocated by standard GC new and S.data_ can contain pointers/ranges to GC allocated data. If is GC disabled then program run fine. But when is GC enabled then it fail randomly. If the definition of S look like this: struct S{ void[N] data_; uint kind; } then program run fine with GC.enable. Whats the problem? Something with alignment? Probably. Try something like: struct S { uint kind; align((void *).alignof) void[N] data_; } And see if it solves the problem. align((void *).alignof) work, thanks.
Re: GC and void[N] in struct
On Monday, 6 August 2018 at 18:22:24 UTC, vit wrote: Hello, I have this struct: struct S{ uint kind; void[N] data_; } Instances of struct S are allocated by standard GC new and S.data_ can contain pointers/ranges to GC allocated data. If is GC disabled then program run fine. But when is GC enabled then it fail randomly. If the definition of S look like this: struct S{ void[N] data_; uint kind; } then program run fine with GC.enable. Whats the problem? Something with alignment? Probably. Try something like: struct S { uint kind; align((void *).alignof) void[N] data_; } And see if it solves the problem.
Re: GC and void[N] in struct
On Monday, 6 August 2018 at 18:28:11 UTC, Steven Schveighoffer wrote: On 8/6/18 2:22 PM, vit wrote: Hello, I have this struct: struct S{ uint kind; void[N] data_; define "N" } Instances of struct S are allocated by standard GC new and S.data_ can contain pointers/ranges to GC allocated data. If is GC disabled then program run fine. But when is GC enabled then it fail randomly. how does it fail? -Steve private auto sizeOf(T)(){return T.sizeof;} struct ExprImpl(Ts...){ enum N = max(staticMap!(sizeOf, Ts)); invariant(kind_ != 0); uint kind_ = 0; void[N] data_; this(T)(auto ref T x){/+emplace T to data_ and change kind_ to something != 0+/} } Ts == structs data change without triggering invariant after allocation in other part of program.
Re: GC and void[N] in struct
On 8/6/18 2:22 PM, vit wrote: Hello, I have this struct: struct S{ uint kind; void[N] data_; define "N" } Instances of struct S are allocated by standard GC new and S.data_ can contain pointers/ranges to GC allocated data. If is GC disabled then program run fine. But when is GC enabled then it fail randomly. how does it fail? -Steve
GC and void[N] in struct
Hello, I have this struct: struct S{ uint kind; void[N] data_; } Instances of struct S are allocated by standard GC new and S.data_ can contain pointers/ranges to GC allocated data. If is GC disabled then program run fine. But when is GC enabled then it fail randomly. If the definition of S look like this: struct S{ void[N] data_; uint kind; } then program run fine with GC.enable. Whats the problem? Something with alignment?
Re: Prime number
On Thursday, 2 August 2018 at 14:37:56 UTC, Greatsam4sure wrote: On Thursday, 2 August 2018 at 09:35:20 UTC, Cym13 wrote: On Thursday, 2 August 2018 at 08:30:05 UTC, Greatsam4sure wrote: I know D is very powerful from my little experience. What is the idiomatic way to get prime numbers say from 1-30 without using loops(outer and inner loop). Can map, filter, fold etc in algorithm be use. Pls show some code with chain call. I can easily achieve even numberd and odd numbers using filter. But prime numbers I have to use 2loops. I will appreciate any help,just a newbie in D Denis' answer is good but I'd like to add that the idiomatic D solution is to use whatever tool is the most adequate to solve the issue. If two loops is more natural it wouldn't make much sense to force yourself to use range functions (even though I'd obviously understand that stand to learn to use them). Thanks, I like the idea of using helper function from algorithm module to do the magic instead of loops. I want to know How To optimize it to efficient. I will appreciate any help. Computing prime numbers efficiently would require something more complex like an Atkin sieve which I doubt will be very easy to implement without loop. That said, to start optimizing without changing the algorithm you can profile your code with -profile to see where you're spending time that you can shave off and rewrite the code to accelerate those parts. You should really start by changing the algorithm though. I will also appreciate a link to a comprehensive tutorial on the algorithm module. The documentation did not give me all the help I needed Not specifically on the algorithm module but I'd recommend reading [1] for a good intro to D from basics to advanced topics. For algorithms especially, I'd recommend reading on templates [2] and ranges [3]. Especially one thing you should know to understand the concepts behind most range-based functions is that most of them try to work on infinite sequences of things and therefore make assumptions only about the first items and never about the last ones. That's why functions like std.algorithm.find don't just return the element or its position but the sub-sequence starting at that element. There are exceptions though, and this comment may not make much sense at first so feel free to ignore it for the moment, but hopefully it'll come back to you when you need it. [1]: https://ddili.org/ders/d.en/index.html [2]: https://ddili.org/ders/d.en/templates.html [3]: https://ddili.org/ders/d.en/ranges.html
Re: foreach on a tuple using aliases
On 06.08.2018 14:37, Steven Schveighoffer wrote: On 8/5/18 11:40 AM, Timon Gehr wrote: On 05.08.2018 16:07, Steven Schveighoffer wrote: So is this a bug? Is it expected? It's a bug. The two copies of 'item' are not supposed to be the same symbol. (Different types -> different symbols.) Yep. I even found it has nothing to do with foreach on a tuple: https://run.dlang.io/is/vxQlIi I wonder though, it shouldn't really be a different type that triggers it, right? It shouldn't.
Re: Why does templated interface function return something different than final function?
On Thursday, 2 August 2018 at 20:35:57 UTC, Steven Schveighoffer wrote: Looking at the AST, it appears that toImpl doesn't recognize what inout(iface) is: toImpl!(string, inout(iface)) { @system string toImpl(ref inout(iface) value) { import std.array : appender; import std.format : FormatSpec, formatValue; Appender!string w = appender(); FormatSpec!char f = FormatSpec; formatValue(w, value, f); return w.data(); } } Vs. the nice neat call for const(iface) toImpl!(string, const(iface)) { @system string toImpl(const(iface) value) { return toStr(value); } } Note the ref there, too. This means it can't cast to const. I wonder if that's an issue. -Steve Thanks for the insight. To me it sounds like std.conv `toImpl` doesn't properly handle inout types in this case.
Re: dtoh
On Monday, 6 August 2018 at 13:28:05 UTC, Laeeth Isharc wrote: Hi Walter. Can dtoh be open-sourced now that dmd is? Laeeth. Better write Walter a direct mail. He doesn't check the learn NG very often.
dtoh
Hi Walter. Can dtoh be open-sourced now that dmd is? Laeeth.
Re: foreach on a tuple using aliases
On 8/5/18 11:40 AM, Timon Gehr wrote: On 05.08.2018 16:07, Steven Schveighoffer wrote: So is this a bug? Is it expected? It's a bug. The two copies of 'item' are not supposed to be the same symbol. (Different types -> different symbols.) Yep. I even found it has nothing to do with foreach on a tuple: https://run.dlang.io/is/vxQlIi I wonder though, it shouldn't really be a different type that triggers it, right? I mean 2 separate aliases to different variables that are the same type, I would hope would re-instantiate. Otherwise something like .offsetof would be wrong. Is it too difficult to fix? ... Unlikely. https://issues.dlang.org/show_bug.cgi?id=19145 -Steve
Re: foreach on a tuple using aliases
On 8/5/18 10:48 AM, Alex wrote: void main() { Foo foo; assert(isFoo!foo); static struct X { int i; Foo foo; } X x; static foreach(i, item; typeof(x).tupleof) static if(is(typeof(item) == Foo)) // line A static assert(isFoo!item); // line B else static assert(!isFoo!item); } I did try static foreach, but it doesn't work. The difference here is you are using typeof(x).tupleof, whereas I want x.tupleof. Note that in my real code, I do more than just the static assert, I want to use item as a reference to the real field in x. -Steve
Re: getProtection gives different result when member is accessed via getMember
On Sunday, 5 August 2018 at 01:48:08 UTC, Yuxuan Shui wrote: file1.d: import std.stdio; file2.d: import file1; pragma(msg, __traits(getProtection, __traits(getMember, m1, "std"))); // public pragma(msg, __traits(getProtection, m1.std)); // private Bug? Intended? reported for you https://issues.dlang.org/show_bug.cgi?id=19144
Re: getProtection gives different result when member is accessed via getMember
On Sunday, 5 August 2018 at 01:48:08 UTC, Yuxuan Shui wrote: file1.d: import std.stdio; file2.d: import file1; pragma(msg, __traits(getProtection, __traits(getMember, m1, "std"))); // public pragma(msg, __traits(getProtection, m1.std)); // private Bug? Intended? It's a bug since in both cases it's the same symbol how can the result be different ?