Re: Any way to automatically convert structs on return?
On Thursday, 1 August 2024 at 08:46:00 UTC, IchorDev wrote: P.S. You might want to put `value = void`, otherwise it’ll always be default-constructed. Doing `= void` can violate the assumptions of a destructor of T. Nullable uses a union to store T, so it can decide when to call the destructor.
Re: Prevent self-comparison without taking the address
On Thursday, 25 July 2024 at 15:06:35 UTC, IchorDev wrote: I think your function most likely has a safe interface, so it can be marked as `@trusted` as-per [the spec](https://dlang.org/spec/function.html#safe-interfaces). Just to mention that with -dip1000, taking the address of variables is allowed, so the function would be @safe.
Re: Array concatenation & optimisation
On Sunday, 21 July 2024 at 10:33:38 UTC, Nick Treleaven wrote: On Sunday, 21 July 2024 at 05:43:32 UTC, IchorDev wrote: Does this mean that array literals are *always* separately allocated first, or is this usually optimised out? My understanding is that they do not allocate if used to initialize or assign a static array. That includes passing an array literal as an argument to a static array function parameter. A scope slice can also be initialized from an array literal in @nogc code: https://dlang.org/changelog/2.102.0.html#dmd.scope-array-on-stack Another (related) case that doesn't heap allocate is when passing a literal as a scope parameter: ```d void main() @nogc { f([1,2]); } void f(scope int[]) @nogc; ``` I will look at adding these cases to the spec.
Re: Array concatenation & optimisation
On Sunday, 21 July 2024 at 10:33:38 UTC, Nick Treleaven wrote: For instance, will this example *always* allocate a new dynamic array for the array literal, and then append it to the existing one, even in optimised builds? ```d void append(ref int[] a){ a ~= [5, 4, 9]; } ``` If there is enough spare capacity in a's allocation, no allocation will occur. Sorry, I see what you mean. I've compared the -vasm output (without -O) for that function and this one: ```d void append(ref int[] a){ enum e = [5, 4, 9]; a ~= e; } ``` The ASM output is the same. If you use runtime value elements I'm not sure but I think there's still no heap allocation. I'm not good at reading ASM though.
Re: Tuple deconstruction in Phobos
On Sunday, 21 July 2024 at 04:05:52 UTC, IchorDev wrote: On Saturday, 20 July 2024 at 20:48:29 UTC, Nick Treleaven wrote: Instead of the `tie` assignment, you can just do: ```d import std.meta; AliasSeq!(y, x) = tupRetFn().expand; ``` And here I was trying to use comma expressions for this like a buffoon! Of course they didn't work, but I'm pleasantly surprised that using a sequence does. I think The lvalue sequence docs in template.dd were only updated in the last year to mention sequence assignment. I should really PR `std.typecons` to add a couple of examples of this, because I think a lot of people will have overlooked it. Good idea.
Re: Array concatenation & optimisation
On Sunday, 21 July 2024 at 05:43:32 UTC, IchorDev wrote: Obviously when writing optimised code it is desirable to reduce heap allocation frequency. With that in mind, I'm used to being told by the compiler that I can't do this in `@nogc` code: ```d void assign(ref int[4] a) @nogc{ a[] = [1,3,6,9]; //Error: array literal in `@nogc` function `assign` may cause a GC allocation } ``` Just to mention that if you assign to the static array it works: `a = [1,3,6,9];`. 'may cause' a GC allocation Does this mean that array literals are *always* separately allocated first, or is this usually optimised out? My understanding is that they do not allocate if used to initialize or assign a static array. That includes passing an array literal as an argument to a static array function parameter. A scope slice can also be initialized from an array literal in @nogc code: https://dlang.org/changelog/2.102.0.html#dmd.scope-array-on-stack But assigning a literal to a scope slice is not allowed in @nogc code. For instance, will this example *always* allocate a new dynamic array for the array literal, and then append it to the existing one, even in optimised builds? ```d void append(ref int[] a){ a ~= [5, 4, 9]; } ``` If there is enough spare capacity in a's allocation, no allocation will occur. Obviously for a long array literal, the benefit of knowing its length upfront (and the readability) would probably outweigh the allocation; but for small array literals, is splitting them into separate concatenations going to yield faster code, or will I waste my time and screen space? Note that concatenation always allocates: Concatenation always creates a copy of its operands, even if one of the operands is a 0 length array https://dlang.org/spec/arrays.html#array-concatenation P.S. I am mostly addressing LDC2 & GDC's output, since I am aware that DMD's optimisations are usually minimal. While people may say that on the forum, dmd's optimizer does actually do data flow analysis: https://forum.dlang.org/post/uqhgoi$31a7$1...@digitalmars.com
Re: Tuple deconstruction in Phobos
On Saturday, 20 July 2024 at 14:02:21 UTC, IchorDev wrote: Why does Phobos not provide a method to easily deconstruct tuples? Here's a trivial implementation: ... tie!(y, x) = tupRetFn().expand; writeln(x,", ",y); } ``` Not having this is like if Phobos didn't have `AliasSeq`. Yes you can make your own, but it's wasteful boilerplate. Instead of the `tie` assignment, you can just do: ```d import std.meta; AliasSeq!(y, x) = tupRetFn().expand; ```
Re: need help to check symbol is static variable or not
On Monday, 15 July 2024 at 06:44:12 UTC, Dakota wrote: ```d struct type_s { union { struct { int a; int b; } c; }; }; ``` `type c` will return false with `enum isStatic(alias V) = __traits(compiles, { enum v = V; });` I put `type_s` in a file anonstruct.c, then: ```d import anonstruct; pragma(msg, isStatic!(type_s.c)); ``` That outputs `false`, because the symbol is not a compile-time value. Is that what you meant?
Re: need help to check symbol is static variable or not
On Monday, 1 July 2024 at 07:32:30 UTC, Dakota wrote: this code give error: ```d static if( !__traits(compiles, mixin("enum v = V;")) ) { enum v = V; } ``` __traits(compiles, ...) can't check if a declaration is valid directly. You have to wrap it in a function literal expression: ```d enum isStatic(alias V) = __traits(compiles, { enum v = V; }); extern const float NotWorkVar; const float Works = 2; pragma(msg, isStatic!NotWorkVar); // false pragma(msg, isStatic!Works); // true ```
Re: Default struct constructors if a struct member is a union
On Saturday, 29 June 2024 at 23:33:41 UTC, solidstate1991 wrote: S foo0 = S(TypeEnum.Integer32, S(20)); //Ugly, but works S foo1 = S(TypeEnum.Integer64, S(20L)); //Error: cannot Did you mean `U(20)`? The 20 applies to the first field of the union, i32. `U(20L)` also works and (I think) it does the same because of VRP. My question is can I initialize structs like these in one line without relying on a second line? My usecase scenario doesn't really allow constructors for the struct, since it's a binding to an external library via C API. You can use a field initializer: ```d enum TypeEnum { Integer32, Integer64 } union U { int i32; long i64; float f32; double f64; } struct S { TypeEnum type; U data; } S foo0 = S(TypeEnum.Integer32, U(20)); // init i32 S foo1 = S(TypeEnum.Integer64, U(f32: 0.5F)); // struct initializer syntax S foo2 = {TypeEnum.Integer32, {20}}; S foo3 = {TypeEnum.Integer64, {f32: 0.5F}}; // init f32 void main() { assert(foo0.data.i32 == 20); assert(foo3.data.f32 == 0.5F); } ```
Re: Why `foo.x.saa.aa` and `foo.y.saa.aa` is the same? `shared_AA.saa` should still be instance variable, not class variable, right?
On Tuesday, 25 June 2024 at 02:16:25 UTC, mw wrote: Why `foo.x.saa.aa` and `foo.y.saa.aa` is the same? (and of course print out the same contents). `shared_AA.saa` should still be instance variable, not class variable, right? `saa` is an instance variable, but both `foo.x.saa` and `foo.y.saa` are initialized to the same instance of `shared_AA_class`. I think in the next edition of D we can forbid tail mutable initializers. BTW there's also another issue that the initializer is not TLS - that could probably be fixed (also in an edition) to use TLS. https://forum.dlang.org/post/sexmkjnbtxvsvodca...@forum.dlang.org
Re: How to generate a random number from system clock as seed
On Saturday, 8 June 2024 at 16:09:04 UTC, monkyyy wrote: rng is an optional parameter, `uniform(0,100).writeln;` alone works; the docs not telling you that is really bad They do tell you: urng (optional) random number generator to use; if not specified, defaults to rndGen That overload is used in the 2nd example. https://dlang.org/phobos/std_random.html#.uniform
Re: Unintentional sharing?
On Thursday, 6 June 2024 at 17:49:39 UTC, Andy Valencia wrote: I was using instance initialization which allocated a new object. My intention was this initialization would happen per-instance, but all instances appear to share the same sub-object? That is, f1.b and f2.b appear to point to a single object? Obviously I moved the new into the initializer code, but I hadn't appreciated how initial instance values were calculated once. Interestingly, this makes it similar to how Python calculates default argument values for functions. class Bar { int z = 3; } class Foo { auto b = new Bar(); } void main() { import std.stdio : writeln; auto f1 = new Foo(), f2 = new Foo(); f1.b.z = 0; writeln(f2.b.z); } This is a long standing issue: https://issues.dlang.org/show_bug.cgi?id=2947 I think with the next edition we can disallow (tail) mutable initializers for fields (and TLS globals too).
Re: How to pass in reference a fixed array in parameter
On Wednesday, 5 June 2024 at 09:24:23 UTC, evilrat wrote: for simple cases like this it might work, but 2d array is not even contiguous, A 2D static array is contiguous: https://dlang.org/spec/arrays.html#rectangular-arrays D static arrays, while using the same syntax, are implemented as a fixed rectangular layout in a contiguous block of memory
Re: How to pass in reference a fixed array in parameter
On Wednesday, 5 June 2024 at 10:27:47 UTC, Nick Treleaven wrote: foreach (i, row; maze) slices[i] = row; Sorry that assignment was wrong (edited at last minute). Fixed: ```d import std.stdio; alias s_cell = int; void main() { writeln("Maze generation demo"); s_cell [5][5] maze; int n; foreach (i, row; maze) foreach (j, col; row) maze[i][j] = n++; s_cell[][5] slices; foreach (i, _; maze) slices[i] = maze[i]; print_maze (slices); } void print_maze ( s_cell [][] maze ) { foreach (a; maze) a.writeln(); } ```
Re: How to pass in reference a fixed array in parameter
On Wednesday, 5 June 2024 at 10:27:47 UTC, Nick Treleaven wrote: //~ void print_maze ( s_cell [][] maze... ) I meant to delete that line!
Re: How to pass in reference a fixed array in parameter
On Tuesday, 4 June 2024 at 12:22:23 UTC, Eric P626 wrote: ~~~ void main() { writeln("Maze generation demo"); s_cell [5][5] maze; print_maze (maze); } void print_maze ( s_cell [][] maze ) { } ~~~ This is how to do it without GC allocations (I have used `int` instead for demo purposes): ```d import std.stdio; alias s_cell = int; void main() { writeln("Maze generation demo"); s_cell [5][5] maze = [0, 1, 2, 3, 4]; s_cell[][5] slices; // static array of 5 slices foreach (i, row; maze) slices[i] = row; print_maze (slices); } //~ void print_maze ( s_cell [][] maze... ) void print_maze ( s_cell [][] maze ) { foreach (a; maze) a.writeln(); } ```
Re: How to pass in reference a fixed array in parameter
On Wednesday, 5 June 2024 at 06:22:34 UTC, Eric P626 wrote: Now according to the book, it's possible to assign a slice from a fixed array. This code will compile: ~~~ int[12] monthDays = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ]; int[] a_slice = monthDays; ~~~ The element types are both int, so the compiler can slice the static array. As if you had written `a_slice = monthDays[];`. How come the assignment does not work when passing a parameter. I tried the following and it failed: ~~~ s_cell [5][5] maze; The element type is s_cell[5]. s_cell [][] sliced_maze = maze; The element type of sliced_maze is s_cell[], so the element types are incompatible. ~~~ void print_maze ( ref s_cell maze ) void print_maze ( ref s_cell [][] maze ) ~~~ From what I found, arrays passed in parameters are always passed by reference. So the ref keyword seems pointless. You don't need `ref` to be able to read the array length and elements. However, if you want to modify the array length, and have it affect the caller's dynamic array, you need `ref`. --- The only solution left is to use pointers. But even this does not seems to work as in C. I created a function with different pointer signature and they all fails. Normally in C, this would have worked: ~~~ s_cell [5][5] maze; create_maze(); Pass `[0][0]` instead. ~~~ Error: function `mprmaze.create_maze(s_cell[][]* maze)` is not callable using argument types `(s_cell[5][5]*)` cannot pass argument `& maze` of type `s_cell[5][5]*` to parameter `s_cell[][]* maze` ~~~ s_cell[5][5] cannot implicitly convert to s_cell[][]. Now I think it expect a 2D array of pointers instead of a pointer on a 2D array. It's also not clear if there is a difference between those 2 notations: ~~~ maze.ptr ~~~ is a pointer to s_cell[5][5]. maze.ptr is a pointer to s_cell[5]. `.ptr` means a pointer to the first element of the array.
Re: bool passed by ref, safe or not ?
On Wednesday, 5 June 2024 at 09:09:40 UTC, Kagamin wrote: On Wednesday, 5 June 2024 at 01:18:06 UTC, Paul Backus wrote: The only safe values for a `bool` are 0 (false) and 1 (true). AFAIK that was fixed and now full 8-bit range is safe. `cast(bool) someByte` is fine - that doesn't reinterpret the bit representation. The problem is certain values such as `0x2` for the byte representation can cause the boolean to be both true and false: https://issues.dlang.org/show_bug.cgi?id=20148#c3 Void initialization of bool and bool union fields are now deprecated in @safe functions as of 2.109. There is a remaining case of casting an array to bool[], which I am working on disallowing in @safe.
Re: What prevents ImportC from using .h directly?
On Sunday, 12 May 2024 at 21:34:30 UTC, Chris Piker wrote: So, why does ImportC need *.c files exclusively? I'm sure it solves a problem, but I don't know what that problem is. Support for headers has been worked on, but had to be reverted: https://issues.dlang.org/show_bug.cgi?id=23479
Re: "in" operator gives a pointer result from a test against an Associative Array?
On Friday, 10 May 2024 at 15:23:39 UTC, Andy Valencia wrote: On Friday, 10 May 2024 at 03:07:43 UTC, Steven Schveighoffer wrote: Yes, we say that a type has "truthiness" if it can be used in a condition (`while`, `if`, `assert`, etc). So if I may ask for one more small clarification... WRT "truthiness", I've observed that empty arrays are treated as false, non-empty as true. Arrays evaluate to true in boolean conditions if their `.ptr` field is non-null. This is bug-prone and I hope we can remove this in the next edition. However, although I thought a string was basically an immutable array of characters, "" is treated as true, not false? A string literal's `.ptr` field is always non-null, because it is null-terminated.
Re: Why is Phobos `Flag` so overthought ?
On Wednesday, 8 May 2024 at 10:24:07 UTC, Nick Treleaven wrote: Named arguments are optional, so I don't see how they could make Flag redundant. Actually, an external tool could detect when a bool is passed as an argument to a function and warn when not done with a named argument. This would free library APIs from having to use Flag when some users don't care about it. The cost would come in a bit more build system complexity/build time, which might mean a lot less enforcement due to inertia. Though maybe a reasonable trade-off.
Re: Why is Phobos `Flag` so overthought ?
On Thursday, 9 May 2024 at 13:40:56 UTC, cc wrote: It's pointless mandatory verbosity. StopWatch ctor only takes one boolean argument. It doesn't *need* to specify what it relates to. You either already know, or you have to look it up anyway. Flags made sense when you might get the order of multiple bools confused, but if there's only one, *or* if you can use named arguments to avoid ambiguity, So you have justified Flag. there's no point in demanding every parameter be a unique type. It's easy to remember I can pass a bool to a StopWatch to autostart it. But perhaps true means manual start? Remembering can also be used to justify dynamic typing outside of hot loops, I'd rather not rely on remembering with a big team of programmers working on a project. It's less easy to remember that a specific unique type needs to be used, and remembering whether the name/casing of that type was Start, StartNow, StartAuto, Autostart, AutoStart, autostart, autoStart, etc. So just pass it true, and run the compiler. The compiler will tell you what the correct type is. We have a tool in our box already called `true` and that solves the problem. If we had to type out the full name of every argument passed to every function ever written we may as well just adopt ObjC Cocoa style and call it StopWatchWithAutoStartBool(). Strawman.
Re: Why is Phobos `Flag` so overthought ?
On Wednesday, 8 May 2024 at 04:27:13 UTC, cc wrote: It doesn't allow a simple boolean to be used as an argument, or any other Flag as they are different instantiations of a template rather than equivalent aliases. It is however awful, cumbersome, annoying design and needs to be completely phased out now that we have named arguments. Flag enforces that the argument says what it relates to. `true` does not say what it relates to. Named arguments are optional, so I don't see how they could make Flag redundant.
Re: How can I put the current value of a variable into a delegate?
On Monday, 6 May 2024 at 06:29:49 UTC, Liam McGillivray wrote: Here's a line that caused a bug that took me awhile to find: ``` foreach(card; unitCards) card.submitted = delegate() => selectUnit(card.unit); ``` I think you can do: ```d import std.algorithm.iteration : each; unitCards.each!(c => c.submitted = () => selectUnit(c.unit)); ```
Re: How can I put the current value of a variable into a delegate?
On Monday, 6 May 2024 at 06:29:49 UTC, Liam McGillivray wrote: This is because the delegate assignment causes the local `card` variable to remain alive. The delegate that's assigned is linked to this variable itself, not the value at the time that the delegate is assigned. This is https://issues.dlang.org/show_bug.cgi?id=23136. Perhaps it can be fixed in the next edition. Is there a way I can dereference a variable when placing it in a delegate, so that it's current value is used, rather than the variable itself? I think you would need to make an array before the loop, assign to an indexed element and use that in the delegate.
Re: Turning fixed sized array into tuple
On Saturday, 4 May 2024 at 16:58:00 UTC, Dmitry Olshansky wrote: So I have a function: ```d size_t awaitAny(T...)(T args) { ... } ``` And I have: ``d Event*[4] events; `` How do I pass all 4 of events to awaitAny as tuple of arguments? Use `awaitAny(events.tupleof)`? https://dlang.org/spec/arrays.html#array-properties
Re: Phobos function to remove all occurances from dynamic array?
On Wednesday, 1 May 2024 at 01:09:33 UTC, Liam McGillivray wrote: I get compiler errors when using it on other array types. I've tried using it to replace occurrences of a certain object in an array with [] in order to remove all occurrences, but it's not allowed. Can you post a code example?
Re: Challenge Tuples
On Saturday, 27 April 2024 at 15:32:40 UTC, Nick Treleaven wrote: On Saturday, 27 April 2024 at 11:55:58 UTC, Basile B. wrote: foreach const e in u do if echo(is, e, T) do result += e; static if (is(typeof(e) == int)) r += e; Actually I would write that: ```d R r; foreach (e; v) { static if (is(typeof(e) : R)) ```
Re: Challenge Tuples
On Saturday, 27 April 2024 at 11:55:58 UTC, Basile B. wrote: Here's [STYX](https://gitlab.com/styx-lang/styx) solution: function sum[T,U](U u): u32 I think you meant `: T`. { var T result; foreach const e in u do if echo(is, e, T) do result += e; else do result += sum![T](e); return result; } function main(): s32 { assert((1, 2, 3, [1, 3], 5).sum![u32]() == 15); return 0; } Mostly equivalent D: ```d R sum(R = long, T)(T v) { R r; foreach (e; v) { static if (is(typeof(e) == int)) r += e; else r += sum!R(e); } return r; } void main() { import std; assert(tuple(1, 2, 3, [1, 3], 5).sum == 15); } ```
Re: std.traits.ParameterIdentifierTuple problem
On Sunday, 31 March 2024 at 23:05:44 UTC, Carl Sturtivant wrote: Yes, it's not possible to instantiate a function type. But with extern it seems the semantics is fine as a function is not being instantiated. It is merely associating a name with a type: in what sense is this instantiation in any reasonable way? Yes there is no instantiation for extern. But what would be the use of allowing an extern function type instance, when there's no way to instantiate it?
Re: std.traits.ParameterIdentifierTuple problem
On Saturday, 30 March 2024 at 22:37:53 UTC, Carl Sturtivant wrote: I'm inclined to a view that keeps more "it just works" options open. Regard the parameter names as a part of the type (which I am very grateful for them being currently) and just regard part of the definition of "type equality" as being to ignore parameter names when comparing types. With this viewpoint, ParameterIdentifierTuple should be repaired to work with function types just as it works with functions, and the current behavior is a bug. Maybe, but one of its unittests specifically tests that a function pointer has no parameter identifiers: ```d // might be changed in the future? void function(int num, string name) fp; static assert([ParameterIdentifierTuple!fp] == ["", ""]); ``` And changing in the future got quite a bit of push back in that PR link. This is because `fp` is declared using a function pointer type, and the author of the test did not think function pointer types should include identifiers. So it seems logical that ParameterIdentifierTuple should not give identifiers for a function type either. If a function type does include identifiers, then would two function types with the same argument types but different identifiers compare equal using `is`? Incidentally, I tried ```D extern typeof(foo) func; ``` to say that func was an actual function (`extern` so defined elsewhere) whose type was the type of the function `int foo(int num, string name, int);` so I can then use `ParameterIdentifierTuple` on a function, not a type, Nice try! but the compiler said `bug1.d(5): Error: variable ``bug1.func`` cannot be declared to be a function`. Seems unreasonable given the implied semantics. Yes, it's not possible to instantiate a function type.
Re: std.traits.ParameterIdentifierTuple problem
On Saturday, 30 March 2024 at 21:45:34 UTC, Nick Treleaven wrote: On Saturday, 30 March 2024 at 21:25:45 UTC, Carl Sturtivant wrote: OK, so how can I get them? Am I forced to take that string and parse it with CTFE? Lookup the source of ParameterIdentifierTuple and change `FunctionTypeOf!func` to just `func` inside the first `static if`. Sorry, that actually doesn't work.
Re: std.traits.ParameterIdentifierTuple problem
On Saturday, 30 March 2024 at 21:25:45 UTC, Carl Sturtivant wrote: OK, so how can I get them? Am I forced to take that string and parse it with CTFE? Lookup the source of ParameterIdentifierTuple and change `FunctionTypeOf!func` to just `func` inside the first `static if`.
Re: std.traits.ParameterIdentifierTuple problem
On Saturday, 30 March 2024 at 19:23:07 UTC, Carl Sturtivant wrote: $ dmd -c bug1.d int(int num, string name, int) ["", "", ""] bug1.d(9): Error: static assert: "wrong!" ``` Please explain. How do I get the names of the identifiers out of a parameter list at compile time reliably? Although `.stringof` on a function type does include the parameter names, the names are not really part of the type - see: https://github.com/dlang/phobos/pull/3620#issuecomment-288469685 Perhaps `ParameterIdentifierTuple` should give a compile error when given a function type.
Re: Mutate immutable inside shared static constructor
On Saturday, 23 March 2024 at 21:53:43 UTC, Jonathan M Davis wrote: Yes, it's a bug. It's a clear violation of the type system if a non-mutable variable is ever given a value more than once. It should be initialized, and then it should be treated as illegal to ever assign to it - or to do anything else which would mutate it. So, clearly, the logic in static constructors with regards to non-mutable variables is overly simple at the moment. Thanks, filed: https://issues.dlang.org/show_bug.cgi?id=24449
Mutate immutable inside shared static constructor
I've not used static constructors before, but it seems like the following should not be allowed: ```d import std.stdio; immutable int x; @safe shared static this() { x.writeln(); // 0 x = 5; x.writeln(); // 5 x = 6; x++; assert(x == 7); } ``` Should I file a bug to require that `x` is only written to once? That would make it consistent with class constructors: ```d class C { immutable int x; this() { x = 5; x = 6; // error, x initialized multiple times } } ```
Re: Mutability issue
On Saturday, 23 March 2024 at 19:30:29 UTC, Menjanahary R. R. wrote: for (T candidate = T(5); candidate * candidate <= n; candidate += T(6)) { When T is `const int`, the above code declares and initializes a constant variable: ```d const int candidate = const int(5); ``` Then, at the end of each loop iteration, it does: ```d candidate += const int(6); ``` So you are trying to modify a constant. Constants can only be initialized, never assigned. T candidate = (n % T(2) == T(0)) ? n + T(1) : n + T(2); // Start from next Odd for (;; candidate += T(2)) { // Skip even Same here, you declare a constant then try to assign to it at the end of each loop iteration.
Re: length's type.
On Friday, 9 February 2024 at 15:19:32 UTC, bachmeier wrote: It's been discussed many, many times. The behavior is not going to change - there won't even be a compiler warning. (You'll have to check with the leadership for their reasons.) Was (part of) the reason because it would disrupt existing code? If that was the blocker then editions are the solution.
Re: Providing implicit conversion of
On Monday, 22 January 2024 at 19:49:19 UTC, Siarhei Siamashka wrote: The two's complement wraparound behavior mandated by the D language spec is a non-technical political decision, intended to make life easier for the DMD compiler developers, but ignoring the needs of the users. Actually it is for compatibility when porting C code to D.
Re: Providing implicit conversion of - memory-safety
On Monday, 22 January 2024 at 19:11:50 UTC, Siarhei Siamashka wrote: On Monday, 22 January 2024 at 16:39:10 UTC, Nick Treleaven wrote: Memory safety issues are a worse class of bug than arithmetic bugs. The latter are reproducible if you feed them the same input. Memory safety bugs are reproducible with the tools like `valgrind`. Not necessarily, valgrind can execute programs too slowly for human input, so anything that relies on timing is difficult to reproduce. It also uses far more memory, it could be too much memory for the system. Whereas arithmetic overflow bugs are a real PITA to debug. Assuming that the incorrect results are even noticed. You're talking about debugging, whereas I'm saying you often don't even have a chance to *notice* memory-safety bugs, because they might not even occur on the development system, only on the production system. And even if you know there's a memory-safety problem, you can't easily narrow down where it is (without language support for memory-safety). With arithmetic problems it's far easier to narrow down which code is causing them. But I'm strongly in favour of catching any bugs at compile-time (and have been since before I discovered D). I just object to anyone trying to downgrade the importance of automated memory-safety checking.
Re: Providing implicit conversion of
On Monday, 22 January 2024 at 01:14:06 UTC, Steven Schveighoffer wrote: The language should not allow unary unsigned anything. This is unlikely to get fixed, just due to the nature of D's philosophy when it comes to C compatibility. It would also break a lot of existing code. I think the bigger issue is implicit conversion from unsigned to signed of the same bit size. In a future edition D could require a larger signed type in order to implicitly convert from unsigned. That would have caught the `long johnstone =` line. Also signed should never convert to unsigned, though I don't think that's happening here.
Re: Permutations of array (slice) ?
On Tuesday, 12 December 2023 at 16:21:46 UTC, Kevin Bailey wrote: On Tuesday, 12 December 2023 at 15:20:23 UTC, Paul Backus wrote: But unfortunately, the code shown now prints 120 lines of: b 120 being suspiciously equal to 5!. The documentation[2] seems to imply that this should be: b abaaa ... This code works for me. (The last 20+ lines are `b`): ```d import std; void main() { char[] as = replicate(['a'], 5); as[0] = 'b'; foreach (perm; as.byChar.permutations) writeln(perm); } ``` Try it on https://run.dlang.io/. Maybe there's some issue on your machine? Also if you use `string as = "abcde";` you can see the permutations better.
Re: union default initialization values
On Wednesday, 6 December 2023 at 12:38:35 UTC, Nick Treleaven wrote: Correct. So I expected a NaN output for x. However, I wasn't expecting lo == 13835058055282163712 and hi == 32767 where x is of type real, or lo == 9221120237041090560 and hi = 0 where x is of type double. Based on the default initialization rules, I expected both lo and hi to have a value of zero regardless if x is of type double or real. This is what I'm trying to understand, how are these values derived? ulong.sizeof is 8, like double.sizeof. So F.init.lo should have the same bit pattern as F.init.x because they share storage exactly. F.init.hi should be 0 and it is on my system. (*"If the union is larger than the first field, the remaining bits are set to 0"*). I don't know why you don't get zero for that. Oops, you said you did get zero in that case, so all is well. When `x` is `real`, that may overlap with `F.hi` because `real` can be more than 8 bytes.
Re: union default initialization values
On Tuesday, 5 December 2023 at 19:47:38 UTC, confuzzled wrote: On 12/6/23 4:28 AM, Adam D Ruppe wrote: On Tuesday, 5 December 2023 at 19:24:51 UTC, confuzzled wrote: Given the following union union F { double x; struct { ulong lo; ulong hi; } } The default value of this would be `double.init`, since the first member of the union is a `double`, which is a kind of NaN. This is non-zero. Correct. So I expected a NaN output for x. However, I wasn't expecting lo == 13835058055282163712 and hi == 32767 where x is of type real, or lo == 9221120237041090560 and hi = 0 where x is of type double. Based on the default initialization rules, I expected both lo and hi to have a value of zero regardless if x is of type double or real. This is what I'm trying to understand, how are these values derived? ulong.sizeof is 8, like double.sizeof. So F.init.lo should have the same bit pattern as F.init.x because they share storage exactly. F.init.hi should be 0 and it is on my system. (*"If the union is larger than the first field, the remaining bits are set to 0"*). I don't know why you don't get zero for that.
Re: Inversion of conditional compilation statements
On Saturday, 2 December 2023 at 15:03:25 UTC, ryuukk_ wrote: I wish we could use ``version`` as expression, to void the repetition: ```D import std.stdio; enum HasTest = version (Test) ? true : false; Tomek Sowiński wrote this template: ```d enum bool isVersion(string ver) = !is(typeof({ mixin("version(" ~ ver ~ ") static assert(0);"); })); static assert(isVersion!"assert"); static assert(!isVersion!"Broken"); ```
Re: D: Convert/parse uint integer to string. (@nogc)
On Monday, 27 November 2023 at 12:34:30 UTC, Nick Treleaven wrote: On Friday, 24 November 2023 at 09:35:00 UTC, BoQsc wrote: You can use std.conv.toChars: ```d void main() @nogc { int n = 515; import std.conv; char[10] s = 0; auto r = n.toChars(); assert(r.length < s.length); size_t i; foreach (c; r) s[i++] = c; import core.stdc.stdio; puts(s.ptr); } ``` Or, using std.experimental.allocator: ```d void main() @nogc { int n = 515; import std.conv; import std.experimental.allocator; import std.experimental.allocator.mallocator; alias a = Mallocator.instance; auto s = a.makeArray(n.toChars); assert(s == "515"); a.dispose(s); } ```
Re: D: Convert/parse uint integer to string. (@nogc)
On Friday, 24 November 2023 at 09:35:00 UTC, BoQsc wrote: I tried to look into https://dlang.org/phobos/std_conv.html Most of the functions inside `std.conv` seem to be dependant on [Garbage Collection](https://dlang.org/spec/garbage.html). And I couldn't find a straightforward way to produce a `string` value out of `uint` value. How to convert or parse `uint` value to a `string` in `@nogc` way? You can use std.conv.toChars: ```d void main() @nogc { int n = 515; import std.conv; char[10] s = 0; auto r = n.toChars(); assert(r.length < s.length); size_t i; foreach (c; r) s[i++] = c; import core.stdc.stdio; puts(s.ptr); } ```
Re: Struct copy constructor with inout
On Tuesday, 14 November 2023 at 13:58:17 UTC, Paul Backus wrote: On Tuesday, 14 November 2023 at 13:41:32 UTC, Steven Schveighoffer wrote: ``` Error: copy constructor `testinoutctor.S1.this(ref const(S1) s) const` is not callable using argument types `(const(S1))` ``` I'm not sure what this means. There shouldn't be a copy being made here, as the thing is already const. I don't understand this error, and it looks like a bug to me. The error is saying that the copy constructor expects a `const` `this` argument, but you're passing a mutable `this` argument. Thanks for explaining, it's a confusing error. The error when the constructor is changed to be immutable is: ``` Error: `immutable` method `immutable_ctor.S1.this` is not callable using a mutable object ``` (I've made a fix to say constructor instead of method for that.) Now I've made a fix to produce a similar error for const: https://issues.dlang.org/show_bug.cgi?id=24248
Re: dlang.org/spec/function.html#pure-functions example
On Monday, 16 October 2023 at 18:05:04 UTC, Paul wrote: On Thursday, 12 October 2023 at 21:20:44 UTC, Jonathan M Davis wrote: look like? Types can have static members. Basically what it comes down to is that outside of immutable data, pure functions only have access to their arguments and to what they can access via their arguments (be it by getting pointers from those arguments or calling other pure functions on them). - Jonathan M Davis Can I say in the general sense that when the word static is used it means that something is defined/declared at compile time? This link should describe all the uses of `static`: https://dlang.org/spec/attribute.html#static
Re: How to use ".stringof" to get the value of a variable and not the name of the variable (identifier) itself?
On Tuesday, 10 October 2023 at 11:45:25 UTC, Dennis wrote: ```D enum itoa(int i) = i.stringof; static foreach(i; 0 .. 10) { mixin(create_fn!(itoa!i)); } ``` You can also do it using a string mixin: mixin(create_fn!(mixin("`", i, "`"))); I think that's equivalent to `i.stringof` anyway.
Re: dlang.org/spec/function.html#pure-functions example
On Thursday, 12 October 2023 at 19:33:32 UTC, Paul wrote: If **int x** is global mutable state, what does static mutable state look like? In addition to Jonathan's reply, see: https://dlang.org/spec/function.html#local-static-variables
Re: how to assign multiple variables at once by unpacking array?
On Saturday, 7 October 2023 at 17:23:40 UTC, ryuukk_ wrote: there was a DIP for tuple/deconstruction prior to that question, sadly nothing came out of it, I don't think it was formally submitted. and now the language is frozen... The DIP process is temporarily suspended, it may be modified. The priority for (most of) this year is fixing bugs. However language changes do happen, e.g. just this weekend switch can now declare a variable in the condition. Atila is working on a DIP for editions.
Re: C to D: please help translate this weird macro
On Thursday, 21 September 2023 at 16:28:25 UTC, Nick Treleaven wrote: return cast(T*)(cast(void*)(cast(char*)ptr - __traits(getMember, T, member).offsetof))); There's a trailing `)` that needs removing. Also pretty sure it can be simplified to: return cast(T*)(cast(char*)ptr - __traits(getMember, T, member).offsetof);
Re: C to D: please help translate this weird macro
On Thursday, 21 September 2023 at 02:57:07 UTC, Ki Rill wrote: On Thursday, 21 September 2023 at 02:23:32 UTC, Ki Rill wrote: wrote: [...] Translated it to this eventually: ```D auto nk_container_of(P, T)(P ptr, T type, const(char)* member) { return cast(T*)(cast(void*)(cast(char*) (ptr - __traits(getMember, type, member).offsetof))); } ``` The 1st argument of `getMember` can just be T, like the original macro. The 2nd argument needs to be a compile-time string. Also the `char*` cast needs to apply to `ptr` before subtracting the offset AFAICS. So reordering to keep type inference of `ptr`: ```d auto nk_container_of(T, string member, P)(P ptr) { return cast(T*)(cast(void*)(cast(char*)ptr - __traits(getMember, T, member).offsetof))); } ``` (Untested)
Re: container vs standard array
On Tuesday, 19 September 2023 at 19:57:34 UTC, Nick Treleaven wrote: This is because a single array can be passed to a typesafe variadic parameter rather than elements of that array type. And then immutable(char) doesn't convert to string. I think a non-variadic overload could be added to make it work as expected. https://github.com/dlang/phobos/pull/8818
Re: container vs standard array
On Tuesday, 19 September 2023 at 06:35:01 UTC, JG wrote: On Tuesday, 19 September 2023 at 00:34:01 UTC, vino wrote: //auto a = Array!string("Aname"); // throws error auto b = Array!char("Bname");// works auto c = Array!string("Aname", "Bname"); // works ... Looks to me like when it receives a single range it expects the elements of that range to match the type. Yes, the first overload fails to match because U is inferred as immutable(char) rather than string: this(U)(U[] values...) if (isImplicitlyConvertible!(U, T)) This is because a single array can be passed to a typesafe variadic parameter rather than elements of that array type. And then immutable(char) doesn't convert to string. I think a non-variadic overload could be added to make it work as expected.
Re: Ideas to reduce error message size?
On Wednesday, 30 August 2023 at 09:24:21 UTC, Paolo Invernizzi wrote: src/api3.d(49):called from here: `checkSql(Schema("public", src/dget/db.d(276): Error: template instance `api3.forgeSqlCheckerForSchema!(Schema("public", **BAZILLIONS of lines**> error instantiating ``` The compiler could limit the call expression to a few lines unless the verbose flag is passed. A similar problem exists when calling a function literal which errors, the whole body is printed which can be long.
Re: toLower
On Thursday, 17 August 2023 at 09:28:05 UTC, Joel wrote: .map!(std.uni.toLower) .sort!"aonlineapp.d(8): Error: none of the overloads of template `std.algorithm.sorting.sort` are callable using argument types `!("a /dlang/dmd/linux/bin64/../../src/phobos/std/algorithm/sorting.d(1925):Candidate is: `sort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable, Range)(Range r)` with `less = "a `map` generates a range `r` whose elements can be accessed by mutable reference only if the result of calling the map function (on a source element) is a mutable reference. But `std.uni.toLower` returns by value, and `sort` requires `r.front` to be a mutable reference. I'll look at improving the docs.
Re: Why is GC.collect `pure`
On Wednesday, 2 August 2023 at 17:55:12 UTC, Nick Treleaven wrote: On Wednesday, 2 August 2023 at 17:52:00 UTC, Nick Treleaven wrote: Now I'm wondering why those functions are marked `pure` - they must affect the GC's bookkeeping state. I guess it was because the GC's internal state is not supposed to be observable outside internal GC functions. I find it harder to accept some of those than `GC.malloc` being pure, because GC.disable and GC.enable will affect how long future allocations will take. That latency can be significant and observed by the program. Also conceptually they are changing GC state.
Re: Why is GC.collect `pure`
On Wednesday, 2 August 2023 at 17:52:00 UTC, Nick Treleaven wrote: Now I'm wondering why those functions are marked `pure` - they must affect the GC's bookkeeping state. Here's the pull that added it: https://github.com/dlang/druntime/pull/3561
Re: Why is GC.collect not @safe?
On Wednesday, 2 August 2023 at 13:27:50 UTC, Steven Schveighoffer wrote: On 8/2/23 7:40 AM, Nick Treleaven wrote: Presumably an allocation like `new T` (for a type with a @safe constructor) can be made anywhere a call to `GC.collect` can be made, which may trigger a collection. So why isn't `GC.collect` marked @safe? It should be. Maybe historical reasons? One possible (but wrong) reason is that destructors can be unsafe. But you are correct in that allocation can cause a collection. OK, thanks. I've made a pull to add `@safe` for enable, disable, collect, minimize: https://github.com/dlang/dmd/pull/15493/files Now I'm wondering why those functions are marked `pure` - they must affect the GC's bookkeeping state.
Re: How to free memory ater use of "new" to allocate it.
On Sunday, 16 July 2023 at 18:18:08 UTC, Alain De Vos wrote: 12 │ ~this(){ 13 │ writeln("Free heap"); 14 │ import object: destroy; 15 │ import core.memory: GC; 16 │ i=null; // But How to force GC free ? Firstly, be careful with class destructors and GC managed objects. The memory referenced by `i` may already have been freed by the GC when the class destructor is called - see: https://dlang.org/spec/class.html#destructors If you want to free GC memory when you know the allocation is still live, you can call __delete: https://dlang.org/phobos/core_memory.html#.__delete import std.stdio: writeln; ```d void main() { int[] i=null; writeln("Allocate heap"); i=new int[1]; i[9000]=5; import core.memory; const p = i.ptr; assert(GC.addrOf(p) !is null); writeln("Free heap"); __delete(i); assert(GC.addrOf(p) is null); } ```
Re: is ref inout redundant in: ref inout(T) opIndex(size_t index)
On Monday, 19 June 2023 at 18:19:18 UTC, mw wrote: 2) `inout T` alone Steve covered everything, though you might also like to read the inout spec: https://dlang.org/spec/const3.html#inout
Re: Given an object, how to call an alias to a member function on it?
On Wednesday, 3 May 2023 at 11:26:00 UTC, ag0aep6g wrote: On 03.05.23 13:13, Nick Treleaven wrote: void fun(alias method)(C c) { void delegate() dg = dg(); } No, it doesn't. You're not using the alias. You're just accessing `c.method` directly. If the actual method weren't called "method", you'd get an error. Sorry, you're right.
Re: Given an object, how to call an alias to a member function on it?
On Tuesday, 2 May 2023 at 13:06:41 UTC, ag0aep6g wrote: void fun(alias method)(C c) { void delegate() dg; dg.funcptr = dg.ptr = cast(void*) c; dg(); } This also works: void fun(alias method)(C c) { void delegate() dg = dg(); }
Re: Why are globals set to tls by default? and why is fast code ugly by default?
On Monday, 27 March 2023 at 08:44:41 UTC, wjoe wrote: e.g.: It used to be faster to ... - pre-calculate sin/cos tables, now the memory look up cost more cycles than the calculation itself ... - only redraw the parts of the screen that changed, now the branching is slower than to redraw everything Good to know, thanks. another example is sorting - Alexei wrote a blog post about how a stupid and slow sorting algorithm now performs better in multi threading. Maybe someone remembers the title/url of the post ? Not sure, but that reminds me of Andrei's blog on partitioning (for quicksort): https://dlang.org/blog/2020/05/14/lomutos-comeback/ The algorithm traditionally considered slower can be faster because it can be optimized to work better with branch prediction.
Re: Why are globals set to tls by default? and why is fast code ugly by default?
On Sunday, 26 March 2023 at 20:36:37 UTC, ryuukk_ wrote: Golang doesn't even have thread local storage, yet they do very well Go doesn't have a solution to preventing data races at compile time, they just say don't share memory. But what if you accidentally share memory? That is *very* easy to do in Go. You and your users are out of luck. All you can do is run the race detector and pray that you happen to test all the code paths with it that might have data races: The race detector only finds races that happen at runtime, so it can't find races in code paths that are not executed https://go.dev/doc/articles/race_detector
Re: Why are globals set to tls by default? and why is fast code ugly by default?
On Sunday, 26 March 2023 at 20:39:21 UTC, ryuukk_ wrote: if my code doesn't do threads, why should i put my variable into TLS? I don't think writing __gshared is much of a burden. You can use -vtls to print out all variables that are TLS, and add that to an automated test to check you don't have any accidentally. I have thought before that a --no-threads compiler switch that does not link the key thread functions but makes __gshared the default might be a good enhancement for your use case. Then if you accidentally call some code that uses std.parallelism internally you would get a link error. If i want fast code, why should i make use of ugly syntax? 1. If you want fast code, why aren't you using threads? 2. By default D supports threads and accidental data races are far worse than ugly syntax.
Re: Why are globals set to tls by default? and why is fast code ugly by default?
On Sunday, 26 March 2023 at 20:39:21 UTC, ryuukk_ wrote: if my code doesn't do threads, why should i put my variable into TLS? I don't think writing __gshared is a huge burden. You can use -vtls to print out all variables that are TLS, and add that to an automated test to check you don't have any accidentally. I have thought before that a --no-threads compiler switch that does not link the key thread functions but makes __gshared the default might be a good option for your use case. Then if you accidentally call some code that uses std.parallelism internally you would get a link error. If i want fast code, why should i make use of ugly syntax? By default D supports threads and accidental data races are far worse than ugly syntax.
Re: Why are globals set to tls by default? and why is fast code ugly by default?
On Sunday, 26 March 2023 at 18:07:03 UTC, ryuukk_ wrote: What i find even more weird is writing fast code is ugly in D Look at this ugly code ```D __gshared int fast_code_ugly; ``` Because it should be rare that __gshared is used. And if you need it, you won't be worried about how the storage class looks because you'll be concentrating on if your design is thread-safe. It should be the opposite Then by default, @safe code can not access global variables and there can easily be accidental races between threads.
Re: templates and traits
On Saturday, 18 March 2023 at 19:22:07 UTC, Chris Katko wrote: ... So there's multiple sub-problems to solve. I asked this years ago, and got 90% of the way done and then lost the code and cannot find the original forum post. Maybe it was this?: https://forum.dlang.org/post/dqzxnctucwvyhstfz...@forum.dlang.org
Re: Is comparison of shared data thread-safe?
On Thursday, 16 March 2023 at 12:32:34 UTC, Nick Treleaven wrote: With -preview=nosharedaccess, I get: int y = 2; shared int x = y; // OK assert(x == 2); // no error y = x; // error This also does not error: ```d bool b = x == 3; ``` Filed: https://issues.dlang.org/show_bug.cgi?id=23783
Is comparison of shared data thread-safe?
With -preview=nosharedaccess, I get: int y = 2; shared int x = y; // OK assert(x == 2); // no error y = x; // error So for the assignment to y, reading x is an error and atomicLoad should be used instead. But is it an oversight that reading x in the assert is not an error? I have also found this in a unittest in core.atomic: shared(size_t) i; atomicOp!"+="(i, cast(size_t) 1); assert(i == 1); Is the assert somehow thread-safe?
Re: Non-ugly ways to implement a 'static' class or namespace?
On Friday, 20 January 2023 at 11:28:23 UTC, thebluepandabear wrote: ``` final abstract class Algo { void drawLine(Canvas c, Pos from, Pos to) { .. }; } ``` This solution seems like a bit of a hack, which is why I don't like it. Interesting solution if you put `static:` in there. Alternatively you could create a module, but then it would just be a function without a clear type. Why do you want a type? Is anyone aware of a non-ugly way to implement a 'static' class or namespace? Use a struct and put `static:` after the opening brace. That's what GC is in core.memory.
Re: Where I download Digital Mars C Preprocessor sppn.exe?
On Monday, 23 January 2023 at 17:15:30 UTC, Nick Treleaven wrote: On Saturday, 2 April 2022 at 21:57:02 UTC, Marcone wrote: Where I download Digital Mars C Preprocessor sppn.exe? I need it to use ImportC Found this thread by googling `dlang sppn.exe`. For the record, it can be obtained from sppn.zip here: http://ftp.digitalmars.com/ I didn't have it for some reason even though latest dmc is installed. I then got some weird errors building druntime: std::array not supported by DMC std::basic_string_view not supported by DMC I figured that dmc was not correctly installed (not sure why). So I downloaded dmc.zip which fixed it.
Re: Where I download Digital Mars C Preprocessor sppn.exe?
On Saturday, 2 April 2022 at 21:57:02 UTC, Marcone wrote: Where I download Digital Mars C Preprocessor sppn.exe? I need it to use ImportC Found this thread by googling `dlang sppn.exe`. For the record, it can be obtained from sppn.zip here: http://ftp.digitalmars.com/ I didn't have it for some reason even though latest dmc is installed.
Re: Preventing nested struct destructor accessing stack frame
On Tuesday, 20 December 2022 at 06:31:09 UTC, ag0aep6g wrote: On 16.12.22 14:07, Nick Treleaven wrote: This seems to work: ~this() @trusted { if ( > cast(void*)1024) i++; } It would be better if there was a struct property to get the context pointer though. A quick test suggests that the context pointer is the last item in `tupleof`. So this might do the trick: ~this() { if (this.tupleof[$ - 1] !is null) i++; } I don't know if it's guaranteed to work though. Might be an implementation detail. Great, thanks. The struct tupleof docs just link to the class tupleof docs, which say: The order of the fields in the tuple matches the order in which the fields are declared. So I think for a struct the context pointer has to come after any fields.
Re: Unique!struct bug - Re: unique_ptr | Unique for autoclose handle
On Thursday, 15 December 2022 at 20:12:12 UTC, Ali Çehreli wrote: I think this is a bug because the documentation clearly talks about destroying the object: OK: https://github.com/dlang/phobos/pull/8651 > do we need to do some kind of deprecation? The behavior is so different from the intention that I don't think anybody is using Unique anyway. :o) Yes, at least for structs.
Re: Preventing nested struct destructor accessing stack frame
On Friday, 16 December 2022 at 12:17:40 UTC, Nick Treleaven wrote: It seems destroy clears the context pointer. Is there a way to test if the context pointer is null in the dtor, to prevent the increment? This seems to work: ~this() @trusted { if ( > cast(void*)1024) i++; } It would be better if there was a struct property to get the context pointer though.
Preventing nested struct destructor accessing stack frame
This code segfaults when the GC calls the dtor after the unittest succeeds: ```d unittest { int i; struct S { ~this() { i++; } } (*new S).destroy; } ``` It seems destroy clears the context pointer. Is there a way to test if the context pointer is null in the dtor, to prevent the increment?
Re: pointer escaping return scope bug?
On Thursday, 15 December 2022 at 20:02:38 UTC, Nick Treleaven wrote: auto f() return @trusted => p ? p : v.ptr; Whoops, that can't be @trusted unless I `assert(p)`.
Re: pointer escaping return scope bug?
On Saturday, 19 November 2022 at 15:24:33 UTC, Dukc wrote: On Saturday, 19 November 2022 at 15:02:54 UTC, Nick Treleaven wrote: OK, so how do I make `lf` implicitly scope? Have the `int*` inside it to point to a local, or assign another `scope int*` to it. Thanks, this works: ```d @safe: struct S { int* p; int[0] v; // dummy storage auto f() return @trusted => p ? p : v.ptr; } void main() { int* p; { S s = S(new int); p = s.f; // error } } ```
Unique!struct bug - Re: unique_ptr | Unique for autoclose handle
On Wednesday, 14 December 2022 at 17:41:07 UTC, Ali Çehreli wrote: I've never used Unique but I think it has a bug (or a design issue?): Its destructor is the following: ~this() { if (_p !is null) { destroy(_p); _p = null; } } Because _p is a pointer, destroy(_p) will not dereference and destroy what it points to. I think this is a bug with Unique. I think it should do destroy(*_p); Now filed: https://issues.dlang.org/show_bug.cgi?id=23561 Do you think it's OK to just fix this or do we need to do some kind of deprecation?
Re: printf, writeln, writefln
On Thursday, 8 December 2022 at 17:39:58 UTC, Ali Çehreli wrote: On 12/8/22 08:21, Salih Dincer wrote: > void stringCopy(Chars)(string source, > ref Chars target) >sample.stringCopy = cTxt; // disappeared ? char Nothing disappeared on my system. (?) Going off-topic, I find the expression above extremely confusing. I am used to assignment expression changing the value of the left hand side, but that expression changes cTxt. Very confusing... Such obfuscations make it very hard for me to understand what the code is trying to demonstrate. Yes, with function call syntax it's more understandable if an argument is modified. It was bizarre and confusing that assignment syntax was implemented for functions and methods not explicitly marked with @property.
Re: How ptr arithmitic works??? It doesn't make any sense....
On Sunday, 4 December 2022 at 16:33:35 UTC, rempas wrote: struct MemoryBlock { char* ptr; ulong length; } (MemoryBlock.sizeof is 16 on my 64-bit system). void* ptr = cast(void*)0x7a7; void* right() { return cast(MemoryBlock*)(ptr + MemoryBlock.sizeof); // Cast the whole expression between paranthesis. Got the right value! } The above adds 16 bytes to ptr. void* wrong() { return cast(MemoryBlock*)ptr + MemoryBlock.sizeof; // First cast the `ptr` variable and then add the number. Got a wronge value... } The above adds 16 * MemoryBlock.sizeof bytes (16 * 16) to ptr, because ptr is cast first. Should be `+ 1` to be equivalent. https://dlang.org/spec/expression.html#pointer_arithmetic "the resulting value is the pointer plus (or minus) the second operand **multiplied by the size of the type pointed to by the first operand**." char* return_address_wrong() { MemoryBlock* local_ptr = cast(MemoryBlock*)ptr; return cast(char*)(local_ptr + MemoryBlock.sizeof); // Casted the whole expression. BUT GOT THE WRONG VALUE Why??? } Because you are adding to a pointer that points to a 16-byte block, rather than a void* which points to a single byte. char* return_address_right() { MemoryBlock* local_ptr = cast(MemoryBlock*)ptr; return cast(char*)local_ptr + MemoryBlock.sizeof; // Now I first casted the `local_ptr` variable and then added the number but this time this gave me the right value } The casted pointer points to a single byte.
Re: pointer escaping return scope bug?
On Friday, 25 November 2022 at 15:03:57 UTC, ShadoLight wrote: I don't grok how `lf` can survive the local scope. Or am I missing something? Perhaps because the local scope is not pushed as a separate (anonymous) function on the stack... if true then, yes, then `lf` will indeed have the same physical lifetime as main (and `p`)...? On the other hand, if you add a destructor to `LockedFile`, it will be invoked at the end of the local scope, not the end of main. Yes, the actual code does have a destructor. It's analogous to this: ```d @safe: struct S { private int* fps; auto fp() return scope => fps; this(int) { fps = new int; } @disable this(); @disable void opAssign(S); ~this() @trusted // how do we make this safe? { import core.memory; GC.free(fps); } } void main() { int* p; { auto lf = S(5); p = lf.fp; } assert(p != null); // address escaped } ``` That compiles with -dip1000. D doesn't seem to have a way to prevent the memory outliving the struct. Just to note there is another problem when the struct is destroyed explicitly whilst the `fp` result is still live. But that could be solved by making `object.destroy` and `std.algorithm.move` be restricted to @system for certain structs like this one (either opt-in or some other mechanism). The first problem doesn't seem to have a solution.
Re: pointer escaping return scope bug?
On Saturday, 19 November 2022 at 14:52:23 UTC, ag0aep6g wrote: That's essentially just a function that returns its pointer parameter. So the program boils down to this: @safe: int* fp(return scope int* p) { return p; } void main() { int* p; { auto lf = new int; p = fp(lf); } assert(p != null); // address escaped } Which is fine, as far as I can tell. `lf` is not `scope`. And when you pass it through `fp`, the result is still not `scope`. So escaping it is allowed. You do get an error when you make `lf` `scope` (explicitly or implicitly). So everything seems to be in order. OK, so how do I make `lf` implicitly scope?
pointer escaping return scope bug?
Hi, The following seems like a bug to me (reduced code, FILE* changed to int*): ```d @safe: struct LockedFile { private int* fps; auto fp() return scope => fps; } void main() { int* p; { auto lf = LockedFile(new int); p = lf.fp; } assert(p != null); // address escaped } ``` There's no error with -dip1000. I'll file this unless I overlooked something.
Re: Hipreme's #2 Tip of the day - Reducing .di files dependency
On Sunday, 23 October 2022 at 20:12:46 UTC, Hipreme wrote: For reducing a D Interface file dependency when generating it with the `-H` flag for DMD, you can't import a module on the top level. Take a look at that example: This would make a nice blog post if you have one ;-)
Re: Remove elements without losing capacity
On Tuesday, 4 October 2022 at 18:18:41 UTC, Ali Çehreli wrote: A related topic is how the "end slice" never loses that capacity: void main() { auto a = [ 1, 2 ]; auto b = a; assert(a.capacity != 0); assert(b.capacity != 0); b.length--; assert(b.capacity == 0); assert(a.capacity != 0);// <-- Preserved } Aside: .capacity is an expensive operation that requires some levels of table lookups in the druntime. A data structure would benefit a lot if it kept its own capacity as a member variable. I've now made a pull to document this: https://github.com/dlang/dlang.org/pull/3445
Re: rotate left an array
On Monday, 3 October 2022 at 18:09:05 UTC, Fausto wrote: Hello all, I am trying to rotate left an array. I found a very basic way, and I am not sure if there is something clever than this :) maybe using slices... Here we can't use slice assignment instead of the inner loop because that doesn't work for an overlapping slice. (Instead there's `copy` in std.algorithm). The algorithm you wrote doesn't scale the best for speed - yours is the second one mentioned here: https://www.geeksforgeeks.org/array-rotation/ Phobos has `bringToFront(arr[0..2], arr[2..$])` which does the same thing as a `rotate(arr, 2)` function. It seems to use the third algorithm from the link (or at least has the same time and space complexity). The first algorithm may also work better in some cases, when swapping is expensive or when the result is duplicated anyway.
Re: Linker Error with Template Function
On Tuesday, 13 September 2022 at 03:00:17 UTC, Kyle Ingraham wrote: Any suggestions for being able to call one function for any instance given but maintain flexible return types? Not sure if it helps, but you can define final methods in an interface, which can call virtual interface methods: ```d interface PathConverter { string getValue(); final T toD(T)() { import std.conv : to; return to!T(getValue()); } } ``` Not tested as AFK.
Re: Tracing out error that causes compiler crash
On Sunday, 4 September 2022 at 20:48:52 UTC, solidstate1991 wrote: What do I pass as the tester? You can use a script as described here: https://github.com/CyberShadow/DustMite/wiki/Detecting-a-segfault-in-dmd-itself
Re: Tracing out error that causes compiler crash
On Saturday, 3 September 2022 at 21:20:01 UTC, solidstate1991 wrote: During unittest in my own fork of std.experimental.xml (link: https://github.com/ZILtoid1991/experimental.xml ), potentially an error so severe is present, that it causes to crash the compiler (both DMD and LDC2, on Windows). I was able to separate the issue by commenting out all unittests, then re-enabling them one-by-one seeing when it crashes the compiler, but wasn't able to track down the issues. However, `domimpl.d` is a 2000+ line monster, with a huge templated class that nests multiple other classes. You may be able to use dustmite to automatically reduce the code to a minimal test case: https://dlang.org/blog/2020/04/13/dustmite-the-general-purpose-data-reduction-tool/ Send my regards to the planet smasher.
Re: How to build DMD/Phobos on Windows
On Thursday, 25 August 2022 at 07:22:32 UTC, bauss wrote: We really need a page in the documentation that describes how to build each component of D for each major platform. There is on the wiki, but it's out of date: https://wiki.dlang.org/Building_under_Windows build.d works for dmd, but I haven't been able to build druntime for a while, even before the repo was merged into dmd's. (What I do is just rename and move dmd to a folder with existing druntime installed, but that doesn't really work beyond simple uses as it gets out of sync as the implementation changes). Last time I tried digger, even that didn't work. This is a problem.
Re: Convert array of tuples into array of arrays.
On Wednesday, 31 August 2022 at 14:34:50 UTC, musculus wrote: Hi. I have an array of tuples that I would like to convert to an array of arrays. All of the elements in the tuples have matching types (string). How would I go about doing this? Thanks! Assuming std.typecons.Tuple, you can use `[tup.expand]` to make an array from a tuple. If you mean a value sequence, you can use `[valSeq]`.
Re: Fix template parameter
On Wednesday, 10 August 2022 at 06:15:39 UTC, Dom Disc wrote: Ok, then I consider this is a bug in Phobos that should be corrected. All instances of ```D foo(T : fixedType)(T x) { } ``` should be replaced by ```D foo(fixedType x) { } ``` Perhaps, but not necessarily. The body of foo could do introspection on T with static if or overloaded functions and produce specialised code. Even if foo doesn't do that, perhaps the author reserves the right to do that in future. Or perhaps it needs to be a template to infer attributes. For that case, using an empty template parameter list would be clearer.
Re: Why are immutable array literals heap allocated?
On Friday, 5 July 2019 at 23:05:32 UTC, Jonathan M Davis wrote: Yes, I was wondering why the compiler doesn't statically allocate it automatically as an optimization. It would have to be set up to store the literal somewhere else. I was thinking the read-only data segment. Certainly, it can't just put it on the stack, because that risks it going out of scope and causing memory problems. It It can do that with small-ish sized literals if they don't escape (-dip1000). I think Walter may have advocated something like this. This one can be done even with literals of mutable elements. no matter what optimizations the compiler does with array literals, that shouldn't affect whether the function can be @nogc. For it to affect that, it would have to be something that was guaranteed by the language's semantics regardless of whether any optimizations were being done. Yes, just like string literals I think static allocation can be part of the language for immutable data.
Re: Why are immutable array literals heap allocated?
On Thursday, 4 July 2019 at 11:06:36 UTC, Eugene Wissner wrote: static immutable arr = [1, 2]; You have to spell it out that the data is static. Yes, I was wondering why the compiler doesn't statically allocate it automatically as an optimization.