Re: D outperformed by C++, what am I doing wrong?
On Sunday, 13 August 2017 at 06:09:39 UTC, amfvcg wrote: Hi all, I'm solving below task: Well, for one thing, you are preallocating in C++ code but not in D. On my machine, your version of the code completes in 3.175 seconds. Changing it a little reduces it to 0.420s: T[] result = new T[input.length]; size_t o = 0; for (uint i; i < input.length; i=min(i+range, input.length)) { result[o] = sum(input[i..min(i+range, input.length)]); o++; } return result[0..o]; You can also use Appender from std.array.
Re: What the hell is wrong with D?
On Tuesday, 19 September 2017 at 17:40:20 UTC, EntangledQuanta wrote: writeln(x + ((_win[0] == '@') ? w/2 : 0)); writeln(x + (_win[0] == '@') ? w/2 : 0); The first returns x + w/2 and the second returns w/2! Yeah, it sucks to have bugs like this crop up. I have enough trouble remembering operator precedence, so I end up using parentheses everywhere and pretending the ternary operator doesn't exist. I also tend to break up complex expressions a lot. It's just safer, and usually clearer.
Re: opEquals code generation
On Tuesday, 19 September 2017 at 13:18:04 UTC, drug wrote: 19.09.2017 15:38, Steven Schveighoffer пишет: On 9/19/17 8:01 AM, drug wrote: I iterate over struct members and check against equality depending on member type. is there more simple/cleaner/better way to achieve this functionality? Especially without string mixins? Why not just use tupleof directly instead of having to find the member name and using mixins? -Steve Hmm, I'm sure I had tried it before and failed, but now I've managed to do so and it's really simpler Could be a bit simpler than that, depending on your needs: bool opEquals(Object other) const nothrow @nogc { auto f = cast(typeof(this)) other; if (f is null) return false; return this.tupleof == other.tupleof; }
Re: wstring hex literals
On Wednesday, 20 September 2017 at 15:04:08 UTC, jmh530 wrote: testing_utf16.d(5): Error: Truncated UTF-8 sequence testing_utf16.d(6):while evaluating: static assert((_error_) == (wstring )) Failed: ["dmd", "-unittest", "-v", "-o-", "testing_utf16.d", "-I."] https://dlang.org/spec/lex.html#hex_strings says: The string literals are assembled as UTF-8 char arrays, and the postfix is applied to convert to wchar or dchar as necessary as a final step. This isn't the friendliest thing ever and is contrary to my expectations too. You basically have to encode your string into UTF-8 and then paste the hex of that in. What should work is escape sequences: wstring str = "\u03c0"w;
Re: How to check if path is writable
On Friday, 15 September 2017 at 01:42:02 UTC, Joseph wrote: Is there a cross-platform way in D to check if a path is writable? Try to write to it and see if you get an error.
Re: Tango + D2 + Mac
On Tuesday, 17 October 2017 at 02:52:41 UTC, Fat_Umpalumpa wrote: I am having a lot of trouble trying to install Tango to use with D2 on my mac os Sierra. Is this even possible? Thanks! I take it you're using https://github.com/SiegeLord/Tango-D2 ? I tried it out about a year ago and it worked, but your mileage may vary. For the most part, Phobos and various Dub packages have superseded it. Tango's main benefit was that it was code that was well maintained over the course of several years, and that's no longer true.
Re: Struct List Human
On Sunday, 24 September 2017 at 16:13:30 UTC, dark777 wrote: when you execute and call Name: I type my name: Name: dark777 + [enter] and he does not jump to the next line to get the age This is what I want to know how to solve. Add a `writeln();` after reading input, maybe?
Re: Seperating class methods in a different module
On Thursday, 7 December 2017 at 02:32:03 UTC, helxi wrote: 1. How can I separate class methods from the declaration block? And how can I implement them in a separate module? module a; class Test { import b; mixin TestMethodImpl!(); } module b; template TestMethodImpl() { void foo(); } But this is abnormal for D. We almost invariably put function bodies inside declarations. What's your goal with separating the declaration from the implementation? If you want people to be *unable* to read method bodies, you can generate *.di files that only contain declarations. `dmd --help | grep -i header` or so -- though that keeps in templates and functions that are candidates for inlining. If you want to make it easy for someone to look at the API without wading through function declarations, use ddox to generate HTML documentation. Imagine I am making a package called forward_list. Under the directory forward_list/, I have modules.d that imports dedicated modules for useful methods like push_back, insert_after, front, sort, merge etc. Is it an acceptable practice to declare classes in package.d? That would be abnormal. You can look at the layout of std.container by way of comparison -- one module per container type, one for miscellaneous utilities, and only documentation in package.d.
Re: package modules and how to generate a shared library plus .di file (I)
On Thursday, 7 December 2017 at 16:39:14 UTC, kdevel wrote: But why do I have to use the prefix "mymod.:" in the library case? If you have an editor open with ten tabs pointing to different files in your source tree, all your imports are uniform -- you don't have to step back and consider where the specific file you're editing is and calculate relative import paths. You always import a given module with the exact same code. If you copy and paste code between two modules and that contains an import statement, it just works. If you decide to move a module to a different package, you need to change its module name, move it on disk, and update the stuff that imports it. You don't have to update every import it does. If you have a source tree like: pierce/ db/ core.d controllers/ feed.d then feed.d can have `import pierce.db.core;` instead of people being confused about how to refer to the parent directory in a relative imports style. The tradeoff is that you have to type sometimes as many as twelve extra characters in a handful of lines of code.
Re: std.conv.to!string refuses to convert a char* to string.
On Saturday, 9 December 2017 at 05:55:21 UTC, Venkat wrote: I am trying out the DJni library (https://github.com/Monnoroch/DJni). For some reason std.conv.to!string doesn't want to convert a char* to a string.The lines below are taken from the log. I see that the last frame is at gc_qalloc. I am not sure why it failed there. Can anybody elaborate on what is going on here ? Thanks in advance. I've got no idea, but can you verify that you can print it with printf? Can you allocate other GC memory? Can you try using fromStringz instead of to!string and see what that does? Just shots in the dark...
Re: Store any callable in an array
On Friday, 4 May 2018 at 15:36:29 UTC, wjoe wrote: I have a class that I want to be able to register callbacks and I'd like to be able to register any callable - functions, delegates, lambdas, anything. Is there another way to do it besides converting those toDelegate, which states a bug with @safe functions? Or better store each type in their own array ? Cheers! auto asDelegate(TFunc)(TFunc func) @trusted { import std.functional : toDelegate; return toDelegate(func); } The "@trusted" means that you promise this thing is safe, even if the compiler can't be certain.
Re: Store any callable in an array
On Friday, 4 May 2018 at 19:12:16 UTC, ag0aep6g wrote: If toDelegate isn't (always) @safe, how can you be sure that your wrapper is? If it were @safe, the compiler would accept it. Looking at the code, I believe there are several casts that the compiler can't verify but are used safely. Also, TFunc may have an unsafe destructor. If it's a delegate with an un-@safe destructor (how would that work? a captured context variable?), then it's already not @safe. If it's a function, it doesn't have a destructor. If it's a user-defined type with opCall, that's something to pay attention to, but it's beyond the scope of the original question.
Re: Error: cannot deduce function from argument types
On Saturday, 5 May 2018 at 16:42:12 UTC, Sisor wrote: Error: template std.string.stripRight cannot deduce function from argument types You used http://dpldocs.info/experimental-docs/std.string.stripRight.html This function only takes one argument and strips whitespace. You want http://dpldocs.info/experimental-docs/std.algorithm.mutation.stripRight.1.html This function can take two arguments and strips the second from the first.
Re: is ==
On Saturday, 19 May 2018 at 01:48:38 UTC, Jonathan M Davis wrote: Actually, that runtime function has existed since before TDPL came out in 2010. It even shows the implementation of the free function opEquals (which at the time was in object_.d rather than object.d). I'm not even sure that the error message was added before the free function version of opEquals was. Maybe when that error message was first introduced, it avoided a segfault, but if so, it has been a _long_ time since that was the case. Good catch. I overly trusted git blame. The opEquals(Object, Object) function was added in February 2010, while the error message was added in March 2008. Of course, the most notable case where using == with null is a terrible idea is dynamic arrays, and that's the case where the compiler _doesn't_ complain. Using == with null and arrays is always unclear about the programmer's intent and almost certainly wasn't what the programmer intended. If the programmer cares about null, they should use is. If they care about lengnth, then that's what they should check. Checking null with == is just a huge code smell. I feel like the array == null version is more explicit about not allocating memory. However, I'm paranoid about whether that's going to check the pointer instead, so I mostly use array.length == 0 instead.
Re: is ==
On Saturday, 19 May 2018 at 04:30:24 UTC, Jonathan M Davis wrote: On Saturday, May 19, 2018 03:32:53 Neia Neutuladh via Digitalmars-d-learn wrote: > Of course, the most notable case where using == with null is > a terrible idea is dynamic arrays, and that's the case where > the compiler _doesn't_ complain. Using == with null and > arrays is always unclear about the programmer's intent and > almost certainly wasn't what the programmer intended. If the > programmer cares about null, they should use is. If they > care about lengnth, then that's what they should check. > Checking null with == is just a huge code smell. I feel like the array == null version is more explicit about not allocating memory. However, I'm paranoid about whether that's going to check the pointer instead, so I mostly use array.length == 0 instead. I'm not sure what memory allocations you're worried about. Neither "" nor [] allocates memory "" is syntax for compile-time constants and shouldn't ever allocate. [] is a specific case of [values...]; the general case allocates, but this one case does not. null is not even a compile-time constant; it's a value baked into the language and is guaranteed not to allocate. but regardless, if you're looking to check whether arr.ptr is null, then that's effectively what you get with arr is null I don't think I've ever wanted to distinguish a zero-length slice of an array from a null array. Regardless, if you're checking for null, then is does the job, and if what you care about is whether the array is empty, then that's what arr.length == 0 and arr.empty do. As I already said, I use "array.length == 0". "array.empty" is part of that newfangled range business.
Re: Splitting up large dirty file
On Tuesday, 15 May 2018 at 20:36:21 UTC, Dennis wrote: I have a file with two problems: - It's too big to fit in memory (apparently, I thought 1.5 Gb would fit but I get an out of memory error when using std.file.read) Memory mapping should work. That's in core.sys.posix.sys.mman for Posix systems, and Windows has some equivalent probably. (But nobody uses Windows, right?) - It is dirty (contains invalid Unicode characters, null bytes in the middle of lines) std.algorithm should generally work with sequences of anything, not just strings. So memory map, cast to ubyte[], and deal with it that way? - When you convert chunks to arrays, you have the risk of a split being in the middle of a character with multiple code units It's straightforward to scan for the start of a Unicode character; you just skip past characters where the highest bit is set and the next-highest is not. (0b1100_ through 0b_1110 is the start of a multibyte character; 0b_ through 0b0111_ is a single-byte character.) That said, you seem to only need to split based on a newline character, so you might be able to ignore this entirely, even if you go by chunks.
Re: is ==
On Friday, 18 May 2018 at 23:53:12 UTC, IntegratedDimensions wrote: Why does D complain when using == to compare with null? Is there really any technical reason? if one just defines == null to is null then there should be no problem. It seems like a pedantic move by who ever implemented it and I'm hoping there is actually a good technical reason for it. tldr: this error is outdated. In the days of yore, "obj == null" would call "obj.opEquals(null)". Attempting to call a virtual method on a null object is a quick path to a segmentation fault. So "obj == null" would either yield false or crash your program. Except it's worse than that; your opEquals method had to explicitly check for null. So if your class had a custom equality function, "obj == null" was probably going to segfault no matter what. Because of this common source of errors, in DMD 2.012 (2008), we got an error only for the case of comparing with a literal null. (The compiler isn't a mind-reader; it doesn't know whether that variable will be null when that line of code executes.) This still sucked, so in 2015 we got a runtime function to handle object equality: https://github.com/dlang/druntime/blob/dff824eda422b1fcdde5f2fe53120fcd71733aaa/src/object.d#L140 But we haven't removed the error message. It *is* faster to call "foo is null" than "foo == null", but I don't think that's particularly worth a compiler error. The compiler could just convert it to "is null" automatically in that case. One casualty of the current state of affairs is that no object may compare equal to null.
Re: What is the point of nothrow?
On Wednesday, 13 June 2018 at 00:38:55 UTC, Jonathan M Davis wrote: It's possible to write programs that check and handle running out of memory, but most programs don't, and usually, if a program runs out of memory, it can't do anything about it and can't function properly at that point. Simulations that run out of memory are likely unable to recover from OutOfMemoryError. Transactional programs like webservers are likely to run out of memory due to an unusually large request. The idea is that it's a bug in your code if you ever index an array with an index that's out-of-bounds. If there's any risk of indexing incorrectly, then the program needs to check for it, or it's a bug in the program. Most indices are not taken from program input, so treating them as input in the general case wouldn't really make sense The case I find is almost invariably a hard-coded index into input data, like a CSV file that is supposed to have ten columns but only has eight. This is often a bug in my program simply because most exceptions I encounter are bugs in my program. - plus, of course, treating them as program input in the general case would mean using Exceptions, which would then kill nothrow. Which goes back to my point of problems that could be caused by too wide a range of code being Errors.
Re: What is the point of nothrow?
On Monday, 11 June 2018 at 00:47:27 UTC, Jonathan M Davis wrote: Why do you care about detecting code that can throw an Error? Errors are supposed to kill the program, not get caught. As such, why does it matter if it can throw an Error? Error is currently used for three different things: * This is a problem that could occur in such a wide range of circumstances, it would make it difficult to use nothrow. * This is a problem severe enough that almost every program would have to abort in these circumstances, so it's reasonable to abort every program here, and damn the few that could handle this type of problem. * This is a problem that someone thinks you might not want to catch when you write `catch (Exception)`, even if it can't be thrown from many places and it wouldn't kill most programs. As an example of the former: I have a service that uses length-prefixed messages on raw sockets. Someone tries to connect to this service with curl. The length of the message is read as 0x4854_5450_2131_2E31 -- ASCII "HTTP/1.1" as an unsigned long. (Or we read a 32-bit length, but we're running on a system with 128MB of RAM and overcommit turned off.) The program might be in an invalid state if this allocation fails. It might not. This depends entirely on how it was written. The runtime is in a valid state. But the exception is OutOfRangeError, which inherits from Error. Similarly, RangeError. There's little conceptual difference between `try {} catch (RangeError) break` and `if (i >= length) break`. But forbidding dynamic array indexing in nothrow code would be rather extreme. On the other hand, a Unicode decoding error is a UnicodeException, not a UnicodeError. I guess whoever wrote that thought invalid Unicode data was sufficiently more common than invalid values in length-prefixed data formats to produce a difference in kind. This isn't obviously wrong, but it does look like something that could use justification.
Re: scope(success) lowered to try-catch ?
On Sunday, 17 June 2018 at 10:58:29 UTC, Cauterite wrote: Is there a reason scope(success) needs to set up for exception handling? Or is this a bug / potential enhancement ? If you had no exception handling in place, you'd need to duplicate code in the output. For instance: void foo() { scope(success) writeln("success!"); if (a) return; if (b) return; throw new Exception; } This would have to be lowered to: void foo() { if (a) { writeln("success!"); return; } if (b) { writeln("success!"); return; } throw new Exception; writeln("success!"); // maybe omitted with flow analysis } Now imagine there were 20 places you return from the function early. Now imagine this is in a loop body, where you can leave it via goto, break, continue, return, or end-of-block. And wrapped in several if statements. You generate smaller code with the exception handling system. The compiler only has to pay attention to scope guards in the code that handles it directly, instead of at every flow control statement. Add to that the fact that -betterC is pretty recent and scope guards are more than ten years old, and you get this hole in the compiler.
Re: How do I break from loop when using parallel()?
On Monday, 28 May 2018 at 21:04:21 UTC, Dr.No wrote: import std.parallelism : parallel; foreach(t; parallel(arr)) { if(!doSomething(t)) { return false; } } It reuturns the run time error: std.parallelism.ParallelForeachError@(0): Cannot break from a parallel foreach loop using break, return, labeled break/continue or goto statements. What's the proper way to break from loop? By the time you try to break out of the loop, you've already executed the loop body for later elements in the collection. So if you could do that, it would give the wrong impression. The loop body executes on several threads at once. The `return false` statement might be executing on a different thread, and `return` only returns on the same thread. If you want to do this sort of thing (exit on first error, for instance), you can manually use TaskPool, schedule tasks on it, and use an atomic variable to exit early on each task if necessary.
Re: convert string to wchar[]
On Saturday, 26 May 2018 at 17:12:38 UTC, Dr.No wrote: What's D's way to do that? I need it to be mutable array of wchar because a Windows function requires that. Alternative to go down to using pointers, which would be something like: wchar[] w = new wchar[s.length]; memcpy(w.ptr, s.ptr, s.length); std.conv.to has you covered for quite a lot of conversions: import std.conv; import std.stdio; void main() { string s = "hello world"; wchar[] mutableUtf16 = s.to!(wchar[]); mutableUtf16[0] = '☃'; // prints ☃ello world writeln(mutableUtf16); }
Re: Remove closure allocation
On Saturday, 26 May 2018 at 15:00:40 UTC, Malte wrote: This compiles with DMD, however it returns random numbers instead of the value I passed in. Looks like a bug to me. Should that work or is there any other pattern I could use for that? Filed as https://issues.dlang.org/show_bug.cgi?id=18910 As for the larger issue, you have to store `q` somewhere. The compiler could store it on the stack, but the compiler would have to do a lot of work to prove that that's safe -- that the return value from `arr.map` doesn't escape the current function, that `map` doesn't save the thing you passed to it anywhere, that sort of thing. And that sort of analysis is flaky. It's a recipe for code that compiles on one version of a compiler and not the next, a lot of bug reports that are hard to track down, that sort of thing. And it means that it has to assume the worst for functions that it doesn't have the source for -- when you pass a delegate, when you call an extern(D) function, when you call a virtual method. So the compiler does the safe thing, and it has the GC allocate a bit of memory to hold `q`. The way around that is the `scope` keyword. The compiler can do that complex analysis one function at a time; that's sufficiently simple. So if you wrote a `map` function, you could define it as taking a `scope U delegate(T)` and the compiler wouldn't need to use the GC there. That obviously adds restrictions on how you can write that function.
Re: determining if array element is null
On Saturday, 2 June 2018 at 18:10:38 UTC, eastanon wrote: Does D array implementation support an array of null values? int a[4] = null; But I ran into a type error while checking if a[i] is null foreach(i; 0..3){ if(i == null){ writeln("it is null"); } } } How do you set fixed size array of null values and check if they are null? There are several problems with your code. 1. `int a[4]` should be `int[4] a`. You probably see a warning about using the C-style array syntax. 2. `int[4] a = null` treats the initialization as a copy from an array whose value is null. If you run just that line of code, it will produce an error at runtime: "object.Error@(0): Array lengths don't match for copy: 0 != 4" If you want to initialize every member of an array with a value, you write it as: int[4] a; a[] = 5; 3. `foreach (i; 0..3)` will iterate through a range of integers: 0, 1, and 2. You haven't touched your array. 4. `i == null` is trying to compare an integer, which can never be null, to null. You either want to use std.typecons.Nullable (if you just want integers-that-might-be-null) or an array of pointers to integers (if you want reference semantics). 5. Usually, you want to use `i is null` instead of `i == null`.
Re: how to define infix function
On Saturday, 2 June 2018 at 21:44:39 UTC, greatsam4sure wrote: Sorry for the typo is it possible to define infix function in D 3.min(5)// 3: where min is a function, works in D 3 min 5 // does not work. thanks in advance This is a horrible abuse of D's operator overloading discovered by FeepingCreature in the distant past. You have to delimit your custom infix operator with slashes; you can't make `3 min 5` work, but you can make `3 /min/ 5` work. Observe: struct Min { MinIntermediate!T opBinaryRight(string op, T)(T value) if (op == "/") { return MinIntermediate!T(value); } } struct MinIntermediate(T) { T value; T opBinary(string op, T)(T value2) if (op == "/") { if (value < value2) return value; return value2; } } Min min; void main() { writeln(1 /min/ 2); }
Re: copy only reference rather duplicate a string in appender!string
On Tuesday, 26 December 2017 at 15:37:12 UTC, Marc wrote: I do build a string by coping large parts of diffrent buffers, all those buffers live after the functional call, so rather than duplicate those string I'd like to copy only references to those parts rather duplicate every string. I combined appender!string, assumeUnique() and array slices. Something like this: This depends on whether you have several variables as buffers or an array of buffers. With several variables: http://dpldocs.info/experimental-docs/std.range.chain.html With an array, or something else iterable: http://dpldocs.info/experimental-docs/std.algorithm.iteration.joiner.2.html So you can use: chain(buf1, buf2, buf3); Or: myBuffers = [buf1, buf2, buf3]; joiner(myBuffers); That produces something string-like. (A rope, but with a poor API.) You can iterate through it as a string, you can output it to a file, etc. You can't pass it to something that expects a string specifically; for instance, you can't return that from `MyClass.toString()`.
Re: Don't expect class destructors to be called at all by the GC
On Thursday, 21 December 2017 at 18:20:19 UTC, H. S. Teoh wrote: Even calling GC.collect directly did not guarantee the DB handle was closed at the right time. This may have been a bug in my code that left dangling references to it, or perhaps the array of Database handles was still scanned through by the GC even though the only remaining array slice has a shorter length. Whatever the reason was, it left me with the very unpleasant prospect of silently accumulating file descriptor leaks. Last I checked, the GC doesn't understand arrays. It only understands "segment of memory that might contain pointers" and "segment of memory that doesn't contain pointers". You might have gotten better results if you had nulled out the reference in the array. Of course, that relies on not having any remaining references on the stack or in registers, neither of which is easy to guarantee.
Re: Dub project has both .sdl and .json files. Is this normal or did I do something wrong?
On Friday, 3 August 2018 at 19:41:32 UTC, Bastiaan Veelo wrote: But if you commit it, and a compiler deprecation causes a dependency in that pinned version to fail to compile, then your app won't compile either, even though your code itself does not suffer from the deprecation and even though a newer release of the dependency is available that solves the deprecations. This means that, if your app is on code.dlang.org, people won't be able to dub fetch && dub run. This is also true if the dependency gets a major version bump and then gets updated for a breaking compiler change. If the dependency range is broad enough, you can `dub upgrade && dub run`. What advantages does committing dub.selections.json have that outweigh this disadvantage? Dependencies don't always follow semantic versioning. For instance, a binding for a C library that is actively developed might reasonably follow the bound library's versioning. Or the maintainer might make a mistake and commit a breaking change without bumping to a new major version. This is why my top-level projects these days have specific versions of dependencies rather than the more commonly used ranges. I'm only going to test against those specific versions, so why should I claim that my application can use future versions? It would be OK if dub.selections.json would also pin the compiler version and there were a standard way to select that version (like dvm, but without its shortcomings). That would be good. If I were less lazy, I could add that to dub. It already manages packages; the compiler is just a slightly different dependency.
Re: Are properties mature enough?
On Sunday, 19 August 2018 at 18:32:17 UTC, QueenSvetlana wrote: In the D Style Guide, it says: Properties https://dlang.org/dstyle.html#properties Functions should be property functions whenever appropriate. In particular, getters and setters should generally be avoided in favor of property functions. And in general, whereas functions should be verbs, properties should be nouns, just like if they were member variables. Getter properties should not alter state. In the Properties function section, it says: https://dlang.org/spec/function.html#property-functions WARNING: The definition and usefulness of property functions is being reviewed, and the implementation is currently incomplete. Using property functions is not recommended until the definition is more certain and implementation more mature. So which is it? The `@property` annotation might not remain in the language. However, the property call syntax for functions will remain. So you can write: --- struct Random { private int value; int next() { value++; return value; } void seed(int value) { this.value = value; } } Random r; r.seed = 21; writeln(r.next); --- That's going to work forever. You *could* add @property to the next and seed functions. That forces people to use them as fields. However, there's some discussion about how that's going to be handled in the future. So you might want to leave it off.
Re: Better diagnostics for null classes dereferencing
On Tuesday, 10 July 2018 at 22:53:25 UTC, kdevel wrote: extern (C) __gshared bool rt_trapExceptions; static this () { rt_trapExceptions = false; } This will catch exceptions raised in main and in static constructors that run after this one. However, if you put that code in the module that includes main(), it's probably going to be the last static constructor run. That means it doesn't impact other static constructors. The only fix for that is putting this code in its own module that you add as the first import in every module. And if you depend on any library with a static constructor anywhere inside, you have to modify that library. But exceptions can be thrown before any static constructor is run. The function that calls static constructors might detect a cycle straight off, for instance. That's why the This Week In D post injected it into the C main function.
Re: static array of pointers to dynamic arrays of ints problem...
On Sunday, 22 April 2018 at 06:00:15 UTC, WhatMeForget wrote: foreach(i, elem; a) { int[] temp = new int[](5); .. a[i] = } You're taking the address of a local variable and persisting it beyond the variable's scope. This is not safe in general; compilers regularly reuse spaces on the stack. DMD specifically tends to do this reliably with foreach loop bodies. You see the same thing in C: #include int main(int argc, char** argv) { int* p[2]; for (int i = 0; i < 2; i++) { int f = i; p[i] = } printf("p[0] = %x, *p[0] = %d\n", p[0], *p[0]); printf("p[1] = %x, *p[1] = %d\n", p[1], *p[1]); return 0; } Which prints something like: p[0] = d9b69428, *p[0] = 1 p[1] = d9b69428, *p[1] = 1
Re: how to make '==' safe for classes?
On Sun, 28 Oct 2018 18:00:06 +, Stanislav Blinov wrote: > On Sunday, 28 October 2018 at 12:38:12 UTC, ikod wrote: > >> and object.opEquals(a,b) do not inherits safety from class C >> properties, and also I can't override it. > > Yep. Since Object is the base class and it defines opEquals as: > ``` > bool opEquals(Object); > ``` > > the compiler rewrites `a == b` as > `(cast(Object)a).opEquals(cast(Object)ob)`, i.e. it inserts a @system > call into your code. More pedantically, it rewrites it as: (a is b) || (a !is null && (cast(Object)a).opEquals(cast(Object)b)) An object might not be equal to itself via opEquals, but it will always compare equal to itself with ==.
Dealing with raw types as attributes
The spec says that a user-defined attribute must be an expression, but DMD accepts a wide range of things as UDAs: struct Foo { string name = "unknown"; } @Foo int bar; `bar` has the *type* Foo as an attribute. It's not an *instance* of Foo. So if I try to look at the UDAs: static foreach (uda; __traits(getAttributes, bar)) { static if (is(typeof(uda) == Foo)) { pragma(msg, "bar is @Foo"); } } That just doesn't work; typeof(Foo) isn't anything, so is(typeof(Foo) == Foo) is false. I can change my code to read `static if (is(uda == Foo))`. But that obviously fails: @Foo("customName") int bar2; What do you do to handle this? My current workaround is to make the attribute into a struct instance and use opCall in lieu of constructors: struct _Foo { string name; _Foo opCall(string name) { _Foo f; f.name = name; return f; } } enum _Foo Foo = _Foo.init; Now I can use `static if (is(typeof(uda) == _Foo))` and it always works. But are there better options? Any obvious flaws?
Re: Dealing with raw types as attributes
On Thu, 01 Nov 2018 11:35:27 -0700, Ali Çehreli wrote: > On 11/01/2018 09:14 AM, Neia Neutuladh wrote: >> The spec says that a user-defined attribute must be an expression, but >> DMD accepts a wide range of things as UDAs: >> >>struct Foo { string name = "unknown"; } >>@Foo int bar; >> >> `bar` has the *type* Foo as an attribute. It's not an *instance* of >> Foo. So if I try to look at the UDAs: > > That would work with hasUDA(). I have an example here: > >http://ddili.org/ders/d.en/uda.html That lets me test for presence, nothing more. While that's useful, I usually have a UDA struct whose fields I need to access. std.traits.getUDAs doesn't hide the difference between @Foo and @Foo(), so that's also not an option. I could use a customized version of that that replaces @Type with @Type.init, and that's a reasonable choice when I know other people aren't going to deal with that annotation type.
Re: Dealing with raw types as attributes
On Thu, 01 Nov 2018 20:01:51 +, Stanislav Blinov wrote: > Check if an UDA is a type?.. As in, not just `is(uda == Foo)`, > but simply `is(uda)`: Which works, but generally makes things more complex in code that's already pretty deeply nested. It's also something I have to worry about every time I do the static foreach to get UDAs, in the cases where that's more than once.
Re: Removing the precision from double
On Thu, 01 Nov 2018 23:59:26 +, kerdemdemir wrote: > I am doing trading and super scared of suprices like mathematical errors > during the multiplications(or division 1/tickSize) since market will > reject my orders even if there is a small mistake. > > Is this safe? Or is there a better way of doing that ? tldr: consider using std.experimental.checkedint and highly granular units, like milli-cents. Also consider using a rational number library. Doubles aren't necessarily bad, but they'd concern me. # 1. Fixed precision The common way of working with sensitive financial stuff is fixed precision numbers. With fixed precision, if you can represent 0.0001 cents and you can represent ten billion dollars, you can represent ten billion dollars minus 0.0001 cents. This is not the case with single-precision floating point numbers: writeln(0.0001f); writefln("%20f", 10_000_000_000f); writefln("%20f", 10_000_000_000f - 0.0001f); prints: 0.0001 100.00 100.00 The problem with fixed precision is that you have to deal with overflow and underflow. Let's say you pick your unit as a milli-cent (0.001 cents, $0.1). This works okay...but if you're trying to assign a value to each CPU cycle, you'll run into integer underflow. Like $10/hour divided by CPU cycles per hour is going to be under 0.001 cents. And if you try inverting things to get cycles per dollar, you might end up with absurdly large numbers in the middle of your computation, and they might not fit into a single 64-bit integer. ## Fixed precision with Checked std.experimental.checkedint solves the overflow problem by turning it into an error. Or a warning, if you choose. It turns incorrect code from a silent error into a crash, which is a lot nicer than quietly turning a sale into a purchase. It doesn't solve the underflow problem. If you try dividing $100 by 37, you'll get 270270 milli-cents, losing a bit over a quarter milli-cent, and you won't be notified. If that's deep in the middle of a complex calculation, errors like that can add up. In practice, adding six decimal places over what you actually need will probably be good enough...but you'll never know for certain. # Floating point numbers Floating point numbers fix the underflow and overflow problems by being approximate. You can get numbers up to 10^38 on a 32-bit float, but that really represents a large range of numbers near 10^38. **That said**, a double can precisely represent any integer up to about 2^53. So if you were going to use milli-cents and never needed to represent a value over one quadrillion, you could just use doubles. It would probably be easier. The problem is that you won't know when you go outside that range and start getting approximate values. # Rational numbers A rational number can precisely represent the ratio between two integers. If you're using rational numbers to represent dollars, you can represent a third of a dollar exactly. $100 / 37 is stored as 100/37, not as something close to, but not exactly equal to, 2.702 repeating. You can still get overflow, so you'll want to use std.experimental.checkedint as the numerator and denominator type for the rational number. Also, every bit of precision you add to the denominator sacrifices a bit of range. So a Rational!(Checked!(long, Throw)) can precisely represent 1/(2^63), but it can't add that number to 10. Manual rounding can help there.
Re: Dealing with raw types as attributes
On Fri, 02 Nov 2018 00:36:18 +, Nicholas Wilson wrote: >> What do you do to handle this? > > @Foo() int bar; > > instead of > > @Foo int bar; Right. And if you're offering a library with UDAs for other people to use?
Re: Dealing with raw types as attributes
On Fri, 02 Nov 2018 04:01:00 +, Nicholas Wilson wrote: > By noting that all (interesting for the purpose of UDA's i.e. not void) > types have a .init > > or you could do > > static if (is(typeof(uda) == Foo) || is(uda == Foo)) Which, again, only tests for presence, when I want to check for presence *and* get the value, which should be Foo.init if the person supplied the raw type.
Re: Dub Renaming source/app.d makes project a library
targetType "executable" does it for me (dub 1.11.0). Can you post your full dub.sdl?
dip1000: why can't the addressee come into existence later?
The following code doesn't work with @safe -dip1000: int* p; int i; p = i has a shorter lifetime than p, the compiler complains. But this code does: int i; int* p; p = In both cases, p can't point to i before i exists, and p ceases to exist when i ceases to exist. I believe this is because the first option would let me write: struct Foo { bool exists = true; ~this() { exists = false; } void doStuff() { assert(exists); } } Foo* p; scope(exit) (*p).doStuff; Foo f; scope(exit) destroy(f); p = And this will run into the assert when -dip1000 should ensure it can't. The compiler does this even in the absence of scope guards and destructors because simple, obvious rules will be easier to understand and implement than nuanced ones, even if it makes you reorder declarations sometimes. Is this right?
Re: dip1000: why can't the addressee come into existence later?
On Sat, 10 Nov 2018 11:47:24 +, Nicholas Wilson wrote: > On Saturday, 10 November 2018 at 06:56:29 UTC, Neia Neutuladh wrote: >> Is this right? > > Are you sure you added @safe to the second example? > https://run.dlang.io/is/2RbOwK fails to compile. Maybe take another look at the post you're replying to? I was saying that, if the compiler allowed one thing that looked safe to me, it would either require nuance (check for scope guards, destructors, and the like before saying something is un-@safe) or allow other code that is obviously invalid.
Re: Exception slipping through the catch block?
On Thu, 08 Nov 2018 17:27:40 -0700, Jonathan M Davis wrote: > You ran into one of the rare cases where it makes sense catch an Error > or a Throwable, and you're one of the few people who understands the > situation well enough to deal with it properly. The vast majority of D > programmers don't. Certainly, anyone who has to ask about the > differences between Throwable, Error, and Exception doesn't. I really don't believe it's that rare or that fraught, most of the time. If an error happens, it's better for most programs to try to leave behind enough artifacts for you to start debugging the problem. Most of the time, a stacktrace on stderr is good enough and still possible. And that's what the runtime does. This isn't, strictly speaking, safe. Your program detected an error, and in Walter's book, that means you can't trust the program to do *anything*. Unwinding the stack, formatting a stacktrace, writing to stderr, this is all Dangerous Stuff You Shouldn't Be Doing. Even sending your process sigabrt to trigger a core dump is potentially dangerous. But the utility is greater than the likely harm, which is why druntime will unwind the stack, format a stacktrace, and write to stderr when an Error is thrown and not caught. Similarly, if your program logs to a file normally and you use that logfile for most of your debugging, it's sensible to try to log the error to that file and then exit. Especially if, like with H. S. Teoh's case, it's difficult or impossible for you to access the process's stderr. This is still *slightly* fraught. If your logging system is responsible for that Error being thrown, you probably won't succeed in logging the Error. If you have custom Error classes that do weird things, those things are more likely to break. Your application might be out of memory, so the allocations involved in logging could also fail. So, moderately fraught, but I don't think it's "here be dragons" any more than usual.
Re: Why is stdio ... stdio?
On Fri, 09 Nov 2018 02:03:36 +, Chris Katko wrote: > Simple curious question. > > Why isn't : > > import std.stdio; > > instead: > > import std.io; IO includes things like memory mapping, sockets, listing files, named pipes, that sort of thing. Standard IO includes only reading and writing to files and the console. > (Also, while we're at it. Why doesn't this form have code highlighting? > It would much improve readibility. Doesn't that seem almost essential > for a programming forum?) It's not a forum. It's a newsgroup that happens to have a web interface. Newsgroups are text-only. So bbcode is out, html is out, but interpreting markdown might be reasonable. But nobody's done that work.
Re: dip1000: why can't the addressee come into existence later?
On Sat, 10 Nov 2018 16:25:40 +, Stanislav Blinov wrote: > Yep, you just over-simplified the first case. It is too simple to clearly illustrate why the code is invalid, but not so simple that the compiler accepts that code. > Consider: > > int* p; > { > int i; > p = > } > *p = 42; In that example, the scope for i ends before the scope for p ends. It's not at all surprising that that code is wrong. In the other examples I gave, both i and p go out of scope at the same time. But there's a total ordering for when variables' lifetimes end, which is the key (and non-obvious) difference between the two.
Re: Is this a bug? +goto
On Tue, 06 Nov 2018 00:33:56 +, MatheusBN wrote: > Just to be clear, when you say "x exists at the label Q", you mean at > the same scope, right? The same or an outer scope. It's also invalid to write: goto Y; { int x; { Y: } } > That's interesting but a bit confusing isn't? > > And I found a bit strange that in such code, since "x" is never used, > why it isn't skipped. Because simple rules are usually easier to understand and implement. > I know it's another language but in C at least in GCC there is no error > over such code, so that's my confusion. Because C is a horribly unsafe language, far beyond necessary to have a low-level systems language. In C++, if you skip over `int i = 10;` it's an error, but not if you skip over `int i;`. Similarly, if you skip over a class variable declaration without an explicit initialization expression, if the class has a constructor or destructor, it's an error. In D, every variable of every type is initialized unless you opt out. The compiler *could* let you skip over declarations that are void-initialized, but there isn't a huge reason to do so.
Re: scoped classes and dependency inversion
On Thu, 08 Nov 2018 12:45:57 +, Alex wrote: > Hmm... not sure, if I got your idea... Do you think about something like > this? The point is dependency inversion. The class shouldn't need to know how to build its dependencies; it should leave that to other code. The fact that you can use the default constructor to build a thing is more coupling than desired.
Re: scoped classes and dependency inversion
On Thu, 08 Nov 2018 11:04:19 +, Sjoerd Nijboer wrote: > I'm trying to invert the dependency from the classes `Bar -> Foo` to > `Foo -> IFoo <- Bar` at compile time. > > I do want `Foo's` to be embedded into `Bar` These goals are a *little* at odds with each other; having a scoped!Foo puts significant constraints on how to build the object. But you know your needs a lot better than some generic advice. I believe what you need to do is pass a factory function into the constructor. This is a bit awkward. The really annoying part is that std.typecons doesn't have a named type for the scoped wrapper for a type. It's actively hostile to having scoped fields for no discernable reason. Filed https://issues.dlang.org/ show_bug.cgi?id=19379 Anyway, here's some code to make it work. It's kind of ugly. --- import std.stdio; import std.typecons; void main() { auto bar = new Bar!Foo((ref f) { f = scoped!Foo(); }); } class Bar(TFoo) if(is(TFoo : IFoo)) { alias SFoo = typeof(scoped!TFoo()); SFoo _foo; this(void delegate(ref SFoo) dg) { dg(_foo); } } class Foo : IFoo { void baz(){} } interface IFoo { void baz(); } ---
Re: Could not setup D extension on vs code
On Wed, 14 Nov 2018 19:28:44 +, WebFreak001 wrote: > It's a real pain that you can't select specific commits in dub, but I > try to keep up with the updates and make them work somehow. Yeah, I've used submodules and path-based dependencies once or twice because of that. It's not the best.
Re: static foreach
On 10/10/2018 04:03 PM, James Japherson wrote:> Says that it cannot interpret X(the class that contains the static> opApply). It's a bit hard to diagnose the problem you're getting using that function when we don't have the code that uses it. Or the context that's referenced with the foreach loop there. You might want to post a larger segment of code and the entire error message. The error I'm seeing that might be related is: opApply is a static member of the type. So part of the function (after mixins) reads: dg(X.opApply); This attempts to call X.opApply with no arguments and pass the result to dg. But X.opApply requires an argument. You probably want to add a `is(typeof(mixin("X." ~ m)) == cPiece)` in there.
Re: How to use listener.d example?
On Friday, 31 August 2018 at 07:38:54 UTC, Marcin wrote: https://github.com/dlang/dmd/blob/master/samples/listener.d Can some one add more comment to that example? I need to make code that connects to local application, very similar to this. Assumptions: 1. Create an application that listens to arguments. 2. Create an application that will send arguments to the application mentioned above. 3. The application will return the sine (argument) to the client. 4. All communication must be realized via console. Another, more structured way to do this is with an RPC framework like Apache Thrift. With Thrift, you'd write an interface description: --- namespace d math.api service Sine { double sine(1: double value); } --- In your application, you'd have something like: --- import vibe.d; import vibethrift; import math.api.Sine; class SineImpl : Sine { double sine(double value) { static import std.math; return std.math.sin(value); } } void main() { serve!Sine(new SineImpl, "0.0.0.0", ); return runApplication(); } --- Then you use the corresponding Thrift client to make requests against it. You could also do this with Vibe and REST: --- import vibe.d; class Sine { @path("/sine") string getSine(double value) { static import std.math; import std.conv : to; return std.math.sin(value).to!string; } } void main() { auto settings = new HTTPServerSettings; settings.port = ; auto router = new URLRouter; router.registerWebInterface(new Sine); listenHTTP(settings, router); runApplication(); } --- And then you can point your browser at http://localhost:/sine?value=1.5 and get back 0.997495. You can similarly use std.net.curl to make the request. But let's say you want to do everything yourself. That script is the server. Line 55 is the thing that handles the input. You need to put your code there. The remote application might send input in multiple packets. That means you have to collect input somewhere and figure out where the end is. You can either pass a length as the first part (usually a 4-byte value in network byte order), or require a special character to terminate the commend (I recommend the ASCII Record Separator character, U+001E, or the like), or know enough about your input to figure out where it ends anyway. Once you get the end of your input, you send it off somewhere to parse and process. It's up to you how you want to send numbers across. When you're done, you need to convert the output numbers back to bytes somehow and send them back with socket.send(), and then you close the connection. Once you've got that working, you need to write a client that does pretty much the same thing, but Socket.connect instead of the bind/listen/accept business, and you can just use Socket.read for the response rather than dealing with a SocketSet.
Re: extern __gshared const(char)* symbol fails
On Friday, 31 August 2018 at 06:20:09 UTC, James Blachly wrote: Hi all, I am linking to a C library which defines a symbol, const char seq_nt16_str[] = "=ACMGRSVTWYHKDBN"; In the C sources, this is an array of 16 bytes (17 I guess, because it is written as a string). In the C headers, it is listed as extern const char seq_nt16_str[]; When linking to this library from another C program, I am able to treat seq_nt16_str as any other array, and being defined as [] fundamentally it is a pointer. When linking to this library from D, I have declared it as: extern __gshared const(char)* seq_nt16_str; ***But this segfaults when I treat it like an array (e.g. by accessing members by index).*** I believe this should be extern extern(C)? I'm surprised that this segfaults rather than having a link error. A bare `extern` means "this symbol is defined somewhere else". `extern(C)` means "this symbol should have C linkage". When I try it with just `extern`, I see a link error: scratch.o: In function `_Dmain': scratch.d:(.text._Dmain[_Dmain]+0x7): undefined reference to `_D7scratch5cdataPa' collect2: error: ld returned 1 exit status Error: linker exited with status 1
Re: Load entire file, as a char array.
On Monday, 3 September 2018 at 03:04:57 UTC, Chris Katko wrote: This should be simple? All I want to do is load an entire file, and access individual bytes. The entire thing. I don't want to have know the file size before hand, or "guess" and have a "maximum size" buffer. So far, all google searches for "dlang binary file read" end up not working for me. Thank you. http://dpldocs.info/experimental-docs/std.file.read.1.html import std.file : read; auto bytes = read("filename"); This gives you a void[], which you can cast to ubyte[] or char[] or whatever you need.
Re: Simple parallel foreach and summation/reduction
On Thursday, 20 September 2018 at 05:34:42 UTC, Chris Katko wrote: All I want to do is loop from 0 to [constant] with a for or foreach, and have it split up across however many cores I have. You're looking at std.parallelism.TaskPool, especially the amap and reduce functions. Should do pretty much exactly what you're asking. auto taskpool = new TaskPool(); taskpool.reduce!((a, b) => a + b)(iota(1_000_000_000_000L));
Re: Neater enum + version
On Sun, 18 Nov 2018 17:47:07 +, Vladimirs Nordholm wrote: > Is there anyway to make it "neater"? Maybe something in one line: > > enum foo = version (Posix) { "posix" } : { "other" } ; If you're doing it often: T ifPosix(T)(T a, T b) { version (Posix) return a; else return b; } enum foo = ifPosix("posix", "other"); If it's a one-off thing, though, there's not much you can do.
Re: Subtypes with tighter constraints
On Tue, 01 Jan 2019 14:05:43 +, Victor Porton wrote: > In Ada2012 there are "subtypes". Subtypes can have tighter constraints > (such as type invariants) than their base types. > > I have a struct X in D. Is it possible to define a type equivalent to X > except that having tighter invariants? In D, structs don't participate in inheritance. Classes do, but invariants aren't inherited; they're specific to the class in which the function is defined. (Which is probably a bug and I filed https://issues.dlang.org/ show_bug.cgi?id=19537.) I see three ways to make this work today: 1. Use alias this to wrap the struct. Add invariants that deal with the wrapped struct's fields. 2. Use compile-time reflection to copy the fields over, then manually copy the invariants over and add more. 3. Use a class. Define a virtual function like 'doInvariant()`. Call it from the base class's invariant{} block. > As I understand if I derive Y from X, then it is no more X; that is I > cannot use X (even provided it matches Y invariants) where I need Y. So > in D it is impossible, right? With classes, a derived class instance can be used anywhere you expect a base class instance. The reverse is not true.
Re: Why can't or shouldn't I just hash the address of an object? And how.
On Sun, 30 Dec 2018 05:36:41 +, Enjoys Math wrote: > Is it: > > typeof(T).getHash()? This gets the hashcode for the object by calling toHash() on it. > Or does that do something other than just get the address? It XORs the address with a bitwise rotation of the address. This reduces collisions since objects are allocated aligned. As for your larger problem, I'd strongly tend toward using a database to hold application state instead of keeping it in memory.
Re: D-oriented Syntax Highlighting Plugin for WordPress?
On Tue, 01 Jan 2019 14:46:15 +, Ron Tarrant wrote: > I've found a ton of syntax highlighter plugins for WordPress, but none > that admit to supporting D. Anyone know of one? I believe I use Enlighter for that: https://wordpress.org/plugins/enlighter/
Re: Co-developing application and library
On Sat, 05 Jan 2019 13:01:24 +, Russel Winder wrote: > Dub seems to have the inbuilt assumption that libraries are dependencies > that do not change except via a formal release when you developing an > application. > Clearly there is the workflow where you want to amend the library but > not release as a part of developing an application. Does Dub have a way > of doing this, I haven't been able to infer one to date. But I am a > beginner at Dub. There are a few ways to do this: 1. Path dependency, as Alex mentioned. 2. Different build configurations. The same source code has two different build targets; the executable doesn't depend on the library. Or, with enough bludgeoning, you can make the executable depend on the library. 3. Subprojects. 4. dub add-local on the library, as Mike Parker mentioned. I wouldn't depend on ~master because (a) that won't change until you commit stuff and (b) it might require also running dub upgrade to get the new source code. The subproject way of doing things: --- # dub.sdl name "myproject" targetType "none" # So we build the child projects dependency "myproject:lib" version="*" dependency "myproject:exe" version="*" # To define the child projects subPackage "./lib" subPackage "./exe" --- --- # exe/dub.sdl name "exe" dependency "myproject:lib" version="*" targetType "executable" --- This will intuit a project structure like: dub.sdl exe/ dub.sdl src/ lib/ dub.sdl src/ But if you prefer, you can modify that with "sourcePaths" in the subpackage dub.sdls.
Re: Co-developing application and library
On Sat, 05 Jan 2019 17:44:27 +, Neia Neutuladh wrote: > 2. Different build configurations. The same source code has two > different build targets; the executable doesn't depend on the library. > Or, with enough bludgeoning, you can make the executable depend on the > library. Hit 'send' too soon. The build configuration way would be: --- # dub.sdl configuration "exe" { targetType "executable" } configuration "lib" { targetType "staticLibrary" excludedSourceFiles "src/cli/*" } --- Then you'd build with: dub build --config=lib dub build --config=exe To make this version of things yield an executable depending on a library, you'd use something like: --- # dub.sdl configuration "exe" { targetType "executable" excludedSourceFiles "src/lib/*" importPaths "src/lib" libs "-L." "-L-l:libmyproject.so" } configuration "lib" { targetType "sharedLibrary" excludedSourceFiles "src/cli/*" } --- The one advantage of this is being able to use shared libraries. It's awkward.
Re: Forward declaration inside Function block, no error?
On Sun, 06 Jan 2019 20:19:59 +, Rubn wrote: > You can declare functions inside of functions in D. You weren't forward > declare grow() in the module namespace, so much as you were forward > declaring a new function grow. Unfortunately, you can't do forward declarations for nested functions. If you could, that would be handy for mutual recursion: void main() { int a(int i); int b(int i) { if (i > 0) return a(i - 1); return abs(i); } int a(int i) { if (i % 2 == 0) return b(i - 2); return b(i - 1); } writeln(a(12)); } Unfortunately, Error: declaration a is already defined And omitting the forward declaration gets you: Error: undefined identifier a
Re: What is the Utility of Parent Class Method Hiding in Inheritance?
On Wed, 16 Jan 2019 12:01:06 -0500, Steven Schveighoffer wrote: > It was 2.068 that removed the HiddenFuncError, and made this a compile > error instead. If your compiler is that or newer, definitely file a bug > report. Oh god, that must have been awful. I'm glad we're no longer in those benighted times.
Re: unittest which uses a disk file
On Wed, 16 Jan 2019 21:07:24 +, Victor Porton wrote: > What is the rule for unittest which uses a file (containing example data > for testing) available only in the source distribution, not in binary > distribution? > > I am writing a library. The easy way of doing things is to define a version for your library's unittests. Like I might write: version (EpubTest) unittest { writeEbookFile("test.epub"); } And then in dub.sdl, I'd have the test configuration add -version=EpubTest. Dub has support for this sort of thing, but I don't know the details offhand. If you have extra dependencies or need extra environment setup, you might want to make a second dub package inside the same repository and give it a path-based dependency on your library. Normal people won't touch that second package, so you can do whatever you want there, and it's a good place to add another README.
Re: Runtime heterogeneous collections?
On Thu, 17 Jan 2019 02:21:21 +, Steven O wrote: > I want to create a heterogeneous collection of red-black trees, and I > can't seem to figure out if it's possible. RedBlackTree!int and RedBlackTree!string are entirely different types (they just happen to be generated from the same template). There are two reasonable ways of doing things: 1. Make a wrapper class. Now you can store Object[], or you can make a base class or base interface and use that. 2. Use Variant, which can wrap anything, or the related Algebraic, which can wrap a fixed collection of types. You can use this technique either with the collection types themselves or with the value types.
Re: Runtime heterogeneous collections?
On Fri, 18 Jan 2019 10:07:41 -0500, Steven Schveighoffer wrote: > But what is the common interface between those 2 types? Even in > Dcollections, where RedBlackTree came from, there was no interfaces that > didn't specify the type they were dealing with. In other words, there is > no common interface for sets of 2 different types. .empty(), .clear(), .length(), and .toString(sink, formatspec). Which is kind of anemic. Might as well use Object.
Re: Is there a nice syntax to achieve optional named parameters?
On Fri, 18 Jan 2019 09:39:31 +, John Burton wrote: > On Thursday, 17 January 2019 at 01:43:42 UTC, SrMordred wrote: > >> struct Config { >> string title; >> int width; >> } >> >> struct Window { >> this(Config config) > > It likely is a bad idea for a small struct like this but if it was much > bigger would it makes sense to write this as :- > > this(const ref Config config) > > Which is what you might do in C++ or does D handle this differently? Creating a window is the dominating cost here. If you're creating enough windows that copying them is a problem, you're doing something seriously weird and it might be more productive to step back and think about that than to switch to const ref.
Re: Deprecation
On Fri, 18 Jan 2019 22:53:23 +, Ali wrote: > Hello. I am having an issue with the code below. the out put after > compiling is this : > > Deprecation: foreach: loop index implicitly converted from size_t to > uint > > the code is : > > auto available = new int[cast(uint) max - min]; > foreach (uint i, ref a; available) > a = min + i; > > Any help would be highly appreciated. You are trying to use a uint (max value 2^32-1) to give an index for an array (which might be more than 2^32-1 elements long). That's deprecated and will be gone from the language in a few releases. Instead, write: foreach (size_t i, ref a; available) a = cast(uint)(min + i);
Re: What is the Utility of Parent Class Method Hiding in Inheritance?
On Mon, 14 Jan 2019 09:10:39 +, Vijay Nayar wrote: > a.foo(1); // issues runtime error (instead of calling > A.foo(int)) Calling the function doesn't issue any sort of error. Overriding one overload without overloading or explicitly aliasing in the rest issues a compile-time error. If you got a runtime error instead, please create a bug report. > I ran into this the other day, where I had a function of the same name > in a child class, and found that all functions in the parent of the same > name now became hidden, unless I add an alias statement. If the functions from the parent class are hidden but your code compiles, please create a bug report.
Re: problem extracting data from GtkSourceView using Gtkd
On Mon, 14 Jan 2019 22:52:48 +, Chris Bare wrote: > auto start = new TextIter(); > auto end = new TextIter(); You shouldn't need to new these. `out` means that the function is going to overwrite the variables. Other than that, I'm not sure.
Re: std.socket.Address not allowed in tuples
On Wed, 23 Jan 2019 15:56:15 +, Steven O wrote: > Why am I not allowed to put Address types in tuples? As always, it helps a lot to post the error message the compiler gave you. The message is: /usr/include/dmd/phobos/std/functional.d-mixin-215(215): Error: template std.typecons.Tuple!(Address, int).Tuple.opCmp cannot deduce function from argument types !()(Tuple!(Address, int)) inout, candidates are: /usr/include/dmd/phobos/std/typecons.d(806):std.typecons.Tuple! (Address, int).Tuple.opCmp(R)(R rhs) if (areCompatibleTuples! (typeof(this), R, "<")) /usr/include/dmd/phobos/std/typecons.d(820):std.typecons.Tuple! (Address, int).Tuple.opCmp(R)(R rhs) if (areCompatibleTuples! (typeof(this), R, "<")) /usr/include/dmd/phobos/std/container/rbtree.d(866): Error: template instance `std.functional.binaryFun!("a < b", "a", "b").binaryFun! (inout(Tuple!(Address, int)), Tuple!(Address, int))` error instantiating scratch.d(13):instantiated from here: RedBlackTree!(Tuple! (Address, int), "a < b", false) The last line says that the error came when trying to instantiate the RedBlackTree template. At that point, Tuple was instantiated. There is no issue putting an address in a Tuple. The issue is that Address doesn't have a comparison operator defined, so the resulting tuple type can't be compared with the standard operators. You need to define your own function for comparing the tuples in question and pass that to RedBlackTree.
Re: How to set constant value to environment variable at compile time?
On Mon, 10 Dec 2018 11:08:23 +, Narxa wrote: > Hello, people! > > I would like to have a constant with the value of some environment > variable that is defined at compile time. In your build script, echo the environment variable into a file. Then import() that file and use the value. > I know I could possibly use 'gdc' to achieve that but I want to use the > 'dmd' compiler. Defining variables like that is a language-level feature. gdc supports exactly the same options as dmd.
Re: How to set constant value to environment variable at compile time?
On Mon, 10 Dec 2018 17:58:32 +, aliak wrote: > string parseConfig(string str) { >string ret; >foreach (line; str.split("\n")) { > auto parts = line.split("="); > ret ~= `string ` ~ parts[0] ~ ` = "` parts[2] `";`; >} >return ret; > } That works as long as none of the environment variable values contain a double quote or a newline character.
Re: saving std.random RNG state
On Mon, 17 Dec 2018 22:20:54 +, harfel wrote: > I am looking for a way to serialize/deserialize the state of the > std.random.Random number generator, ideally using orange > (https://github.com/jacob-carlborg/orange) or another serialization > library. From looking at the module source code, I understand how to > seed a random number generator with the state of another, but I do find > a way to access the RNG's state, since it is hidden away in a private > attribute. What is the recommended solution for this? Thanks in advance! The .tupleof field allows you to access private members. This behavior might eventually change, but probably not without a long deprecation period. If the struct stores everything by value: cast(ubyte[])[0..1]; If you have typeinfo available, you can check if the thing has pointers with `(typeof(rng).flags & 1) == 0`. There's probably an equivalent in std.traits that works at compile time.
Re: How to deprecate member function from outside?
On Sat, 22 Dec 2018 18:55:47 +, Dru wrote: > I would like to use "deprecated" on a member function, but do it from a > separate file > > this works: > /// > void func() {} > > deprecated { >void func(); > } You're defining two functions, presumably in two different modules and with two different fully qualified names. One function is deprecated but has no body, so you will get a deprecation warning and a linker error if you try using it. One function is not deprecated and has a body, so you'll get no errors if you try using it. If, on the other hand, you define both the non-deprecated and deprecated functions in the same file, and you try using them, you'll get an error saying that the function call matches multiple functions.
Re: Bug in shifting
On Fri, 14 Dec 2018 00:16:51 +, Michelle Long wrote: > byte x = 0xF; > ulong y = x >> 60; "Error: shift by 60 is outside the range 0..31" This is the result of integer promotion rules. Change the 30 to a 60 and it works, and the result is, as you would expect, 0. > I thought D required breaks for cases? Seems it doesn't any longer! A number of things can terminate a case block: * break * continue * goto * assert * throw * return Probably a few others.
Re: How to initialize a globle variable nicely and properly?
On Sat, 15 Dec 2018 02:54:55 +, Heromyth wrote: > shared static this() { > writeln("running A in shared static this(), > sharedField=", sharedField); > > Thread th = new Thread(() { }); > th.start(); When you start a D thread, thread-local static constructors get run. So don't start threads until your shared static constructors finish. If I encountered something like this, I would set up a queue of actions to be run at the start of main() and fill them with static constructors. Instead of this static constructor creating a thread, it would enqueue a delegate that starts the thread.
Re: Mysteries of the Underscore
On Mon, 24 Dec 2018 08:16:01 -0800, H. S. Teoh wrote: > Rather, it's *conventionally* taken to mean "unused". The language > actually does not treat it in any special way apart from "normal" > identifiers. It's perfectly valid (though probably not recommended!) to > declare functions or variables with the name "_" and use them. I once, in my callow days, wrote a unittest with variables named _, __, ___, etc. It did not pass code review, but it did amuse.
Re: class template conflict
On Tue, 25 Dec 2018 13:03:13 +, Michelle Long wrote: > But I am not talking about inside the template being used. The whole > point of doing this is so that one can refer to the base class using the > same name as the derived with a template parameter to make a composite > structure. The following are entirely equivalent: class X(int N) : X {} template X(int N) { class X : X {} } You want to be able to do, essentially: class X {} template X(int N) { // `: X` somehow refers to the X in the outer scope class X : X {} } And sure, this specific case obviously doesn't work if the `: X` refers to the template or the class inside the template. But the symbol lookup rules aren't "try everything and see what sticks". You look up the nearest symbol and then you just use that. It would be like arguing that, in the following example, the compiler should know that ints aren't callable and should call the function: void foo() { writeln("merr critmis"); } void main() { int foo = 10; foo(); } Which isn't obviously wrong, but it does make things harder to understand.
Re: class template conflict
On Tue, 25 Dec 2018 16:55:36 +, Neia Neutuladh wrote: And I forgot part of it. Let's say we did the work to make this function: class X {} template X(int N) { // `: X` somehow refers to the X in the outer scope class X : X {} } How do you distinguish between the base class and the derived class in there? You'd have to use typeof(this) and typeof(super) everywhere. And externally, how do you refer to class X and template X separately? If you have a template with an alias parameter and pass X, how do you pass class-X and how do you pass template-X? This is already unpleasant with functions, and there's a way to distinguish them.
Re: Determination of thread status.
1. Find the Thread object: Tid threadId = spawn(); auto thread = Thread.getAll.filter!(x => x.id == threadId).front; 2. Check the `isRunning` property. The indirection with spawn() is awkward.
Re: How to deprecate member function from outside?
On Sat, 22 Dec 2018 21:33:14 +, Dru wrote: > The first example shows that it is possible to deprecate a function > separately from it's definition. No, it doesn't. You declared two *different* functions. One was deprecated; the other wasn't. > I want to know if it is possible to "fix" the second example? (deprecate > a member function separately from it's definition) No. All functions must be deprecated where you declare them.
Re: class template conflict
On Tue, 25 Dec 2018 18:34:04 +, bauss wrote: > I think there is a bigger problem at stake here in terms of software > architecture. > > What's the point needed for them to have the same identifier? A probably abstract base class with only one child class. Normally you have "Foo" and "FooImpl", or "IFoo" and "Foo", but that's ugly. This was the primary example that Michelle Long gave. I'd expect that a fair portion of people people who have used C# encountered this kind of situtaion. Like this sort of thing works in C#: class Foo {} class Foo : Foo {} class Foo : Foo {} You can do this in C# because each of these are *classes*, and some just happen to have type parameters. In D, you'd have one class and two templates, and you can't overload two symbols of different kinds, so you have to write it as: class Foo() {} class Foo(T): Foo!() {} class Foo(T, U): Foo!() {} In Java, for legacy reasons, this pattern is baked into the language; Foo always has another class, Foo, that it implicitly casts to and from. Some people take advantage of that. Most people who do both metaprogramming and OOP in D and have been doing that for a nontrivial amount of time probably encountered this exact same thing in D. I encountered it the first time before D2 was a thing. > Clearly the two classes will have two different functions and should be > named accordingly. They will have different implementations and may have different interfaces. The proposed use case is inheritance, so X!10's public interface will be a superset of X's (and likely identical). To give a slightly less contrived example, let's say you want to have some functions available to a scripting language. (I'm doing something like this in a side project for a CLI spreadsheet program.) Each function has a display name, help text, argument validation, and the function body. If I had done this in an OOP style (and I might end up reworking it to look more like this), I'd have something like: interface Function { string helpText(); string name(); Nullable!Error validateParameters(Val[] parameters); Val execute(Val[] parameters); } And then I'd have a convenience mechanism to produce a conforming class from a function with UDAs: class FunctionImpl(alias fn) : Function { override: string helpText() { return getUDAs!(fn, Help)[0].text; } string name() { return __traits(identifier, fn); } // etc } It would be slightly nicer to just have "Function" everywhere instead of both Function and FunctionImpl. Not enough to justify the complexity of the symbol lookup rules required. Not enough to make `class Foo(T)` mean something different from `template Foo(T) class Foo`. But it *would* be slightly nicer, and it would make things slightly more straightforward for people coming from C#.
Re: How to initialize a globle variable nicely and properly?
On Sat, 15 Dec 2018 13:49:03 +, Heromyth wrote: > Yes, it's very dangerous to create a new thread in shared static this(). > For a big project, it sometimes hard to identify this problem. Maybe, > the compiler should do something for this, should it? The runtime, more likely. There are plenty of problems in this vein that the compiler can't detect, but the runtime should be able to detect all of them. Filed https://issues.dlang.org/show_bug.cgi?id=19492
Re: Shared static this() not executed for unittest
On Sat, 15 Dec 2018 17:19:05 +, Timoses wrote: > Running `dub test` will output: > Running ./unit-test-library writeln: unittest All unit tests have been > run successfully. > > Why is the `shared static this()` not executed? Run `dub clean; dub test -v` and you'll see that main.d isn't compiled into the test library. dub test substitutes its own main() function over yours. In order to do this, it needs to not compile in your main() and to compile in its own. dmd doesn't have an option to replace main(), so dub drops that entire source file.
Re: using dub to compile plugins
On Fri, 21 Dec 2018 10:56:39 +, Atila Neves wrote: > I don't see how you can do this with dub, and I wouldn't attempt it > either. Just use make, and have make call dub for the main project (and > potentially any plugins that need it). Remember to make the dub targets > `.PHONY` since you don't want to be managing the D dependencies by hand. Or you could have it depend on dub.sdl, dub.selections.json, your D source files, and your string import files. Which is a bit more work but will result in a little less recompilation.
Re: what are the rules for @nogc and @safe attributes inference?
On Fri, 30 Nov 2018 20:41:03 +, ikod wrote: > I can't find the reason why nogc/nothrow can't be inferred in this case: > > class S(K,V) > { > auto get/*()*/(K a) { > return 0; > } > } > void main() @nogc nothrow { > S!(int, string) sia; > auto v = sia.get(1); > } class Nefarious : S!(int, string) { override int get(int a) { // Whoops, I used the GC return new char[a].length; } } The compiler can't prove that a variable of type S!(int, string) will not be of type Nefarious, which uses the GC, so it can't infer @nogc for S.get. However, if you make the function final, then the compiler can infer it to be pure nothrow @nogc @safe. Or if you use a struct instead of a class, structs don't do inheritance, so the compiler can infer attributes without worrying about nefarious inheritance. > But everything is ok if you uncomment parentheses after get. Templated functions are implicitly final.
Re: Function signature as string
On Thu, 29 Nov 2018 21:11:06 +, John Chapman wrote: > Is there any way to get a string representing a function's exact > signature as declared in the source? I can generate it myself using > reflection but it might not be 100% verbatim so wanted to know if > there's anything built in? > >foreach (m; __traits(allMembers, T)) { > alias member = __traits(getMember, T, m); > string signature = // Call some function to get "member"'s > signature as a string >} typeof().stringof should do it: void bar(string s, ref Foo!int i) {} void main() { writeln(typeof().stringof); } prints: void function(string s, ref Foo!int i)
Re: what are the rules for @nogc and @safe attributes inference?
On Fri, 30 Nov 2018 22:10:11 +, ikod wrote: > Thanks for explanation, got it. > > My case is actually > > interface I(K,V) > { > int get()(K); > } Interface functions must be abstract. Templated functions are implicitly final. Final things can't be abstract. If there's something about types K and V that determine whether you should be able to use the GC or not, you'll have to encode that explicitly.
Re: Compiling a template
On Thu, 06 Dec 2018 22:50:49 +, albertas-jn wrote: > If templates are a compile-time feature and instances of templates are > generated by compiler at compile time, why is it possible to compile a > template definition with dmd -lib or -c? You compile files, not individual declarations like a template. If you have a source file containing a hundred templates and nothing else, and you compile it, you'll get the same output as if you had an empty source file, byte for byte.
Re: Trying to get current function name results in compiler error with __traits
On Fri, 07 Dec 2018 02:37:34 +, Arun Chandrasekaran wrote: > I'm trying to get the current function name and apparently the commented > line errors out. > > What am I doing wrong? Referring to nested functions is weird. Dotted identifiers let you traverse aggregates. Modules, C++ namespaces (ugh), enums, structs, identifiers, unions, that sort of thing. They *don't* let you traverse functions to refer to symbols defined inside those functions. *Separately*, nested functions have names that look like dotted identifiers. But you can't use that to refer to them, because that would make it *very* awkward to do symbol lookup. For example: struct Foo { int bar; } Foo test() { void bar() { } writeln(); return Foo(); } Should the `writeln` line invoke the `test` function, get the `bar` field from its result, and take its address? Or should it take the address of the nested function `bar`?
Re: dmd -unittest works poorly with executables
On Sat, 08 Dec 2018 20:16:09 +, Andrew Pennebaker wrote: > I think it's lame to have to use magical code like `version(unittest) {} > else` to guard our main functions, when we run unit tests. Could D go > ahead and do the right thing, automatically shadowing our main functions > when the unit tests are run? The original intent was for unittests to run before main(). Your debug / test builds always run the unittests. This is awkward because unittests might sometimes actually be heavier tests that talk to a database or write to local files or change global state that would be used in main(). The normal technique with dub is to put *only* main() in app.d. Sometimes I take that a step further: I put a runMain() function somewhere in my project, and app.d's main() just calls that. Dub automatically excludes app.d from the unittest build. Minimum possible code outside the tested zone. Not necessarily awesome, but we do have workarounds.
Re: .dup vs operation on all elements
On Mon, 03 Dec 2018 21:27:52 +, faissaloo wrote: > Then shouldn't the following output false, false, true? An object reference is a pointer value. The pointer values are copied. The pointed-at objects are not copied. Furthermore, the syntax Object[6] array = new Object(); only allocates one Object. Each item in the array is an object reference to the same object.
Re: Why does nobody seem to think that `null` is a serious problem in D?
On Wed, 21 Nov 2018 20:15:42 +, welkam wrote: > In D classes are reference type and unless you mark them as final they > will have vtable. Even if you mark your class as final, it has a vtable because it inherits from Object, which has virtual functions. The ProtoObject proposal is for a base class that has no member functions. If you had a final class that inherited from ProtoObject instead of Object, it would have an empty vtable. > Lets face it most people dont mark their classes as > final. What all this mean is that EVERY access to class member value > goes trough indirection (additional cost) D classes support inheritance. They implicitly cast to their base types. They can add fields not present in their base types. If they were value types, this would mean you'd lose those fields when up-casting, and then you'd get memory corruption from calling virtual functions. That is a cost that doesn't happen with structs, I'll grant, but the only way to avoid that cost is to give up inheritance. And inheritance is a large part of the reason to use classes instead of structs. > and EVERY method call goes > trough 2 indirections (one to get vtable and second to call > function(method) from vtable). Virtual functions do, that is. That's the vast majority of class member function calls. > Now Java also have indirect vtable calls > but it also have optimization passes that convert methods to final if > they are not overridden. If Java didnt do that it would run as slow as > Ruby. Yeah, no. https://git.ikeran.org/dhasenan/snippets/src/branch/master/virtualcalls/ results Java and DMD both managed to de-virtualize and inline the function. DMD can do this in simple cases; Java can do this in a much wider range of cases but can make mistakes (and therefore has to insert guard code that will go back to the original bytecode when its hunches were wrong). If it were merely devirtualization that were responsible for Java being faster than Ruby, Ruby might be ten times the duration of Java (just as dmd without optimizations is within times the duration of dmd without optimizations). You could also argue that `int += int` in Ruby is another virtual call, so it should be within twenty times the speed of Java. Instead, it's 160 times slower than Java. > On top of that some > people want to check on EVERY dereference if pointer is not null. How > slow you want your programs to run? Every program on a modern CPU architecture and modern OS checks every pointer dereference to ensure the pointer isn't null. That's what a segfault is. Once you have virtual address space as a concept, this is free. > Thats negatives but what benefit classes give us? > First being reference type its easy to move them in memory. That would > be nice for compacting GC but D doesnt have compacting GC. You can do that with pointers, too. D doesn't do that because (a) it's difficult and we don't have the people required to make it work well enough, (b) it would make it harder to interface with other languages, (c) unions mean we would be unable to move some objects and people tend to be less thrilled about partial solutions than complete ones. > Second they > are useful for when you need to run code that some one else wrote for > your project. Something like plugin system. [sarcasm]This is happening > everyday[/sarcasm] > Third porting code from Java to D. > > Everything else you can do with struct and other D features. Similarly, you can write Java-style object oriented code in C. It's hideously ugly and rather error-prone. Every project trying to do it would do it in a different and incompatible way. Walter decided a long time ago that language support for Java-style OOP was a useful component for D to have, and having a standardized way of doing it with proper language support was better than leaving it to a library.
Re: version(StdDoc)
On Fri, 23 Nov 2018 17:21:25 -0800, H. S. Teoh wrote: > Ddoc may have its stink points, but in this case, the stuff inside > version(Windows) blocks simply isn't compiled, so you can't expect ddoc > to do much about it. You can't just arbitrarily ddoc everything inside > version blocks, because then you'll end up with ddocs for stuff inside > version(none) and/or conflicting docs for alternative declarations in, > say, OS-specific version blocks, or user-defined static if's. That means that, instead of one site showing my project's documentation, I need a separate site for every combination of platform and version flags. And users who care about differences between platforms and version flags need to manually cross-reference docs for every symbol and overload. It's a pretty terrible status quo.
Re: version(StdDoc)
On Fri, 23 Nov 2018 21:43:01 -0700, Jonathan M Davis wrote: > A solution like that might work reasonably well, but you still > have the problem of what to do when a symbol is documented in multiple > version blocks, and having almost all the documentation in one version > block and a few pieces of it in other version blocks would risk getting > confusing and messy. Keeping symbol names and function arguments consistent between them is also an issue; it's not just the documentation. The normal solution is to put the version blocks inside the relevant symbols -- sometimes type aliases inside version blocks and consistent code outside, sometimes functions where the entire body is a set of version blocks.
Re: How to get all modules in a package at CT?
Easiest way is to put this in your build script: find path/to/package -name '*.d' | \ xargs grep '^module ' | \ sed 's,^module,import,' \ > data/modules.d Add `-J data` to your DMD command line, or add `"stringImportPaths": ["data"]` to dub.json. Then in your file: mixin(import("modules.d"));
Re: Why does nobody seem to think that `null` is a serious problem in D?
On Tue, 20 Nov 2018 23:14:27 +, Johan Engelen wrote: > When you don't call `a.foo()` a dereference, you basically say that > `this` is allowed to be `null` inside a class member function. (and then > it'd have to be normal to do `if (this) ...` inside class member > functions...) That's what we have today: module scratch; import std.stdio; class A { int i; final void f() { writeln(this is null); writeln(i); } } void main() { A a; a.f(); } This prints `true` and then gets a segfault. Virtual function calls have to do a dereference to figure out which potentially overrided function to call.
Re: What is best way to read and interpret binary files?
On Mon, 19 Nov 2018 21:30:36 +, welkam wrote: > So my question is in subject/title. I want to parse binary file into D > structs and cant really find any good way of doing it. What I try to do > now is something like this > > byte[4] fake_integer; > auto fd = File("binary.data", "r"); > fd.rawRead(fake_integer); > int real_integer = *(cast(int*) fake_integer.ptr); > > What I ideally want is to have some kind of c style array and just cast > it into struct or take existing struct and populate fields one by one > with data from file. Is there a D way of doing it or should I call > core.stdc.stdio functions instead? Nothing stops you from writing: SomeStruct myStruct; fd.rawRead((cast(ubyte*))[0..SomeStruct.sizeof]); Standard caveats about byte order and alignment.
Re: Why does nobody seem to think that `null` is a serious problem in D?
On Mon, 19 Nov 2018 21:23:31 +, Jordi Gutiérrez Hermoso wrote: > When I was first playing with D, I managed to create a segfault by doing > `SomeClass c;` and then trying do something with the object I thought I > had default-created, by analogy with C++ syntax. Seasoned D programmers > will recognise that I did nothing of the sort and instead created c is > null and my program ended up dereferencing a null pointer. Programmers coming from nearly any language other than C++ would find it expected and intuitive that declaring a class instance variable leaves it null. The compiler *could* give you a warning that you're using an uninitialized variable in a way that will lead to a segfault, but that sort of flow analysis gets hard fast. If you wanted the default constructor to be called implicitly, that would make @nogc functions behave significantly differently (they'd forbid declarations without explicit initialization or would go back to default null), and it would be a problem for anything that doesn't have a no-args constructor (again, this would either be illegal or go back to null). Easier for everything to be consistent and everything to be initialized to null.
Re: What is best way to read and interpret binary files?
On Mon, 19 Nov 2018 14:32:55 -0800, H. S. Teoh wrote: >> Standard caveats about byte order and alignment. > > Alignment shouldn't be a problem, since local variables should already > be properly aligned. Right, and the IO layer probably doesn't need to read to aligned memory anyway. Struct fields, however, need to have the same relative alignment as the file.
Re: Why does nobody seem to think that `null` is a serious problem in D?
On Tue, 20 Nov 2018 00:30:44 +, Jordi Gutiérrez Hermoso wrote: > On Monday, 19 November 2018 at 21:57:11 UTC, Neia Neutuladh wrote: > >> Programmers coming from nearly any language other than C++ would find >> it expected and intuitive that declaring a class instance variable >> leaves it null. > > What do you think about making the syntax slightly more explicit and > warn or possibly error out if you don't do it that way? The prevailing idea is that warnings are either non-problems, in which case they shouldn't be emitted, or things you really need to fix, in which case they should be errors. Things that are sometimes errors can be left to lint tools. > Either > >SomeClass c = null; > > or > >SomeClass c = new SomeClass(); > > and nothing else. That would work, though it would be mildly tedious. However, the general philosophy with D is that things should be implicitly initialized to a default state equal to the `.init` property of the type. That default state can be user-defined with structs, but with other types, it is generally an 'empty' state that has well-defined semantics. For floating point values, that is NaN. For integers, it's 0. For arrays, it's a null array with length 0. For objects and pointers, it's null. > Nulls/Nones are always a big gap in a language's type system. A common > alternative is to have some Option/Maybe type like Rust or Haskell or > D's Variant. Variant is about storing arbitrary values in the same variable. Nullable is the D2 equivalent of Option or Maybe. > How about making that required to plug the null gap? That's extremely unlikely to make it into D2 and rather unlikely to make it into a putative D3. However, if you feel strongly enough about it, you can write a DIP. I've used Kotlin with its null safety, and I honestly haven't seen benefits from it. I have seen some NullPointerExceptions in slightly different places and some NullPointerExceptions instead of empty strings in log messages, but that's it.