Re: Limits of implicit conversion of class arrays
On Saturday, 23 March 2024 at 11:04:04 UTC, Dmitry Olshansky wrote: On Saturday, 23 March 2024 at 09:08:45 UTC, Per Nordlöw wrote: Is there a reason why ```d class Base {} class Derived : Base {} @safe pure nothrow unittest { Base b; Derived d; b = d; // pass Base[] bs; Derived[] ds; bs ~= ds; // pass bs = ds; // fail [1], should pass bs = cast(Base[])ds; // fail [2], should pass } ``` fails as [1]: cannot implicitly convert expression `ds` of type `Derived[]` to `Base[]` [2]: cast from `Derived[]` to `Base[]` not allowed in safe code ? The first and second is unsound (infamously allowed in Java). Once you cast the slice you can populate it with Derived2 objects that are not Derived, hence breaking type safety of the ds slice. — Dmitry Olshansky CEO @ Glow labs https://olshansky.me Note that it works if the classes are const: ```d const(Base)[] bs; const(Derived)[] ds; bs ~= ds; // pass bs = ds; // pass bs = cast(const(Base)[])ds; // pass ``` Exactly because you can't replace existing entries.
Re: Setting field of struct object
On Monday, 22 January 2024 at 08:54:54 UTC, zjh wrote: On Monday, 22 January 2024 at 08:27:36 UTC, Joel wrote: ```d import std; struct Person { string name, email; ulong age; auto withName(string name) { this.name=name; return this; } auto withEmail(string email) { this.email=email; return this; } auto withAge(ulong age) { this.age=age; return this; } } void main() { Person p; p.withName("Tom").withEmail("joel...@gmail.com").withAge(44); writeln(p); } ``` VS:`C++` ```d struct Person { string name, email; ulong age; } Person a{"n","email",33}; ``` D: ```d import std.stdio; struct Person { string name, email; ulong age; } void main() { Person p = Person(name: "n", email: "email", age: 33); writefln!"%s"(p); } ```
Re: Delegates and values captured inside loops
On Saturday, 20 January 2024 at 15:59:59 UTC, Anonymouse wrote: I remember reading this was an issue and now I ran into it myself. ```d import std.stdio; void main() { auto names = [ "foo", "bar", "baz" ]; void delegate()[] dgs; foreach (name; names) { dgs ~= () => writeln(name); } foreach (dg; dgs) { dg(); } } ``` Expected output: `foo`, `bar`, `baz` Actual output: `baz`, `baz`, `baz` If I make `names` an `AliasSeq` it works, but I need it to be a runtime array. Is there a workaround? ``` foreach (name; names) { dgs ~= ((name) => () => writeln(name))(name); } ``` lol
Re: Nested delegates and closure allocations
On Tuesday, 16 January 2024 at 15:39:07 UTC, Anonymouse wrote: If I make a `scope` variable of the delegate and pass *it* to `receiveTimeout`, there no longer seems to be any mention of the closure in the error (given 2.092 or later). ```d void foo(Thing thing) @nogc { void sendThing(const string where, int i) { send(thing, where, i); } scope scopeSendThing = receiveTimeout(Duration.zero, scopeSendThing); } ``` Ignoring that it doesn't compile for other reasons; provided `scope scopeSendThing = ` compiles -- as in, `` is eligible for `scope` -- is this a valid workaround? Correct. The problem is that `receiveTimeout` is defined as a template variadic function: it *can* take a scoped function, but it doesn't (can't) declare that its argument is always scoped, so since scoped parameters are opt-in, it defaults to unscoped. And has to also default to unscoped, because you can pass unscoped values to scoped parameters but not the other way around, so it defaults to the most generic type available. With your scoped variable you provide DMD the critical hint that actually you want the closure to be scoped, and once the value is scoped it stays scoped.
Re: Nested delegates and closure allocations
On Tuesday, 16 January 2024 at 10:56:58 UTC, Anonymouse wrote: I'm increasingly using nested delegates to partition code. ```d void foo(Thing thing) { void sendThing(const string where, int i) { send(thing, where, i); } sendThing("bar", 42); } ``` ... 3. Those referenced stack variables that make up the closure are allocated on the GC heap, unless: * The closure is passed to a scope parameter. * The closure is an initializer for a scope variable. * The closure is assigned to a scope variable. I'm generally not storing the delegates or passing them around as values, so I don't think the thing about scope variables and parameters *directly* applies. Am I safe as long as I don't do something like, pass `` as an argument to `std.concurrency.receive`? Yes.
Re: Trying to understand map being a template
On Saturday, 6 January 2024 at 17:57:06 UTC, Paul Backus wrote: On Friday, 5 January 2024 at 20:41:53 UTC, Noé Falzon wrote: In fact, how can the template be instantiated at all in the following example, where no functions can possibly be known at compile time: ``` auto do_random_map(int delegate(int)[] funcs, int[] values) { auto func = funcs.choice; return values.map!func; } ``` Thank you for the insights! It works for the same reason this example works: ```d void printVar(alias var)() { import std.stdio; writeln(__traits(identifier, var), " = ", var); } void main() { int x = 123; int y = 456; printVar!x; // x = 123 printVar!y; // y = 456 x = 789; printVar!x; // x = 789 } ``` To clarify, what this actually compiles to is: ```d void main() { int x = 123; int y = 456; void printVar_x() { import std.stdio; writeln(__traits(identifier, x), " = ", x); } void printVar_y() { import std.stdio; writeln(__traits(identifier, y), " = ", y); } printVar_x; printVar_y; x = 789; printVar_x; } ``` Which lowers to: ```d struct mainStackframe { int x; int y; } void printVar_main_x(mainStackframe* context) { import std.stdio; writeln(__traits(identifier, context.x), " = ", context.x); } void printVar_main_y(mainStackframe* context) { import std.stdio; writeln(__traits(identifier, context.y), " = ", context.y); } void main() { // this is the only "actual" variable in main() mainStackframe frame; frame.x = 123; frame.y = 456; printVar_main_x(); printVar_main_y(); frame.x = 789; printVar_main_x(); } Same with `map`.
Re: Dirty DMD
On Saturday, 18 November 2023 at 18:52:07 UTC, JN wrote: Latest DMD for Windows downloaded from here: https://downloads.dlang.org/releases/2.x/2.105.3/dmd-2.105.3.exe reports version as dirty: DMD64 D Compiler v2.105.3-dirty Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved written by Walter Bright what does it mean by dirty? Oops. It means whoever built it had uncommitted changes in their version of the code. It's probably harmless though - somebody trying to smuggle in changes could just disable that annotation.
Re: Request you advise : isValidFilename
On Friday, 22 September 2023 at 17:52:51 UTC, FeepingCreature wrote: "Integer representation" here refers to the ANSI index or Unicode codepoint, ie. the filename must not contain `\x00` to `\x31`. Er oops, make that `\x00` to `\x1f`.
Re: Request you advise : isValidFilename
On Friday, 22 September 2023 at 17:44:50 UTC, Vino wrote: Hi All, Request you help in understanding why the below code is always returning true when it should return false as per the documentation. Documentation ``` filename must not contain any characters whose integer representation is in the range 0-31. ``` "Integer representation" here refers to the ANSI index or Unicode codepoint, ie. the filename must not contain `\x00` to `\x31`.
Re: dlang custom keyword for struct/class
On Sunday, 17 September 2023 at 15:55:37 UTC, Vitaliy Fadeev wrote: Is it possible to write like this in D? ```d struct Message { ulong timestamp; } Message LongMessage { ubyte[255] s; } // // it mean // // struct LongMessage // { // Message _super; // alias _super this; // ubyte[255] s; // } // // or // // struct LongMessage // { // ulong timestamp; // ubyte[255] s; // } ``` Is it possible? No, there's no struct inheritance. But you can just write the `alias this` version manually.
Re: isBinary
On Sunday, 3 September 2023 at 10:11:22 UTC, Vino wrote: Hi All, Any update as to when the function described in the below ticked would be action-ed, I am more interested in isBinary (check a file whether is is binary file or not) http://d.puremagic.com/issues/show_bug.cgi?id=9455 From, Vino Those are totally different ideas. When writing a file, some operating systems support line ending conversion. To do that, you explicitly specify that you are writing to a text file. Then a "binary file" is just any file that is not a text file. However, this is merely a conversion process on writing. You cannot discover whether a file is a binary file in reverse. At most you can check whether *you yourself* opened the file as a binary file.
Re: pointer to std.algorithm.iteration : splitter
On Thursday, 31 August 2023 at 05:16:02 UTC, Vino wrote: Hi All, Request your help on the below error Program ``` void main() { import std.stdio:writeln; import std.algorithm.iteration : splitter; auto splitter_ptr = !((a, b) => a.splitter(b).array); string str = "TEST1;TEST2;TEST3"; auto words = splitter_ptr(str, ';'); foreach (word; words) { writeln(word); } } ``` ``` Error: template instance `splitter!((a, b) => a.splitter(b).array)` does not match any template declaration ``` From, Vino Why are you trying to take pointers of lots of different things? You should pretty much never need pointers in normal D code.
Re: File size
On Tuesday, 22 August 2023 at 16:22:52 UTC, harakim wrote: On Monday, 21 August 2023 at 11:05:36 UTC, FeepingCreature wrote: Can you print some of the wrong sizes? D's DirEntry iteration code just calls `FindFirstFileW`/`FindNextFileW`, so this *shouldn't* be a D-specific issue, and it should be possible to reproduce this in C. Thanks for the suggestion. I was working on getting the list for you when I decided to first try and reproduce this on Linux. I was not able to do so. Then I opened the Linux File Explorer and went to one of the files. There were two files by that name, with names differing only by case. In windows, I only saw one, because Windows Explorer only supports one file with an identical case-insensitive name per directory. Unsurprisingly, that is also the one that was selected by getSize(filename). The underlying windows functions must ignore case as well and select the same way as Explorer (which makes sense). That explains why Windows Explorer reported the same size as getsize(name) in every case, while DirEntry.size would match for the file with the same case as windows recognized and not for the file with a different case. I was able to get into this state because I copied the files (merged directories) in Linux. It was interesting to look into. It seems everything is working as designed. It shouldn't be an issue for me going forward either as I move more and more towards Linux. That's hilarious! I'm happy you found it.
Re: File size
On Monday, 21 August 2023 at 07:52:28 UTC, harakim wrote: I have been doing some backups and I wrote a utility that determines if files are an exact match. As a shortcut, I check the file size. So far so good on this with millions of files until I found something odd: getSize() and DirEntry's .size are producing different values. ... It seems really odd that getSize(sourceFile.name) is returning a different number than sourceFile.size. This is an external HDD on windows formatted in ntfs that it is reading. I believe I originally wrote the files to the file system in Windows, but then today I cut and paste them (in the same drive) in Linux. However, this is the first time this has happened after millions of comparisons and it only happened for about 6 files. It does happen consistently though. I have verified that the file size is that reported by getSize and not sourceFile.size and that the files open correctly. ... Can you print some of the wrong sizes? D's DirEntry iteration code just calls `FindFirstFileW`/`FindNextFileW`, so this *shouldn't* be a D-specific issue, and it should be possible to reproduce this in C.
Re: Finding duplicate elements
On Tuesday, 15 August 2023 at 17:59:27 UTC, vino wrote: Hi All, Request your help in finding duplicate element without sorting as per the below example ``` Example: string[] args = [" test3", "test2 ", " test1 ", " test1 ", " "]; Output Required: If duplicate element found then print "Duplicate element found: " else print ["test3", "test2", "test1"]; ``` From, Vino.B ``` import std; void main() { string[] args = [" test3", "test2 ", " test1 ", " test1 ", " "]; findDuplicates(args); } void findDuplicates(string[] args) { bool[string] dupes; foreach (arg; args) { if (arg in dupes) { writefln!"Duplicate element found: %s"(arg); return; } dupes[arg] = true; } writefln!"%s"(dupes.keys); } ```
Re: toLower
On Tuesday, 15 August 2023 at 20:09:28 UTC, Joel wrote: On Tuesday, 15 August 2023 at 16:54:49 UTC, FeepingCreature wrote: But does *not* import `std.ascii`! So there's no ambiguity inside the `sort` string expression between the two `toLower` functions.. How do I get it to work? I tried std.ascii.toLower. And using alias toLower=std.ascii.toLower; To elaborate more, `toLower` doesn't work because function-scope aliases are not considered for UFCS. ``` alias toLower = std.ascii.toLower; ... // So this does actually work: .map!toLower // but this does not, because it looks for a UFCS-capable symbol .map!(c => c.toLower) // but this does again .map!(c => toLower(c)) ```
Re: toLower
On Tuesday, 15 August 2023 at 16:47:36 UTC, Joel wrote: How come toLower works in the sort quotes, but not in the map? ```d void main() { import std; "EzraTezla" .to!(char[]) .byCodeUnit .sort!"a.toLower c.toLower) .writeln; } ``` When you pass a string to a lambda, it's evaluated in `std.functional.unaryFun`/`binaryFun`. At that point, these modules are imported for use in string expressions: ``` import std.algorithm, std.conv, std.exception, std.math, std.range, std.string; import std.meta, std.traits, std.typecons; ``` And `std.string` itself publically imports: ``` public import std.uni : icmp, toLower, toLowerInPlace, toUpper, toUpperInPlace; ``` But does *not* import `std.ascii`! So there's no ambiguity inside the `sort` string expression between the two `toLower` functions..
Re: On assigning const to immutable
On Thursday, 13 July 2023 at 11:55:17 UTC, Ki Rill wrote: Why does the first example `class A` work, but the second one with `class B` does not? ```D class A { immutable int a; this(in int a) { this.a = a; } } class B { immutable int[] b; this(in int[] b) { this.b = b; } } void main() { auto a = new A(1); auto b = new B([1, 2]); } ``` It implicitly converts `const` to `immutable`, but fails to do the same with an array. Is it intentional? Why? Yep: `immutable` is data that *cannot ever* change. If you could convert `int[]` to `immutable int[]`, you could do this: ``` int[] a = [2]; immutable(int)[] b = a; auto first = b[0]; a[0] = 3; auto second = b[0]; // Wait, this fails? I thought `b` was immutable. assert(first == second); ``` Use `array.idup` (immutable dup) to turn `int[]` into `immutable int[]`. And you can convert `int` to `immutable int` because it's a "value copy": you cannot mutate the immutable variable through an assignment to the original. Generally speaking, only the constness of referenced data matters for assignment. That's why you can assign `string` to `immutable string`, because `string` is `immutable(char)[]`: the referenced data is immutable in both cases.
Re: Dynamic array of strings and appending a zero length array
On Saturday, 8 July 2023 at 17:15:26 UTC, Cecil Ward wrote: I have a dynamic array of dstrings and I’m spending dstrings to it. At one point I need to append a zero-length string just to increase the length of the array by one but I can’t have a slot containing garbage. I thought about ++arr.length - would that work, while giving me valid contents to the final slot ? What I first did was arr ~= []; This gave no errors but it doesn’t increase the array length, so it seems. Is that a bug ? Or is it supposed to do that? You can append an element to an array. You can also append an array to an array. Because [] can be an array of any type, the compiler guesses that it's an empty `string[]` array and appends it to no effect.
Re: Inheritance and arrays
On Monday, 3 July 2023 at 09:50:20 UTC, Arafel wrote: Hi! I am a D user coming from java, rather than from C/C++ (although obviously also have some exposure to them), and thus apparently one of the few people here who likes OO (within reason, of course). So while I appreciate the fact that D closely follows java's design, I wonder why there is no implicit inheritance for arrays (also the same applies to AAs): ```d interface I {} class C : I {} void main() { I i; C c = null; i = c; // Works I[] ii; C[] cc = null; // ii = cc; // Doesn't work: Error: cannot implicitly convert expression `cc` of type `C[]` to `I[]` ii = cast (I[]) cc; // Works, but why do I need to cast? } ``` The `cast` version "works", but will crash at runtime. In D, as opposed to Java, a reference to an object has a *different pointer value* than a reference to the interface-typed version of that object. This is necessary for efficient compiled virtual method calls on the interface. But for the same reason, you cannot reinterpret an array of objects to an array of interfaces; even if you can implicitly convert each object to that interface, there's a difference between automatically rewriting a value and automatically rewriting every element of an array: one is O(1), the other is O(n) and incurs a GC allocation.
Re: Inheritance and arrays
On Monday, 3 July 2023 at 09:50:20 UTC, Arafel wrote: Hi! I am a D user coming from java, rather than from C/C++ (although obviously also have some exposure to them), and thus apparently one of the few people here who likes OO (within reason, of course). So while I appreciate the fact that D closely follows java's design, I wonder why there is no implicit inheritance for arrays (also the same applies to AAs): ... Is this a conscious design decision (if so, why?), or just a leak of some implementation detail, but that could eventually be made to work? See also this thread on implementation details: https://forum.dlang.org/post/bibtjiiwpiqzzfwgx...@forum.dlang.org
Re: Bug in usage of associative array: dynamic array with string as a key
On Friday, 30 June 2023 at 19:05:23 UTC, Cecil Ward wrote: I have code roughly like the following: dstring str = "name"d; uint ordinal = (( str in Decls.ordinals ) !is null) ? Decls.ordinals[ str ] : -1; struct Decls { uint[ dstring] ordinals; } //and Decls.ordinals[ str ] = ordinal_counter++; The problem is that it always returns ordinal== -1 from the expression. Can you sort me out? Impossible to tell without a complete repro, I'm afraid. The expression, at least, looks correct at first glance. Note that you can do `uint ordinal = Decls.ordinals.get(str, -1);`.
Re: static if - unexpected results
On Friday, 23 June 2023 at 18:43:06 UTC, Steven Schveighoffer wrote: It should be a spec change. Change POD to say "type" instead of "struct". The goal of `isPOD` is to determine how careful generic code needs to be to pass the type around, or copy it. Changing it to false implies that it is not "plain old data". I.e. it has a destructor, it has hidden members, or it cannot be copied via bit copying (all of these do not fit the type in question). The only other option is to error on calling `__traits(isPOD, char)`, but I think that's even worse. -Steve Yeah, I think that's also where I'm standing. The current behavior seems correct and useful, it's just not documented correctly.
Re: static if - unexpected results
On Friday, 23 June 2023 at 14:22:24 UTC, DLearner wrote: Hi Was looking for compile-time detection of a struct variable. However, the following test code gave the two 'FAILS' shown below. Comments? ``` void main() { import std.stdio : writeln; import std.traits; string mxnTst(string VarName) { return `static if (is(typeof(` ~ VarName ~ `) == char)) {` ~ `writeln("` ~ VarName ~ ` ", " is a char");` ~ `} else static if (__traits(isPOD, typeof(` ~ VarName ~ `))) {` ~ `writeln("` ~ VarName ~ ` ", " is a struct");` ~ `} else static if (is(typeof(` ~ VarName ~ `) == int)) {` ~ `writeln("` ~ VarName ~ ` ", " is an int");` ~ `} else {` ~ `static assert(false, "mxnTst Variable '` ~ VarName ~ `' is of unknown type");` ~ `}` ; } char char1; int int1; byte byte1; struct foo { int fooint; char foochar; } foo foovar1; mixin(mxnTst("char1")); // Expected: char1 is a char. Actual: char1 is a char. (ok) mixin(mxnTst("int1"));// Expected: int1 is an int. Actual: int1 is a struct. (FAIL) mixin(mxnTst("foovar1")); // Expected: foovar1 is a struct. Actual: foovar1 is a struct. (ok) mixin(mxnTst("byte1")); // Expected: Run to fail with the static assert message. Actual: byte1 is a struct. (FAIL) } ``` ``` static assert(__traits(isPOD, int)); // ok. static assert(__traits(isPOD, byte)); // ok. ``` It's a bug in either the spec or the compiler.
Re: Strange behaviour of __traits(allMembers)
On Sunday, 18 June 2023 at 10:21:16 UTC, IchorDev wrote: On Sunday, 18 June 2023 at 10:04:14 UTC, FeepingCreature wrote: On Sunday, 18 June 2023 at 09:48:40 UTC, IchorDev wrote: Does anyone understand why this happens? Is there any way to subvert this behaviour, or is it actually a bug? Yes, see also my bug report, https://issues.dlang.org/show_bug.cgi?id=20008 "__traits(allMembers) of packages is complete nonsense". Whaat why has this not been fixed in the last 4 years! I think because nobody *needs* `__traits(allMembers)` of packages. Mostly people just learn to skip them while scanning modules, and instead of iterating imports, they do the standard hack of "generate a list of all files in the project, string import it, and generate import statements for each". Yeah it's ugly. I guess the lesson is, nothing takes as long to fix as a bug with a well-known workaround.
Re: Strange behaviour of __traits(allMembers)
On Sunday, 18 June 2023 at 09:48:40 UTC, IchorDev wrote: Does anyone understand why this happens? Is there any way to subvert this behaviour, or is it actually a bug? Yes, see also my bug report, https://issues.dlang.org/show_bug.cgi?id=20008 "__traits(allMembers) of packages is complete nonsense".
Re: undefined reference to "main"
On Wednesday, 5 April 2023 at 09:19:17 UTC, Alexander Zhirov wrote: How to compile the example given in the book correctly? When compiling, an error occurs that the main function is missing. If I replace `shared static this()` with `void main()', then everything starts. What does the compilation string in `dub` and `dmd` look like correctly? ```d import vibe.d; shared static this() { auto settings = new HTTPServerSettings; settings.port = 8080; settings.bindAddresses = ["::1", "127.0.0.1"]; listenHTTP(settings, ); logInfo("Please open http://127.0.0.1:8080/ in your browser."); } void hello(HTTPServerRequest req, HTTPServerResponse res) { res.writeBody("Hello, World!"); } ``` This seems to work for me: ```d /+ dub.json: { "name": "test", "dependencies": { "vibe-d": "*" } } +/ import vibe.d; shared static this() { auto settings = new HTTPServerSettings; settings.port = 8080; settings.bindAddresses = ["::1", "127.0.0.1"]; listenHTTP(settings, ); logInfo("Please open http://127.0.0.1:8080/ in your browser."); } void main() { runApplication; } void hello(HTTPServerRequest req, HTTPServerResponse res) { res.writeBody("Hello, World!"); } ``` Run with ``` dub run --single test.d ```
Re: Can nice D code get a bit slow?
On Wednesday, 8 March 2023 at 10:49:32 UTC, Markus wrote: So, having no clue about D (just bought some books), I wanted to ask if nice looking code can become slow, in general. In the mentioned case it's just that I like the packaging of functions into some sort of scope (OOP) versus the flat C and Go stuff. I like OOP for this reason, but now I'm unsure whether I might stay out of creating classes at all. Uh, hope you understand my vague question, sorry about that. I found D to be the right place because it's not missing any essential feature I know of. Kind regards If you write D like Java, it will be slow like Java - actually slower, because D's GC isn't as good. If you remember to use structs for value types (no `class Vector3f`, `class Point` etc.), you should be fine. Though as a general rule, don't worry about it too much. Even slow D is still fast.
Re: How would the equivalent C type be in D?
On Wednesday, 1 March 2023 at 09:37:48 UTC, rempas wrote: Thank you! You are amazing for explaining it! I was so focused on thinking that I'm doing something wrong with the type that I didn't noticed that the pointers, points to nowhere so the function obviously has nowhere to write to. Like... OMG! And I want to make a fully fledged compiler when making stupid mistakes like that. Btw, When I executed the program, I got "Error Program exited with code -11". You said that the code was "11". What about that dash? If it is not a "minus" and it's just the dash symbol, then what's the idea? Yay! (Definitely make a compiler, it's a great way to learn.) Yes, that is a bit weird. First of all, the actual signal is 11 ``` $ grep SIGSEGV /usr/include/bits -R /usr/include/bits/signum-generic.h:#define SIGSEGV 11 /* Invalid access to storage. */ ``` As per the POSIX spec https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_21_18. signal exits must be reported with exit codes above 128. Customarily, shells will simply add 128 to the signal: ``` $ cat test.c; gcc test.c -otestc; ./testc; echo $? int main() { int* ip = 0; *ip = *ip; return 0; } Segmentation fault 139 ``` 139 being 128 + 11, but POSIX does not specify *how* the signal code is converted to an exit code. For instance, Python reports a signal 11 exit as -11. Strictly speaking, -11 is "above 128" in two's complement, corresponding to unsigned 245. But I don't know why Python does this. Presumably your shell does it the same way?
Re: How would the equivalent C type be in D?
On Wednesday, 1 March 2023 at 09:37:48 UTC, rempas wrote: Thank you! You are amazing for explaining it! I was so focused on thinking that I'm doing something wrong with the type that I didn't noticed that the pointers, points to nowhere so the function obviously has nowhere to write to. Like... OMG! And I want to make a fully fledged compiler when making stupid mistakes like that. Btw, When I executed the program, I got "Error Program exited with code -11". You said that the code was "11". What about that dash? If it is not a "minus" and it's just the dash symbol, then what's the idea? Yay! Yes, that is a bit weird. First of all, the actual signal is 11 ``` $ grep SIGSEGV /usr/include/bits -R /usr/include/bits/signum-generic.h:#define SIGSEGV 11 /* Invalid access to storage. */ ``` As per the POSIX spec https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_21_18. signal exits must be reported with exit codes above 128. Customarily, shells will simply add 128 to the signal: ``` $ cat test.c; gcc test.c -otestc; ./testc; echo $? int main() { int* ip = 0; *ip = *ip; return 0; } Segmentation fault 139 ``` 139 being 128 + 11, but POSIX does not specify *how* the signal code is converted to an exit code. For instance, Python reports a signal 11 exit as -11. Strictly speaking, -11 is "above 128" in two's complement, corresponding to unsigned 245. But I don't know why Python does this. Presumably your shell does it the same way?
Re: How would the equivalent C type be in D?
On Wednesday, 1 March 2023 at 08:26:07 UTC, FeepingCreature wrote: ```d uint32_t[1] value; value[0] = screen.black_pixel; xcb_create_gc(connection, black, win, mask, value.ptr); ``` To expand on this: ```d uint32_t[2] value; uint32_t* value_ptr = value.ptr; // We are allowed to access the pointer at index 0 // because we declared the value it points to, to be size 2. value_ptr[0] = 0; // This is also allowed, because `value_ptr` is // a pointer to two sequential `uint32_t` in memory. value_ptr[1] = 0; // But this access would segfault, because it's trying to write // to the third element of a two-element array: value_ptr[2] = 0; ``` Note: I just lied; `value_ptr[2]` would not segfault, for somewhat technical reasons; but it *would* corrupt your program's memory. At any rate, it's an invalid operation.
Re: How would the equivalent C type be in D?
On Wednesday, 1 March 2023 at 08:12:05 UTC, rempas wrote: I'm looking into [this](https://www.x.org/releases/X11R7.7/doc/libxcb/tutorial/index.html) tutorial to learn XCB and I'm trying to write the code in D with betterC. In the section 9.1 (sorry, I cannot give a section link, the article does not give us this ability), I'm facing a problem and my program exits with the exit code: "-11". I suspect that this happens because I haven't translated the following code the right way: ```d uint32_t value[1]; value[0] = screen.black_pixel; xcb_create_gc(connection, black, win, mask, value); ``` I originally tried to translate this as: ```d uint[1] value; value[0] = screen.black_pixel; xcb_create_gc(connection, black, win, mask, value); ``` But then, when I tried to compile the program, I got the following error: ``` Error: function `headers.xcb_create_gc(xcb_connection_t* c, uint cid, uint drawable, uint value_mask, const(void)* value_list)` is not callable using argument types `(xcb_connection_t*, uint, uint, uint, uint[1])` src/draw.d(18,16):cannot pass argument `value` of type `uint[1]` to parameter `const(void)* value_list` ``` So I thought of doing the following: ```d uint* value; value[0] = screen.black_pixel; xcb_create_gc(connection, black, win, mask, value); ``` Now the program complies but I get the "-11" exit code. Another thing I thought (which is probably the same thing under the hood but done a different way): ```d const(void)* value; (cast(ubyte*)value)[0] = screen.black_pixel; xcb_create_gc(connection, black, win, mask, value); ``` Same results. Any ideas? 11 is SIGSEGV. A segfault, or access violation, happens when you try to access unallocated memory. In this case, let me annotate your code so it's easier to see what's happening: ```d // null is the default value for a pointer uint* value = null; // because `value` is null, the first index also lies at null. assert([0] is null); // So we try to store screen.black_pixel at memory address null, which is unallocated. value[0] = screen.black_pixel; xcb_create_gc(connection, black, win, mask, value); ``` As there is no memory segment allocated at address null, the CPU indicates a segmentation fault, which terminates the program. So yes, `xcb_create_gc` wants a `uint*` parameter, but not just any `uint*` will do: it has to point to valid memory. Going back to the first snippet, what's happening here is that in C, arrays implicitly convert to pointers, because C doesn't have a notion of array types as distinct from pointer types. So you can have a variable declared as `uint[1]`, but pass it to a parameter that expects `uint*`, and the value that is passed will just be the address of the first field of the array. However, even in C, if you try to define `value` as `uint*`, it will segfault in the same way. Instead, in D, you need to tell the compiler to define an array of size 1, and then pass a pointer to the array's first member explicitly: ```d uint32_t[1] value; value[0] = screen.black_pixel; // this is what C does under the hood xcb_create_gc(connection, black, win, mask, [0]); ``` Or shorter, but with the same effect: ```d uint32_t[1] value; value[0] = screen.black_pixel; xcb_create_gc(connection, black, win, mask, value.ptr); ```
Re: Non-ugly ways to implement a 'static' class or namespace?
On Monday, 20 February 2023 at 07:11:49 UTC, Mike Parker wrote: On Monday, 20 February 2023 at 06:26:34 UTC, FeepingCreature wrote: There have now been three pages produced by three people all agreeing with each other. At what point does it start being spam? Yes, it's all just noise now. Let's end it here. Further posts in this thread will be deleted. oy vey, shut it down fucking idiot
Re: Non-ugly ways to implement a 'static' class or namespace?
On Monday, 20 February 2023 at 05:21:44 UTC, forky wrote: On Friday, 10 February 2023 at 07:04:31 UTC, Max Samukha wrote: ... Having class-private doesn't preclude module-private. Dennis even submitted a PR implementing class-private, but it stalled because people couldn't agree on whether class-private should be "private to class" or "private to class instance". It likely the 'disagreement' was intentional .. i.e. to stall ;-) But in any case, it should be class private. There have now been three pages produced by three people all agreeing with each other. At what point does it start being spam?
Re: Non-ugly ways to implement a 'static' class or namespace?
On Thursday, 16 February 2023 at 02:27:23 UTC, Mike Parker wrote: On Thursday, 16 February 2023 at 02:26:44 UTC, Mike Parker wrote: Wrong. I'm arguing things: Geez. "I'm arguing 2 things:" Springboarding off this post: This thread is vastly dominated by some people who care very much about this issue. Comparatively, for instance, I care very little because I think D already does it right. But then the thread will look unbalanced. This is a fundamental design flaw in forum software. So let me just say: I think D does it right. D does not have class encapsulation; it has module encapsulation. This is by design, and the design is good.
Re: Is defining get/set methods for every field overkill?
On Tuesday, 22 November 2022 at 21:45:29 UTC, []() {}() wrote: On Tuesday, 22 November 2022 at 21:00:58 UTC, []() {}() wrote: "Being able to declare a “friend” that is somewhere in some other file runs against notions of encapsulation." (This is the motivation for that article it seems). I completely disagree with the assertion. C++ Friend notion does not, not by any means, run against the notion of encapsulation. Sure, it expands the perimeter (i.e. it puts a door in the wall). But, and this is my point, there is a guard standing at the door. And that guard knows who has been authorised to pass through it. The encapsulation remains. Only its perimeter has been expanded. One could argue that D's approach is just that. It expands the perimeter to the module level. But there's no guard at the door in D. Surely, this 'let anyone pass through' design, decreases encapsulation? How could it possibly increase encapsulation, as claimed, by the author of that article? If there were a means in the language for controlled sharing within a module, *that* would increase encapsulation. The module is the capsule. D is simply not interested in building a capsule around a class. D does not let "anyone" pass through, it lets "anyone in the module" pass through, because the module is the wall. I think this is a stronger concept of encapsulation than C++ friends because the encapsulation is lexical rather than just declarative.
Re: Is defining get/set methods for every field overkill?
On Thursday, 17 November 2022 at 04:39:35 UTC, thebluepandabear wrote: I am creating a TUI library and I have a class with the following constant fields: ``` class Label : Renderable { const string text; const TextAlignment textAlignment; const Color color; this(Dimensions dimensions, string text, TextAlignment textAlignment, Color color) { this.dimensions = dimensions; this(text, textAlignment, color); } this(string text, TextAlignment textAlignment, Color color) { this.text = text; this.textAlignment = textAlignment; this.color = color; } override Cell[] render() const { Cell[] cells; for (int x = 0; x < 0 + text.length; ++x) { cells ~= Cell(Coordinates(x, 0), text[x], color); } return cells; } } ``` I am debating whether or not I should add getter methods to these properties. On one hand, it will inflate the codebase by a lot, on the other hand -- in other languages like Java it is a good practice: ``` class Label : Renderable { private const string text; private const TextAlignment textAlignment; private const Color color; this(Dimensions dimensions, string text, TextAlignment textAlignment, Color color) { this.dimensions = dimensions; this(text, textAlignment, color); } this(string text, TextAlignment textAlignment, Color color) { this.text = text; this.textAlignment = textAlignment; this.color = color; } string getText() const { return text; } TextAlignment getTextAlignment() const { return textAlignment; } Color getColor() const { return color; } override Cell[] render() const { Cell[] cells; for (int x = 0; x < 0 + text.length; ++x) { cells ~= Cell(Coordinates(x, 0), text[x], color); } return cells; } } ``` It's not a lot of code that has been added but if you have a class with say 10 different fields, adding getter methods would definitely increase the code size by a lot, so what are you guys thoughts on this? Obligatory note that boilerplate https://code.dlang.org/packages/boilerplate exists for just this reason: class Label : Renderable { @ConstRead private const string text_; @ConstRead private const TextAlignment textAlignment_; @ConstRead private const Color color_; this(Dimensions dimensions, string text, TextAlignment textAlignment, Color color) { this.dimensions_ = dimensions; this(text, textAlignment, color); } override Cell[] render() const { Cell[] cells; for (int x = 0; x < 0 + text.length; ++x) { cells ~= Cell(Coordinates(x, 0), text[x], color); } return cells; } mixin(GenerateFieldAccessors); mixin(GenerateThis); }
Re: "chain" vs "~"
On Sunday, 7 August 2022 at 01:22:18 UTC, pascal111 wrote: Why we use "chain" while we have "~": '''D int[] x=[1,2,3]; int[] y=[4,5,6]; auto z=chain(x,y); auto j=x~y; ''' Chain doesn't allocate any memory. This can be useful occasionally.
Re: Obsecure problem 1
On Sunday, 31 July 2022 at 07:43:06 UTC, Salih Dincer wrote: Why are you using const for strings? After all, they are protected by immutable. Moreover, since you do not use refs, copies are taken in every function and also you have created extra copy for results. Note sure if I'm misunderstanding, but: D does not copy strings on value passing, because they're inherently reference types. You can think of a string (or any array) as a `struct { size_t length; T* ptr; }` combined with a bunch of syntax magic.
Re: alias this - am I using it wrong?
On Wednesday, 25 August 2021 at 12:11:01 UTC, Johann Lermer wrote: Hi all, I have a little problem understanding alias this. I always thought, that alias this only makes implicit conversions from the aliased object to this. Then, why do lines 18 and 22 compile in the code below? And, btw, line 22 crashes with a segmentation fault. ```d 01 struct Test_Struct {long t;} 02 03 class Alias_Class 04 { 05 Test_Struct ts; 06 alias ts this; 07 } 08 09 class Test_Class 10 { 11 Alias_Class ac; 12 } 13 14 void main () 15 { 16 auto ac = new Alias_Class; 17 Test_Struct ts = ac; // compiles 18 ac = ts; // compiles as well - why? 19 20 auto tc = new Test_Class; 21 ts = tc.ac; // compiles 22 tc.ac = ts; // again this compiles, but seg faults 23 } ``` Johann ts is a field. You can assign to a field. So when the field is aliased to this, you can assign to the field through a class reference. You can disable this behavior by creating a getter in Alias_Class, then aliasing it to this: ``` class Alias_Class { Test_Struct ts; Test_Struct getter() { return ts; } alias getter this; } ```
Re: using "invariant" with structs ... possible to call when a field value is set??
On Sunday, 8 August 2021 at 11:30:41 UTC, james.p.leblanc wrote: Hello, With structs, I understand that "invariant checking" is called (from dlang tour): It's called after the constructor has run and before the destructor is called. It's called before entering a member function invariant() is called after exiting a member function. But, is is possible to have the invariant checking be performed whenever a field is directly set? For example, suppose a struct "S", has a field "x". I would like to have invariance check in cases such as: S.x = 4; Maybe there is a hidden set field function that gets called that might be exploitable?? Thoughts on this? Possible? Better paths that I should consider? Best Regards, James You can make a field set function like so: ``` struct S { private int x_; int x(int value) { return this.x_ = value; } int x() { return this.x_; } } ``` This will then run invariants. (boilerplate can automate that for you. https://code.dlang.org/packages/boilerplate cough self-advertisement cough)
Re: General rule when not to write ;
On Tuesday, 18 May 2021 at 16:27:13 UTC, Alain De Vos wrote: After each } i write a ; And let the compiler tell me it is an empty instruction. What are the general rules where ; is not needed after a } Is `;` ever needed after a `}`? I guess in `void delegate() dg = { writeln!"Hello World"; };`, but that hardly counts, because it belongs to the variable declaration, not the `{}`.
Re: What are virtual functions?
On Sunday, 18 April 2021 at 23:04:26 UTC, ShadoLight wrote: On Wednesday, 14 April 2021 at 14:06:18 UTC, FeepingCreature wrote: On Wednesday, 14 April 2021 at 13:43:20 UTC, Berni44 wrote: [..] Covariance is related ... [..] The opposite (contravariance) happens ... [..] Nice answer but, just to be clear - D only supports covariance on return types at the moment, and doesn't support contravariance on parameters, right? I remember contravariance being periodically requested in the past but, AFAICR, it has not been implemented, right? A quick search through the forums didn't turn anything up either... and this does not compile: ``` class A {} class B : A {} class Y { public void bar (B b) {} } class X : Y { public override void bar (A a){} } ``` ... That doesn't work?! Holy hell. I mean, run.dlang.io confirms, but ... *why not*?! If you already support return type covariance, parameter contravariance should be easy. It's the same thing! You don't need to do anything! Any B is directly a valid A! Like, sure, there's versions of this that don't trivially work, like mixing interface and class parents, but direct superclass contravariance should be easy. ... Weird. I don't get it. Reading https://issues.dlang.org/show_bug.cgi?id=3075 seems like it collides with overloading. Except ... it doesn't. Because you can't implement multiple overloaded methods with contravariance in a subclass, because it doesn't work for interfaces anyway (cause they occupy a different interface slot in the class and so aren't strictly Liskov.) So the selection of the function to override is still unambiguous. I don't get it.
Re: What are virtual functions?
On Wednesday, 14 April 2021 at 13:43:20 UTC, Berni44 wrote: I'm trying to understand, what virtual functions are. I found the [specs](https://dlang.org/spec/function.html#virtual-functions), but I can't make head or tail of it. - What is a `vtbl[]`? Obviously a function pointer table. But where to find this? The examples don't use it. Maybe something inside of the compiler? - Which of the eight functions in the example are virtual and and which not? OK B.abc is said to be virtual, as the comment states. But it seems never to be used. And why is it considered to be virtual? - There is also the term "covariant function", which is not explained. What is this? Recommended reading: https://en.wikipedia.org/wiki/Liskov_substitution_principle This is all related to object-oriented programming and class inheritance. Because we can put a subclass object into a superclass variable (`class Child : Parent { }; Parent parent = new Child;`), we cannot look at the *type* of an object variable to decide which methods to call, because the object itself may be of a subtype. As such, when we call a method `foo` on `Parent`, the compiler looks up the class info in a pointer in the first 8 bytes of the object, finds the method pointer for `foo`, and calls it with the object as a hidden parameter. (This is the `this` field.) So a virtual method is a method that is called "virtually", as compared to directly by name, by turning the method name into a function pointer call via the classinfo. The list of function pointers for methods in the class info is called the virtual method table, or vtable. Covariance is related to the Liskov principle, and just means that because `Child` can be treated as a `Parent`, a method that returns `Parent` in the superclass can be overridden (its vtable pointer replaced with a new one) by one that returns a `Child` in the subclass. In other words, as "Child class replaces Parent class", the "return type `Child`" can replace the "return type `Parent`"; ie. in the child class you can use a child class of the return type, ie. they "vary together" - covariance. The opposite (contravariance) happens for parameters: if a superclass method takes `Child`, the subclass can take `Parent` instead - again, because `Child` can turn into `Parent` per Liskov. A different way to think about this is that method parameter and return types form a contract that is defined by the superclass and fulfilled by the subclass, and the subclass can relax the call contract ("I demand from my caller") and restrict the return contract ("I promise my caller"). Since the `Child`, by Liskov, can do everything the `Parent` can do, demanding less - ie. a `Parent` instead of a `Child` - keeps the superclass's call contract valid, and promising more - ie. returning a `Child` instead of a `Parent`, which may have additional capabilities - keeps the superclass's return contract valid.
Re: byte array to string
On Thursday, 25 February 2021 at 06:47:11 UTC, Mike wrote: hi all, If i have an array: byte[3] = [1,2,3]; How to get string "123" from it? Thanks in advance. string str = format!"%(%s)"(array);
Re: byte array to string
On Thursday, 25 February 2021 at 06:57:57 UTC, FeepingCreature wrote: On Thursday, 25 February 2021 at 06:47:11 UTC, Mike wrote: hi all, If i have an array: byte[3] = [1,2,3]; How to get string "123" from it? Thanks in advance. string str = format!"%(%s)"(array); Er sorry, typo, that should be "%(%s%)". "Print the elements of the array, separated by nothing." Compare "%(%s, %)" for a comma separated list.
Re: Foo Foo = new Foo();
On Sunday, 21 February 2021 at 18:07:49 UTC, JN wrote: class Foo { } void main() { Foo Foo = new Foo(); } this kind of code compiles. Is this expected to compile? Yes, why wouldn't it? main is a different scope than global; you can override identifiers from global in main. And "Foo" only exists after the declaration, so it doesn't conflict.
Re: 200-600x slower Dlang performance with nested foreach loop
On Wednesday, 27 January 2021 at 02:14:39 UTC, H. S. Teoh wrote: Yes, definitely try this. This will completely eliminate the overhead of using an AA, which has to allocate memory (at least) once per entry added. Especially since the data has to be sorted eventually anyway, you might as well sort first then use the sortedness as a convenient property for fast de-duplication. Since .uniq traverses the range linearly, this will be cache-friendly, and along with eliminating GC load should give you a speed boost. T Associative arrays allocate per entry added?! https://github.com/dlang/druntime/blob/master/src/rt/aaA.d#L205 Oh God, associative arrays allocate per entry added!
Re: F*cked by memory corruption after assiging value to associative array
On Monday, 25 January 2021 at 11:15:28 UTC, frame wrote: After a while my program crashes. I'm inspecting in the debugger that some strings are overwritten after a struct is assigned to an associative array. - I have disabled the GC. - All happens in the same thread. - The strings belong to an object collection inside an object created from a d-DLL. - The object returned by the DLL function is added to the GC with GC.addRoot(). - This object also lives in a static array the whole time. - Not all objects are affected but many. - The struct itself looks okay also the key for the associative array has normal form. The data is not overwritten by another Thread (only one is running) but by the compiler. I'm watching it by memory location. It gets always visible first after that assignment. But how is this even possible? In theory, how could I ran into this issue? That should really not be possible. I suspect the memory used by the original data got reused for the associative array somehow. But if the GC is off from program start, that should really not occur. Do you maybe turn the GC off before the AA assignment, but after it's already marked that memory freed? Try turning it off completely from the commandline with --DRT-gcopt=gc:manual
Re: Handling referencing class parent instances in a GC friendly way.
On Monday, 30 November 2020 at 14:33:22 UTC, realhet wrote: Hi, class A{ A parent; A[] items; void myDestroy(){ items.each!(i => i.myDestroy); parent = null; // after this point I think the GC will release it automatically, and it will call ~this() too. Am I right? } } I have a hierarchy of class instances forward and backward linked to its items ant its parent. What is a proper way to destroy an instance of class A? Is calling instance.myDestroy sufficient? Am I right that this kind of uninitialization MUST not go into the ~this() destructor, because of the references the instance is holding, the system will never call the ~this()? Or is there a better way for this type of thing in Dlang? Thanks in advance! The GC will release it anyways. The advantage of a GC is that it is not deterred by cyclic references, so as soon as no more references into A exist, it will disappear, no matter the parent pointer. At least, that's the theory - in practice, since we don't have precise stack GC, any spurious or leftover pointer to an A can keep the whole tree alive, so the myDestroy cleanup method is still valid and recommended. Though you may want to do `items = null;` too.
Re: `enum x;` - what is it?
On Wednesday, 19 August 2020 at 14:43:22 UTC, Victor Porton wrote: On Wednesday, 19 August 2020 at 14:06:16 UTC, Victor Porton wrote: This declaration does compile: enum x; But what is it? Is it an equivalent of enum x { } ? What in the specification allows this looking a nonsense enum x; ? Oh, found: "An empty enum body (For example enum E;) signifies an opaque enum - the enum members are unknown." But what this "unknown" does mean? How "unknown" differs from "none" in this context? The specification is unclear. It does not define the meaning of unknown. I will submit a bug report. It means exactly what it says. The compiler doesn't know what members are in the enum. So you can't declare a variable of it, you can't use it directly.. you can p much only use it in pointers.
Re: `enum x;` - what is it?
On Wednesday, 19 August 2020 at 14:06:16 UTC, Victor Porton wrote: This declaration does compile: enum x; But what is it? Is it an equivalent of enum x { } ? What in the specification allows this looking a nonsense enum x; ? It's an enum type whose members we don't know. So we can't declare "x var;" but we can declare "x* var;". It's the enum version of "struct SomeExternCStruct;".
Re: D on lm32-CPU: string argument on stack instead of register
On Tuesday, 4 August 2020 at 17:36:53 UTC, Michael Reese wrote: Thanks for suggesting! I tried, and the union works as well, i.e. the function args are registered. But I noticed another thing about all workarounds so far: Even if calls are inlined and arguments end up on the stack, the linker puts code of the wrapper function in my final binary event if it is never explicitly called. So until I find a way to strip of uncalled functions from the binary (not sure the linker can do it), the workarounds don't solve the size problem. But they still make the code run faster. Try -ffunction-sections -Wl,--gc-sections. That should remove all unreferenced functions. It removes all unreferenced sections, and writes every function into a separate section.
Re: How to compile to .bin/.iso format
On Wednesday, 17 June 2020 at 12:39:11 UTC, FeepingCreature wrote: On Wednesday, 17 June 2020 at 12:30:24 UTC, Quantium wrote: Hi all! I have a programm in D (The simplest OS), which should be compiled into .bin or .iso format to be possible to run it on VirtualBox. How can I compile it to .bin / .iso format and which compiler should I use? Try this page? https://wiki.osdev.org/D_Bare_Bones combined with https://dlang.org/phobos/core_volatile.html to replace volatile. Update: Tried and it works with ldc 1.20.1 (2.090.1) at least. The LDC version of the command is `ldc2 -betterC -m32 -c kernel.main.d -ofkernel.main.o -g`.
Re: How to compile to .bin/.iso format
On Wednesday, 17 June 2020 at 12:30:24 UTC, Quantium wrote: Hi all! I have a programm in D (The simplest OS), which should be compiled into .bin or .iso format to be possible to run it on VirtualBox. How can I compile it to .bin / .iso format and which compiler should I use? Try this page? https://wiki.osdev.org/D_Bare_Bones combined with https://dlang.org/phobos/core_volatile.html to replace volatile.
Re: What's the best way to find out which exceptions may be thrown ?
On Tuesday, 2 June 2020 at 13:58:13 UTC, Bienlein wrote: Because of the problems with checked exceptions they were deliberately left out in C#. Here is an interview with Anders Hejlsberg, the creator of C# at MS, where he explains the reasons for this decision: https://www.artima.com/intv/handcuffs.html This wouldn't seem to apply if checked exceptions were inferred by default, right? And the issues with Java generics don't apply to D, because our metaprogramming infers attributes anyways.
Re: From [Tuple!(A,B), ...] to Tuple!(A[], B[])
On Monday, 17 February 2020 at 11:07:33 UTC, foozzer wrote: Hi all, There's something in Phobos for that? Thank you Here you go: import std; // extract the types that make up the tuple auto transposeTuple(T : Tuple!Types[], Types...)(T tuples) { // templated function that extracts the ith field of an array of tuples as an array auto extractArray(int i)() { return tuples.map!(a => a[i]).array; } // return tuple of calls to extractArray, one for each tuple index return tuple(staticMap!(extractArray, aliasSeqOf!(Types.length.iota))); } void main() { Tuple!(int, double)[] array; array ~= tuple(1, 2.0); array ~= tuple(3, 4.0); Tuple!(int[], double[]) tuple = array.transposeTuple; assert(tuple[0] == [1, 3]); assert(tuple[1] == [2.0, 4.0]); }
Re: dub dustmite struggles
On Monday, 20 January 2020 at 06:48:08 UTC, DanielG wrote: I can't seem to figure out what dub's dustmite command is looking for with its regexes. No matter what I try - no matter how simple - the initial test fails. I am able to run dustmite standalone just fine with the following test script: cd example dub 2>&1 | grep -F "ScrollView6__initZ+0xd8): undefined reference to \`internal'" However, when I attempt using 'dub dustmite' with --linker-regex (or --linker-status, even), the initial test always fails. I've also tried simplifying the regex on the assumption that I'm not escaping things properly - to no avail. Is it perhaps something to do with my project structure? My project is a library containing an /example subfolder, containing an application dub project, and that's where my linker error occurs, not in the library itself. So that's where I'm attempting to run dub dustmite as well. I don't know how `dub dustmite` works, but my advice would be to use standalone dustmite and write a shellscript that handles your success/fail condition with an exit code. That's always worked for me, and it makes it easier to externally check what's happening. Ie. test.sh: --- #!/bin/sh dub 2>&1 |grep -F "ScrollView6__initZ+0xd8): undefined reference to \`internal'" --- dustmite example ../test.sh Then if you have to recurse into a dub project, just copy it into your example folder so it's compiled in, and repeat.
Re: weird behave of Array?
On Monday, 29 July 2019 at 05:58:21 UTC, dmm wrote: So, d try to be smart, only make thing worse? D is behaving exactly as it should here. You simply have a wrong model of what an array is in D. In C++, an array owns its memory. In D, an array is a thin wrapper around GC managed memory. As such, for instance, you can take a reference to an array field, then resize the array, and the original reference will still be valid and at its original value. To do what you want, use std.array.Appender, which owns its memory. import std.algorithm; import std.array; import std.range; import std.stdio; void main() { Appender!(int[]) app; 10.iota.each!(a => app.put(a)); writefln!"%s, %s"(app.data.ptr, app.data); app.shrinkTo(0); 10.iota.each!(a => app.put(a)); writefln!"%s, %s"(app.data.ptr, app.data); }
Re: Overloads not returning appropriate info. [Field reflunkory]
On Sunday, 7 April 2019 at 03:47:25 UTC, Alex wrote: rules are meant to be broken. No they're not! Almost by definition not! More comprehensively, if you break a rule you take responsibility for the outcome. You wanna use stringof? "Don't use stringof for that." "rules are meant to be broken." -- "Wah, my code doesn't work, stringof is shit, bad design, fix D pls." Don't ask questions if you don't care about the answers. More importantly, don't ignore advice and then complain about it. You can't expect to lead by authority. Give a good reason why I should avoid it and change my current ways and I will. Your code will break in surprising and unfixable ways. `stringof` is not *for* mixin. If you use it for mixin, you will be on your own design-wise. The language will not be changed to "fix" the "bugs" you run into. It will work until it won't work, and then you'll have to rewrite the entire thing anyway. Don't use stringof for mixin.
Re: Is there something special required to use Appender.clear
On Monday, 28 January 2019 at 15:16:54 UTC, Steven Schveighoffer wrote: It will inspect the allocated length from the GC if the array is appendable from the beginning. So it's not always going to reallocate. e.g.: string x = "abc".idup; auto app = x.appender; app ~= "xyz"; // does not reallocate. -Steve Fair enough. My use case is simply the standard usecase of Appender: I want to build up an array in a way that reduces GC churn. Maybe it's an array of structs that contain const members that I'll serialize to JSON and send on a socket. In that case, I know for a fact that no references will hang around past the serialization. That's what clear _is for._ I don't see why this would be different with const or immutable data; if you hold references past .clear being called you're in trouble *anyways.* Right, this does seem like a big limitation. Keeping with the spirit of how slices don't own the memory in question, Appender is being conservative with what it doesn't know. I wonder if it may be more appropriate to instead of preventing clear() on immutable/const arrays, to make it @system. Or maybe call it something different "dangerousClear" or something ;) There definitely should be some way to fail if clear is called on an array that was passed into the constructor. But I'm still not sure we should allow overwriting immutable memory without a cast, even in @system code. My problem is this. const and immutable are *not* well supported in the standard library at the moment. What I want is that I can use the idioms of the stdlib, semantically, in a way that lets me *not care* about const or immutable, that lets me express the patterns I want without having to worry about whether some type deep inside my code, a dub library, or phobos itself decided to declare a field immutable. Appender covers two usecases: "capacity caching" and "memory reuse." Both of those usecases have two const variations: "possibly immutable" and "mutable". mutable capacity caching | mutable memory reuse ---+- immutable capacity caching | immutable memory reuse But instead of cutting between capacity caching and memory reuse, down the middle, Appender cuts between mutable and immutable, left to right. I think this is a symptom of a broad negligence of constness as a first-class property - constness works sometimes, and it's nice if it does, but it can't be *relied* on to be well supported. This makes using const in D an eternal uphill struggle. Why even go to all the trouble to make a new major version of the language just to introduce constness, if it's not going to be treated as a first-class concern? I don't want to have to sprinkle static if(isAssignable!T) everytime I want to use a library type. If Phobos offers me as generic a data structure as Appender, parameterized on T, it should work for T, regardless of what T is doing, and *certainly* regardless of what fields in T are marked const. Especially considering that if a field is not marked as const, that hardly means it's not going to lead to bugs if its memory is reused while you're referencing it!
Re: Is there something special required to use Appender.clear
On Friday, 25 January 2019 at 14:33:16 UTC, Steven Schveighoffer wrote: On 1/25/19 3:20 AM, FeepingCreature wrote: On Thursday, 24 January 2019 at 17:49:34 UTC, Ali Çehreli wrote: Aren't the semantics of .clear that it's invalid to access references to .data after calling .clear, period? And if not, then shouldn't they be? Consider if Appender managed its own memory and held on to previously-allocated arrays while you were appending, only to free them on .clear. That seems like something Appender should be allowed to do. If you don't want it, just reinitialize Appender instead of calling .clear. You are advised not to. But it's not unsafe, as the memory is still there. That's stupid. Why would you advise me not to, if there's no problem with it? Either it should be accepted or it should be forbidden, just like warnings. Any reason that the semantics of .clear should be different for a starting array? Anyway if so, I'd prefer to just make that a runtime error. Yes, because Appender doesn't know where that memory comes from. A string could be, for instance, passed to another thread and being used, you wouldn't want to overwrite it. In which case, you can't reuse the Appender and should not call `clear`! It seems like we're gimping functionality of a very basic tool for memory efficiency for the sake of not confusing users. This rarely pays off. Generally speaking, overwriting immutable data is UB in D anyway. Making it a runtime error would be possible, but there has to be a good reason to make it that way. I'm mostly fishing around if anyone has an objection to a PR to change this. Without good reasons to change, I don't see why it would be accepted. Maybe you can describe your use case? My use case is simply the standard usecase of Appender: I want to build up an array in a way that reduces GC churn. Maybe it's an array of structs that contain const members that I'll serialize to JSON and send on a socket. In that case, I know for a fact that no references will hang around past the serialization. That's what clear _is for._ I don't see why this would be different with const or immutable data; if you hold references past .clear being called you're in trouble *anyways.* I consider initializing Appender with an array referencing immutable data a borderline error anyways. The entire point of Appender is that it caches capacity data of GC managed memory, which is never immutable. On the first append to an immutable-memory array, it has to reallocate *anyways*. There is no benefit to initializing an Appender with immutable memory over just appending it first thing, unless you never plan to append to it ever.
Re: Is there something special required to use Appender.clear
On Thursday, 24 January 2019 at 17:49:34 UTC, Ali Çehreli wrote: On 01/24/2019 04:35 AM, FeepingCreature wrote: > On Tuesday, 27 March 2018 at 12:31:05 UTC, Simen Kjærås wrote: >> On Tuesday, 27 March 2018 at 12:17:58 UTC, Ellie Harper wrote: >>> Sorry if this is a stupid question, but is there something special >>> required to call Appender.clear? When I attempt even just a simple >>> use I am getting compile errors relating to `template object.clear`. >> >> From the documentation for Appender: >> >>> Note >>> clear is disabled for immutable or const element types, due to the >>> possibility that Appender might overwrite immutable data. >> >> Since string is immutable(char)[], clear() is simply not available for >> appender!string. >> >> -- >> Simen > > Isn't this wrong, though? Appender controls the memory it references. It > could just choose to allocate non-immutable memory internally. As long > as any const data put into the appender is *returned* as const, there is > no chance of immutable memory being overwritten. I think Appender is trying to protect previous data from Appender's later use. If it handed out immutable data, the user is expecting it to not change. So, Appender cannot clear it for later use. Ali Aren't the semantics of .clear that it's invalid to access references to .data after calling .clear, period? And if not, then shouldn't they be? Consider if Appender managed its own memory and held on to previously-allocated arrays while you were appending, only to free them on .clear. That seems like something Appender should be allowed to do. If you don't want it, just reinitialize Appender instead of calling .clear. Appender is sometimes given a starting array. clear isn't callable in that case, and we don't distinguish the difference in the type or at runtime. Any reason that the semantics of .clear should be different for a starting array? Anyway if so, I'd prefer to just make that a runtime error. I'm mostly fishing around if anyone has an objection to a PR to change this.
Re: Is there something special required to use Appender.clear
On Tuesday, 27 March 2018 at 12:31:05 UTC, Simen Kjærås wrote: On Tuesday, 27 March 2018 at 12:17:58 UTC, Ellie Harper wrote: Sorry if this is a stupid question, but is there something special required to call Appender.clear? When I attempt even just a simple use I am getting compile errors relating to `template object.clear`. From the documentation for Appender: Note clear is disabled for immutable or const element types, due to the possibility that Appender might overwrite immutable data. Since string is immutable(char)[], clear() is simply not available for appender!string. -- Simen Isn't this wrong, though? Appender controls the memory it references. It could just choose to allocate non-immutable memory internally. As long as any const data put into the appender is *returned* as const, there is no chance of immutable memory being overwritten.