Re: DIP 1009 (Add Expression-Based Contract Syntax) Accepted
On Wednesday, April 11, 2018 05:23:58 really? via Digitalmars-d-announce wrote: > On Friday, 6 April 2018 at 17:36:20 UTC, H. S. Teoh wrote: > > Yeah, I think having expression syntax will make contracts more > > readable. We'll just have to see. > > Sorry, but I fail to see how (1) is more readable than (2) > > (1) > in(s.length > 0, "s must not be empty") > > (2) > in { assert(s.length > 0, "s must not be empty"); } > > > In (1) The assert .. is removed. > In (1) The scope indicators {} .. are removed. > In (1) The semicolon..is removed. > > Removing all these things equates to being more readable?? > > Sure, it makes it more concise, but more readable?? > > I assert that it does not. But now..do I use the assert keyword.. > or not? Do I end with semicolon..or not?? > > This just removes things that are still needed elsewhere in your > code, but now... you have to remember that sometimes you need > those things, and sometimes you don't. > > Better to have consistency over conciseness > > so glad to hear that existing syntax will remain. > (well, till someone decides that needs to go too) Many have considered the verboseness of contracts to be a major reason to avoid them. The newer syntax will help with that in the cases where all you need is a series of assertions. However, regardless of how anyone feels about the new syntax, there are cases where you need more than just a series of assertions (e.g. you need to declare one or more variables to use in the assertions). The older syntax is required for such cases, and it would make no sense to remove it even if we didn't care about avoiding code breakage. So, if you prefer the older syntax, then feel free to use it, even if the newer syntax will work. You'll be stuck reading the newer syntax in the code of anyone who prefers the newer syntax, so you can't necessarily avoid dealing with it, but you're not going to be forced to switch to the newer syntax if you don't want to. Personally, I think that new syntax is very straightforward. It may take some getting used to, but it's basically the same syntax as an assertion except that it has a different keyword, and because it's not a statement, it doesn't need a semicolon. It makes sense in its context, and ultimately, I don't think that it's really going to be readability problem. That being said, I'm probably still not going to bother with contracts simply because I don't see any real benefit over just putting assertions inside the function except in the cases where inheritance is involved. I find it a lot more tolerable than the old syntax, but I still find it to be pointless so long as contracts are the same thing as putting assertions inside the function (except when inheritance is involved). IMHO, for contracts to be worth much outside of the inheritance case, we'd need to do something like make it so that contracts are compiled in based on whether the caller used -release or not rather than whether the callee did. If that were done, then there would be real value in using contracts, and I'd be a lot more excited about the new syntax. As it is, it seems like a nice improvement that's ultimately pointless. - Jonathan M Davis
Re: DIP 1009 (Add Expression-Based Contract Syntax) Accepted
On Friday, 6 April 2018 at 17:36:20 UTC, H. S. Teoh wrote: Yeah, I think having expression syntax will make contracts more readable. We'll just have to see. Sorry, but I fail to see how (1) is more readable than (2) (1) in(s.length > 0, "s must not be empty") (2) in { assert(s.length > 0, "s must not be empty"); } In (1) The assert .. is removed. In (1) The scope indicators {} .. are removed. In (1) The semicolon..is removed. Removing all these things equates to being more readable?? Sure, it makes it more concise, but more readable?? I assert that it does not. But now..do I use the assert keyword.. or not? Do I end with semicolon..or not?? This just removes things that are still needed elsewhere in your code, but now... you have to remember that sometimes you need those things, and sometimes you don't. Better to have consistency over conciseness so glad to hear that existing syntax will remain. (well, till someone decides that needs to go too)
Re: Parse .eml files
On Monday, 9 April 2018 at 19:17:20 UTC, Adam D. Ruppe wrote: [...] I had a chance to try this out and it worked without a problem. I did have to download color.d in addition to the other dependencies you listed. In the event that Google brings someone here, this is a complete working program: import std.file, std.stdio, std.string; import arsd.email; void main(string[] args) { string[] f = std.file.readText(args[1]).splitLines(); auto em = new IncomingEmailMessage(f); writeln("From: ", em.from); writeln("To: ", em.to); writeln("Subject: ", em.subject); writeln(em.textMessageBody); } Compile with dmd *.d -ofreademail And run ./reademail 'email message.eml'
Re: d2sqlite3 db.run, where lies the bug?
ag0aep6g, thank you most of all for fixing the bug, the removal of my immediate frustration! Also for the thorough step-wise instruction on sleuthing and fixing it. > > If you want, you can make a bug report or a pull request with the fix. > Otherwise, if you're not up to that, I can make one. > Generous, I merely stumbled on it and shouted out, you fixed it. I would be grateful if you please file the bug and your fix. (I thought I might have more to report, but your fix has resolved my multitude of issues with several texts). I did copy my original post to the author of d2sqlite3 (and again this reply which includes your fix), so he hopefully has the information required to make the upstream fix. The diff/patch I used: diff -Naur d2sqlite3-0.16.0/d2sqlite3/source/d2sqlite3/internal/util.d d2sqlite3-0.16.0-1/d2sqlite3/source/d2sqlite3/internal/util.d --- d2sqlite3-0.16.0/d2sqlite3/source/d2sqlite3/internal/util.d 2018-04-10 20:34:11.584498926 -0400 +++ d2sqlite3-0.16.0-1/d2sqlite3/source/d2sqlite3/internal/util.d 2018-04-10 20:46:09.869812899 -0400 @@ -65,13 +65,14 @@ { import std.algorithm : countUntil; import std.string : toStringz; +import std.utf: byCodeUnit; size_t pos; bool complete; do { auto tail = sql[pos .. $]; -immutable offset = tail.countUntil(';') + 1; +immutable offset = tail.byCodeUnit.countUntil(';') + 1; pos += offset; if (offset == 0) pos = sql.length; (if patch is contained in patchfile called d2sqlite3_bugfix.diff and at the same directory level as subdirectory containing d2sqlite3-0.16.0) cp -av d2sqlite3-0.16.0 d2sqlite3-0.16.0-1 \ && cd d2sqlite3-0.16.0-1 \ && patch -Np1 < ../d2sqlite3_bugfix.diff On Tue, Apr 10 2018, ag0aep6g via Digitalmars-dwrote: > On 04/10/2018 08:04 PM, Ralph Amissah wrote: >> The exact location of problem may be provided in the error statement >> "core.exception.UnicodeException@src/rt/util/utf.d(292): invalid >> UTF-8 sequence". >> > [...] >> Mock problem string with test code follows (d2sqlite3 required): >> > [... code ...] [... snip ...] > > From the exception's stack trace we see that > `d2sqlite3.internal.util.byStatement(immutable(char)[]).ByStatement.findEnd` > is the deepest non-Phobos function involved. So that's a good first spot > to look for a bug. Let's check it out. > > https://github.com/biozic/d2sqlite3/blob/2e8211946ae0e09646d561aeae1361a695adcc17/source/d2sqlite3/internal/util.d#L64-L83 > > And indeed, there's a bug in these lines: > > > auto tail = sql[pos .. $]; > immutable offset = tail.countUntil(';') + 1; > pos += offset; > > > `pos` is used to slice the string `sql`. That means, `pos` is > interpreted as a number of UTF-8 code *units*. But then the result of > `countUntil` is added. `countUntil` counts code *points*. So a number of > code points is mistaken as a number of code units. That means the next > slicing can be incorrect and split up a multibyte sequence. And then > `countUntil` will complain about broken UTF-8. > > This can be fixed by letting `countUntil` operate on count code units > instead: > > > import std.utf: byCodeUnit; > immutable offset = tail.byCodeUnit.countUntil(';') + 1; > > > If you want, you can make a bug report or a pull request with the fix. > Otherwise, if you're not up to that, I can make one. > > [...] >>- DMD64 D Compiler v2.074.1 > > That's rather old. I'd recommend updating if possible. for the time being it reflects the status of the rolling development branch of Debian. LDC is based on a newer version. Thanks again. Ralph Amissah
Re: Strange Thread Causing Duplicating `writeln`
On 4/9/18 6:56 PM, Jonathan wrote: On Monday, 9 April 2018 at 22:53:31 UTC, Jonathan wrote: On Monday, 9 April 2018 at 22:49:07 UTC, Cym13 wrote: I don't know, but I can't reproduce either with dmd or ldc. What was your compilation line? dmd -run file.d I am on Window 10 btw. It's a windows 32-bit issue (specifically, DMC's FILE *, upon which std.stdio.File is based, is thread unsafe). Try -m64. https://issues.dlang.org/show_bug.cgi?id=18483 http://bugzilla.digitalmars.com/issues/show_bug.cgi?id=327 -Steve
Re: Should "a is b" compile if a and b have unrelated classes?
On 4/10/18 5:52 PM, Michael Coulombe wrote: I had a bug in my code that was messing me up for a while, and it boiled down to an identity check between two Object references with unrelated static types, like below: class A {} class B {} void main() { A a = new A; B b = new B; if (a is b) {} // compiles } I was surprised that the type system failed me here. It's true that A and B could be upcast to Object and then comparisons would make sense type-wise, but the comparison should never pass (and the compiler should know it won't since they are in separate inheritance subtrees) unless the programmer is intentionally breaking the type system. Is there reasoning for this? If not, should it be a warning or error, as it is for example when comparing two pointers to structs of different types? Probably the reason is laziness. Sure it could be outlawed. But `is` has a special connotation of "identity", meaning it's EXACTLY the same. Let's look at what does compile: https://run.dlang.io/is/KHcHCc So there is at least some type checking for `is`, when it comes to pointers. There's definitely a precedent for this. The question is, should it just fold to "false", or should it fail to compile? If we change it to an error, there may be some unintentional code breakage out there. -Steve
Re: #include C headers in D code
On Tuesday, 10 April 2018 at 20:32:05 UTC, Seb wrote: On Tuesday, 10 April 2018 at 16:51:57 UTC, Atila Neves wrote: If you get to the point where you can #include , it will be doubly impressive! Not *if*, *when*. ;) Atila FYI people have been fighting with this for a long time: https://github.com/dlang/druntime/pull/1316 The beauty of using libclang is that name mangling issues don't exist. :) It's still not going to be easy, but that's one worry I won't have to bother with. Atila
Re: Range length property
On 4/10/18 6:07 PM, Cym13 wrote: On Tuesday, 10 April 2018 at 20:08:14 UTC, Jonathan M Davis wrote: On Tuesday, April 10, 2018 19:47:10 Nordlöw via Digitalmars-d-learn wrote: On Tuesday, 10 April 2018 at 14:34:40 UTC, Adam D. Ruppe wrote: > On Tuesday, 10 April 2018 at 14:25:52 UTC, Nordlöw wrote: >> Should ranges always provide a length property? > > No. > >> If so, in which cases is a length property an advantage or >> a requirement? > > Just provide it whenever it is cheap to do so. If you need > to do complex calculations or especially loop over contents > to figure out the length, do NOT provide it. > > But if it is as simple as returning some value, provide it > and algorithms can take advantage of it for optimizations > etc. as needed. I'm thinking of my own container Hashmap having its range ByKeyValue requiring one extra word of memory to store the iteration count which, in turn, can be used to calculate the length of the remaining range. Is this motivated? That would depend entirely on what you're trying to do, but in general, if a range has length, then some algorithms will be more efficient, and some algorithms do require length. So, if you can provide length, then the range will be more useful, just like a bidirectional range can be more useful than a forward range or a random-access range can be more useful than either. However, if you're not doing anything that ever benefits from it having length, then it doesn't buy you anything. So, it ultimately depends on what you're doing. In a general purpose library, I'd say that it should have length if it can do so in O(1), but if it's just for you, then it may or may not be worth it. The other thing to consider is what happens when the container is mutated. I don't think that ranges necessarily behave all that well when an underlying container is mutated, but it is something that has to be considered when dealing with a range over a container. Even if mutating the underlying container doesn't necessarily invalidate a range, maintaining the length in the manner that you're suggesting probably makes it so that it would be invalidated in more cases, since if any elements are added or removed in the portion that was already popped off the range, then the iteration count couldn't be used to calculate the length in the same way anymore. Now, with a hash map, the range is probably fully invalidated when anything gets added or removed anyway, since that probably screws with the order of the elements in the range, but how the range is going to behave when the underlying container is mutated and how having the length property does or doesn't affect that is something that you'll need to consider. - Jonathan M Davis I find that discussion very interesting as I had never considered that because of design by introspection having a costly length method would lead to unexpected calls by generic algorithms making it a disadventage if present. On the other hand I don't think the end user should have to scratch his head to find the length of a range, especially if it's not trivial to get (say, O(log n) kind of case). Therefore exposing a method in any case seems the best from an API perspective. O(lg n) is fine for .length, it doesn't need to be O(1). It just can't be O(n). I think we established that "fast" operations are O(lg n) or better. That being said, I don't know of a use case where you can get the length in O(lg n). It's usually O(1) or O(n). But to avoid the performance issues mentionned earlier it means it should bear a different name (get/setLength comes to mind). I believe this is the same kind of issue that lead to having "in" for associative arrays but not regular ones. However this also leads to less coherent APIs in contradiction with the principle of least surprise. It's definitely a tradeoff. It pushes some implementation details to the user, but it also makes the runtime complexity more predictable. In retrospect since only "unexpected" calls to such methods cause the issue I wonder if it wouldn't be best to have an UDA saying "Hey, please, this method is costly, if you're a generic template performing introspection you should probably not call me". And writing that Andrei's work on complexity annotations comes to mind. Anyway, I don't think the user should use different names just to alleviate an issue on the library side but the alternative would be costly to put in place... Potentially, but remember at the time length and walkLength were conceived, UDA's didn't exist! Using UDAs would also have the unfortunate side effect of eliminating self-documentation. When you see walkLength right now, you know it's "slow", when you see length, you know "fast". If you have to look at UDAs to figure that out, then reading the code is that much harder. -Steve
Re: Range length property
On Tue, Apr 10, 2018 at 10:07:40PM +, Cym13 via Digitalmars-d-learn wrote: [...] > On the other hand I don't think the end user should have to scratch > his head to find the length of a range, especially if it's not trivial > to get (say, O(log n) kind of case). Therefore exposing a method in > any case seems the best from an API perspective. > > But to avoid the performance issues mentionned earlier it means it > should bear a different name (get/setLength comes to mind). I believe > this is the same kind of issue that lead to having "in" for > associative arrays but not regular ones. However this also leads to > less coherent APIs in contradiction with the principle of least > surprise. [...] I've run into this in my own code, and I've been using `walkLength` as the name of the method, just for consistency with Phobos' walkLength. I'm not 100% sure this is a good idea, since overloading Phobos names can sometimes lead to annoying symbol conflict situations. But the one good thing is that you won't forget what it's called because it's so familiar. T -- An elephant: A mouse built to government specifications. -- Robert Heinlein
Re: Should "a is b" compile if a and b have unrelated classes?
On Tuesday, April 10, 2018 21:52:22 Michael Coulombe via Digitalmars-d-learn wrote: > I had a bug in my code that was messing me up for a while, and it > boiled down to an identity check between two Object references > with unrelated static types, like below: > > class A {} > class B {} > void main() { > A a = new A; > B b = new B; > if (a is b) {} // compiles > } > > I was surprised that the type system failed me here. It's true > that A and B could be upcast to Object and then comparisons would > make sense type-wise, but the comparison should never pass (and > the compiler should know it won't since they are in separate > inheritance subtrees) unless the programmer is intentionally > breaking the type system. > > Is there reasoning for this? If not, should it be a warning or > error, as it is for example when comparing two pointers to > structs of different types? Well, the compiler can't simply say that they're different classes and refuse to compare their references. It could look at the class hierarchy and determine that there's no way that the two are the same reference, because neither A nor B is a subclass of the other and thus treat it as an error - which I gather is what you're suggesting it should do. However, because doing that is more complicated, I suspect that it just doesn't bother. With struct pointers, it can at least see at a glance that one can't be the other, whereas it has to do a lot more examination of the type if it's class references. It's probably a reasonable enhancement request, though I'm not sure that it really matters much. One potential issue is that since opEquals is unfortunately part of Object, it's perfectly legal to do if(a == b) even though a and b can never be equal, so if is were disallowed in this case, then we'd get a situation where a == b compiles but a is b doesn't which would be a bit weird - though presumably, if we do end up going with some form of Andrei's ProtoObject proposal where we get a new root class beneath Object, then we'd definitely have classes that could be compared with is but not ==. So, that may not be all that big a deal as weird as it may be. My bigger concern would be how it would interact with generic code. It's not uncommon that stuff that at first glance seems like it should be disallowed would actually cause a fair but of grief in generic code (e.g. that's at least part of why it's usually the case that function attributes that don't apply are just ignored rather than treated as errors). If it definitely wasn't going to cause problems for generic code, then such a change would probably be reasonable, but I have no idea how likely it would be to cause problems in generic code. So, maybe? You can certainly open an enhancement request about it. - Jonathan M Davis
Re: Range length property
On Tuesday, April 10, 2018 22:07:40 Cym13 via Digitalmars-d-learn wrote: > On Tuesday, 10 April 2018 at 20:08:14 UTC, Jonathan M Davis wrote: > > On Tuesday, April 10, 2018 19:47:10 Nordlöw via > > > > Digitalmars-d-learn wrote: > >> On Tuesday, 10 April 2018 at 14:34:40 UTC, Adam D. Ruppe wrote: > >> > On Tuesday, 10 April 2018 at 14:25:52 UTC, Nordlöw wrote: > >> >> Should ranges always provide a length property? > >> > > >> > No. > >> > > >> >> If so, in which cases is a length property an advantage or > >> >> a requirement? > >> > > >> > Just provide it whenever it is cheap to do so. If you need > >> > to do complex calculations or especially loop over contents > >> > to figure out the length, do NOT provide it. > >> > > >> > But if it is as simple as returning some value, provide it > >> > and algorithms can take advantage of it for optimizations > >> > etc. as needed. > >> > >> I'm thinking of my own container Hashmap having its range > >> ByKeyValue requiring one extra word of memory to store the > >> iteration count which, in turn, can be used to calculate the > >> length of the remaining range. Is this motivated? > > > > That would depend entirely on what you're trying to do, but in > > general, if a range has length, then some algorithms will be > > more efficient, and some algorithms do require length. So, if > > you can provide length, then the range will be more useful, > > just like a bidirectional range can be more useful than a > > forward range or a random-access range can be more useful than > > either. However, if you're not doing anything that ever > > benefits from it having length, then it doesn't buy you > > anything. So, it ultimately depends on what you're doing. In a > > general purpose library, I'd say that it should have length if > > it can do so in O(1), but if it's just for you, then it may or > > may not be worth it. > > > > The other thing to consider is what happens when the container > > is mutated. I don't think that ranges necessarily behave all > > that well when an underlying container is mutated, but it is > > something that has to be considered when dealing with a range > > over a container. Even if mutating the underlying container > > doesn't necessarily invalidate a range, maintaining the length > > in the manner that you're suggesting probably makes it so that > > it would be invalidated in more cases, since if any elements > > are added or removed in the portion that was already popped off > > the range, then the iteration count couldn't be used to > > calculate the length in the same way anymore. Now, with a hash > > map, the range is probably fully invalidated when anything gets > > added or removed anyway, since that probably screws with the > > order of the elements in the range, but how the range is going > > to behave when the underlying container is mutated and how > > having the length property does or doesn't affect that is > > something that you'll need to consider. > > > > - Jonathan M Davis > > I find that discussion very interesting as I had never considered > that because of design by introspection having a costly length > method would lead to unexpected calls by generic algorithms > making it a disadventage if present. > > On the other hand I don't think the end user should have to > scratch his head to find the length of a range, especially if > it's not trivial to get (say, O(log n) kind of case). Therefore > exposing a method in any case seems the best from an API > perspective. > > But to avoid the performance issues mentionned earlier it means > it should bear a different name (get/setLength comes to mind). I > believe this is the same kind of issue that lead to having "in" > for associative arrays but not regular ones. However this also > leads to less coherent APIs in contradiction with the principle > of least surprise. > > In retrospect since only "unexpected" calls to such methods cause > the issue I wonder if it wouldn't be best to have an UDA saying > "Hey, please, this method is costly, if you're a generic template > performing introspection you should probably not call me". And > writing that Andrei's work on complexity annotations comes to > mind. Anyway, I don't think the user should use different names > just to alleviate an issue on the library side but the > alternative would be costly to put in place... > > Any thoughts? In general, if you care about efficient code, it becomes critical that anything that's going to be used in generic code has well-known Big-O complexity, which is why C++ cares about that sort of thing with its containers and why Andrei specifically put the Big-O complexity of all of the generic container operations in std.container. And that extends to ranges. If ranges are implemented without any care about the algorithmic complexity of the operations, then performance is ultimately going to tank. And in the case of ranges, it's really not all that hard to understand the algorithmic complexity, because
Re: Range length property
On Tuesday, 10 April 2018 at 20:08:14 UTC, Jonathan M Davis wrote: On Tuesday, April 10, 2018 19:47:10 Nordlöw via Digitalmars-d-learn wrote: On Tuesday, 10 April 2018 at 14:34:40 UTC, Adam D. Ruppe wrote: > On Tuesday, 10 April 2018 at 14:25:52 UTC, Nordlöw wrote: >> Should ranges always provide a length property? > > No. > >> If so, in which cases is a length property an advantage or >> a requirement? > > Just provide it whenever it is cheap to do so. If you need > to do complex calculations or especially loop over contents > to figure out the length, do NOT provide it. > > But if it is as simple as returning some value, provide it > and algorithms can take advantage of it for optimizations > etc. as needed. I'm thinking of my own container Hashmap having its range ByKeyValue requiring one extra word of memory to store the iteration count which, in turn, can be used to calculate the length of the remaining range. Is this motivated? That would depend entirely on what you're trying to do, but in general, if a range has length, then some algorithms will be more efficient, and some algorithms do require length. So, if you can provide length, then the range will be more useful, just like a bidirectional range can be more useful than a forward range or a random-access range can be more useful than either. However, if you're not doing anything that ever benefits from it having length, then it doesn't buy you anything. So, it ultimately depends on what you're doing. In a general purpose library, I'd say that it should have length if it can do so in O(1), but if it's just for you, then it may or may not be worth it. The other thing to consider is what happens when the container is mutated. I don't think that ranges necessarily behave all that well when an underlying container is mutated, but it is something that has to be considered when dealing with a range over a container. Even if mutating the underlying container doesn't necessarily invalidate a range, maintaining the length in the manner that you're suggesting probably makes it so that it would be invalidated in more cases, since if any elements are added or removed in the portion that was already popped off the range, then the iteration count couldn't be used to calculate the length in the same way anymore. Now, with a hash map, the range is probably fully invalidated when anything gets added or removed anyway, since that probably screws with the order of the elements in the range, but how the range is going to behave when the underlying container is mutated and how having the length property does or doesn't affect that is something that you'll need to consider. - Jonathan M Davis I find that discussion very interesting as I had never considered that because of design by introspection having a costly length method would lead to unexpected calls by generic algorithms making it a disadventage if present. On the other hand I don't think the end user should have to scratch his head to find the length of a range, especially if it's not trivial to get (say, O(log n) kind of case). Therefore exposing a method in any case seems the best from an API perspective. But to avoid the performance issues mentionned earlier it means it should bear a different name (get/setLength comes to mind). I believe this is the same kind of issue that lead to having "in" for associative arrays but not regular ones. However this also leads to less coherent APIs in contradiction with the principle of least surprise. In retrospect since only "unexpected" calls to such methods cause the issue I wonder if it wouldn't be best to have an UDA saying "Hey, please, this method is costly, if you're a generic template performing introspection you should probably not call me". And writing that Andrei's work on complexity annotations comes to mind. Anyway, I don't think the user should use different names just to alleviate an issue on the library side but the alternative would be costly to put in place... Any thoughts?
Should "a is b" compile if a and b have unrelated classes?
I had a bug in my code that was messing me up for a while, and it boiled down to an identity check between two Object references with unrelated static types, like below: class A {} class B {} void main() { A a = new A; B b = new B; if (a is b) {} // compiles } I was surprised that the type system failed me here. It's true that A and B could be upcast to Object and then comparisons would make sense type-wise, but the comparison should never pass (and the compiler should know it won't since they are in separate inheritance subtrees) unless the programmer is intentionally breaking the type system. Is there reasoning for this? If not, should it be a warning or error, as it is for example when comparing two pointers to structs of different types?
Re: Range length property
On Tuesday, 10 April 2018 at 20:16:18 UTC, Steven Schveighoffer wrote: e.g. std.array.array is going to pre-allocate an array of the correct length and fill it in, vs. appending each element as it gets them from the range. Personally, I would store the length because typically a container range is short-lived. It also jives with the container itself which likely has O(1) length. Thanks, that's what I thought too.
Re: #include C headers in D code
On Tuesday, 10 April 2018 at 20:32:05 UTC, Seb wrote: On Tuesday, 10 April 2018 at 16:51:57 UTC, Atila Neves wrote: If you get to the point where you can #include , it will be doubly impressive! Not *if*, *when*. ;) Atila FYI people have been fighting with this for a long time: https://github.com/dlang/druntime/pull/1316 FYI this appears to work just fine in Calypso: https://github.com/Syniurge/Calypso/blob/master/tests/calypso/libstdc%2B%2B/vector.d — David
Re: code-d 0.17.0 + serve-d 0.1.2
On Tuesday, 10 April 2018 at 03:37:59 UTC, evilrat wrote: On Monday, 9 April 2018 at 19:10:46 UTC, Samson wrote: [...] Disable "normal" code-d, close VS, remove %appdata%/code-d, launch VS & enable code-d beta serve-d, enjoy. [...] Thanks, your suggestion work for me. Many thanks to you
Re: code-d 0.17.0 + serve-d 0.1.2
On Tuesday, 10 April 2018 at 03:37:59 UTC, evilrat wrote: On Monday, 9 April 2018 at 19:10:46 UTC, Samson wrote: [...] Disable "normal" code-d, close VS, remove %appdata%/code-d, launch VS & enable code-d beta serve-d, enjoy. [...] Thanks your suggestion work for me. many thanks to you
[Issue 18693] std.math.rndtonl and core.math.rndtonl result in link errors
https://issues.dlang.org/show_bug.cgi?id=18693 --- Comment #1 from github-bugzi...@puremagic.com --- Commits pushed to master at https://github.com/dlang/phobos https://github.com/dlang/phobos/commit/b4f675fe150afaa577d6a41d6013ca33d932bd57 Work On Issue 18693 - Remove rndtonl from std.math https://github.com/dlang/phobos/commit/813327d51affb1af8cdd1c7651612e8778109f10 Merge pull request #6429 from JackStouffer/issue18693 Work On Issue 18693 - Remove rndtonl from std.math merged-on-behalf-of: Jack Stouffer--
Re: #include C headers in D code
On Tuesday, 10 April 2018 at 16:51:57 UTC, Atila Neves wrote: If you get to the point where you can #include , it will be doubly impressive! Not *if*, *when*. ;) Atila FYI people have been fighting with this for a long time: https://github.com/dlang/druntime/pull/1316
[Issue 18754] New: Type sequence instantiation missing from language specification
https://issues.dlang.org/show_bug.cgi?id=18754 Issue ID: 18754 Summary: Type sequence instantiation missing from language specification Product: D Version: D2 Hardware: All OS: All Status: NEW Severity: normal Priority: P1 Component: dlang.org Assignee: nob...@puremagic.com Reporter: snarwin+bugzi...@gmail.com Type sequence instantiation is a special declaration syntax, documented here: https://dlang.org/articles/ctarguments.html#type-seq-instantiation It should be documented in the language specification, most likely in the section about template sequence parameters [1] or in the section about declarations. [2] [1] https://dlang.org/spec/template.html#variadic-templates [2] https://dlang.org/spec/declaration.html --
Re: Range length property
On 4/10/18 4:08 PM, Jonathan M Davis wrote: On Tuesday, April 10, 2018 19:47:10 Nordlöw via Digitalmars-d-learn wrote: I'm thinking of my own container Hashmap having its range ByKeyValue requiring one extra word of memory to store the iteration count which, in turn, can be used to calculate the length of the remaining range. Is this motivated? That would depend entirely on what you're trying to do, but in general, if a range has length, then some algorithms will be more efficient, and some algorithms do require length. e.g. std.array.array is going to pre-allocate an array of the correct length and fill it in, vs. appending each element as it gets them from the range. Personally, I would store the length because typically a container range is short-lived. It also jives with the container itself which likely has O(1) length. -Steve
Re: d2sqlite3 db.run, where lies the bug?
On 04/10/2018 08:04 PM, Ralph Amissah wrote: The exact location of problem may be provided in the error statement "core.exception.UnicodeException@src/rt/util/utf.d(292): invalid UTF-8 sequence". [...] Mock problem string with test code follows (d2sqlite3 required): [... code ...] A more minimal test case, reduced from your code: module d2sqlite3_utf8.issue; import d2sqlite3; void main() { string[] info_tag = ["pass", "fault"]; auto db = Database(":memory:"); string _sql_statement = `SELECT '’’';`; db.run(_sql_statement); db.close; } From the exception's stack trace we see that `d2sqlite3.internal.util.byStatement(immutable(char)[]).ByStatement.findEnd` is the deepest non-Phobos function involved. So that's a good first spot to look for a bug. Let's check it out. https://github.com/biozic/d2sqlite3/blob/2e8211946ae0e09646d561aeae1361a695adcc17/source/d2sqlite3/internal/util.d#L64-L83 And indeed, there's a bug in these lines: auto tail = sql[pos .. $]; immutable offset = tail.countUntil(';') + 1; pos += offset; `pos` is used to slice the string `sql`. That means, `pos` is interpreted as a number of UTF-8 code *units*. But then the result of `countUntil` is added. `countUntil` counts code *points*. So a number of code points is mistaken as a number of code units. That means the next slicing can be incorrect and split up a multibyte sequence. And then `countUntil` will complain about broken UTF-8. This can be fixed by letting `countUntil` operate on count code units instead: import std.utf: byCodeUnit; immutable offset = tail.byCodeUnit.countUntil(';') + 1; If you want, you can make a bug report or a pull request with the fix. Otherwise, if you're not up to that, I can make one. [...] - DMD64 D Compiler v2.074.1 That's rather old. I'd recommend updating if possible.
Re: Range length property
On Tuesday, April 10, 2018 19:47:10 Nordlöw via Digitalmars-d-learn wrote: > On Tuesday, 10 April 2018 at 14:34:40 UTC, Adam D. Ruppe wrote: > > On Tuesday, 10 April 2018 at 14:25:52 UTC, Nordlöw wrote: > >> Should ranges always provide a length property? > > > > No. > > > >> If so, in which cases is a length property an advantage or a > >> requirement? > > > > Just provide it whenever it is cheap to do so. If you need to > > do complex calculations or especially loop over contents to > > figure out the length, do NOT provide it. > > > > But if it is as simple as returning some value, provide it and > > algorithms can take advantage of it for optimizations etc. as > > needed. > > I'm thinking of my own container Hashmap having its range > ByKeyValue requiring one extra word of memory to store the > iteration count which, in turn, can be used to calculate the > length of the remaining range. Is this motivated? That would depend entirely on what you're trying to do, but in general, if a range has length, then some algorithms will be more efficient, and some algorithms do require length. So, if you can provide length, then the range will be more useful, just like a bidirectional range can be more useful than a forward range or a random-access range can be more useful than either. However, if you're not doing anything that ever benefits from it having length, then it doesn't buy you anything. So, it ultimately depends on what you're doing. In a general purpose library, I'd say that it should have length if it can do so in O(1), but if it's just for you, then it may or may not be worth it. The other thing to consider is what happens when the container is mutated. I don't think that ranges necessarily behave all that well when an underlying container is mutated, but it is something that has to be considered when dealing with a range over a container. Even if mutating the underlying container doesn't necessarily invalidate a range, maintaining the length in the manner that you're suggesting probably makes it so that it would be invalidated in more cases, since if any elements are added or removed in the portion that was already popped off the range, then the iteration count couldn't be used to calculate the length in the same way anymore. Now, with a hash map, the range is probably fully invalidated when anything gets added or removed anyway, since that probably screws with the order of the elements in the range, but how the range is going to behave when the underlying container is mutated and how having the length property does or doesn't affect that is something that you'll need to consider. - Jonathan M Davis
Re: #include C headers in D code
On Tuesday, 10 April 2018 at 19:28:09 UTC, Steven Schveighoffer wrote: On 4/10/18 2:36 PM, Atila Neves wrote: Haha, I remember. I do plan on dealing with emplace_back, but I have no idea how just yet and I was hoping nobody was going to call me on it until then. Busted! :P I think we all agree you aren't going to instantiate C++ templates in D (and who would want to). Do we? Do I? :P (I've actually seriously considered it) But since you are using a wrapper to call the compiler, and invoking clang anyway, generating a file to compile which calls the template to generate the object file for the method, and then using the symbol generated to bind to the method might be possible. Of course, you first have to compile your D code to see what templates to generate! So this is another extra step. That's one of my ideas. It could be as easy as generating a mock C++ template for vector, that then has a symbol that d++ recognizes and both replaces with a real call AND helps you figure out what C++ template to generate. -vcg-ast may help here. The details elude me right now, but that seems to make sense. Whatever this is going to be, it ain't going to be fast... Compiling C++ isn't known to be fast. ;) It might be possible to limit the damage by confining the C++ #includes to one D package or module so it doesn't get rebuilt every time. Atila
Re: Range length property
On Tuesday, 10 April 2018 at 14:34:40 UTC, Adam D. Ruppe wrote: On Tuesday, 10 April 2018 at 14:25:52 UTC, Nordlöw wrote: Should ranges always provide a length property? No. If so, in which cases is a length property an advantage or a requirement? Just provide it whenever it is cheap to do so. If you need to do complex calculations or especially loop over contents to figure out the length, do NOT provide it. But if it is as simple as returning some value, provide it and algorithms can take advantage of it for optimizations etc. as needed. I'm thinking of my own container Hashmap having its range ByKeyValue requiring one extra word of memory to store the iteration count which, in turn, can be used to calculate the length of the remaining range. Is this motivated?
Re: Destructor call
On 4/10/18 3:24 PM, Jonathan M Davis wrote: On Tuesday, April 10, 2018 18:52:19 kinke via Digitalmars-d-learn wrote: On Tuesday, 10 April 2018 at 18:34:54 UTC, n0fun wrote: Why the destructor is called in the second case and why not in the first? The first case is RAII, where destruction isn't done for not fully constructed instances. Yeah, which is arguably a bug: https://issues.dlang.org/show_bug.cgi?id=14246 The second case is GC finalization at program shutdown and looks like a bug, as the GC should probably immediately reclaim the allocated heap memory if construction wasn't successful. Maybe it should reclaim the memory immediately, but I don't see how it could be argued to be a bug. When memory is freed by the GC is an implementation detail, and it's never guaranteed that a finalizer will actually ever run. Actually, it is a bug, because the destructor is going to run the finalizer on a collection cycle, and the object may be partially created. This is due to the way it's created using new: 1. a memory block is allocated 2. The typeinfo is stored in the block 3. The runtime returns the pointer to the block. 4. the compiler calls the constructor on the block. Because the typeinfo is unconditionally stored, the finalizer will run, even if it shouldn't. The issue is that the compiler is much better at calling the constructor of the struct. This means we need 2 hooks for the construction -- 1. the memory allocation, and 2. a "post construction" call. I'd hate to pass the constructor parameters to a template function rather than the compiler handle all of these messy details. -Steve
[Issue 18698] static foreach + __traits(allMembers, moduleName)
https://issues.dlang.org/show_bug.cgi?id=18698 --- Comment #16 from Manu--- I remember my work-around; I ran the foreach inside a static module constructor! >From there I generated my reflection information about the module and registered it at runtime (in the module constructor), rather than emit data directly into the module scope. In this instance, I really need to emit functions into the module scope, and not do runtime registration like I did last time. It would be really really nice to fix this issue! --
Re: #include C headers in D code
On 4/10/18 2:36 PM, Atila Neves wrote: Haha, I remember. I do plan on dealing with emplace_back, but I have no idea how just yet and I was hoping nobody was going to call me on it until then. Busted! :P I think we all agree you aren't going to instantiate C++ templates in D (and who would want to). But since you are using a wrapper to call the compiler, and invoking clang anyway, generating a file to compile which calls the template to generate the object file for the method, and then using the symbol generated to bind to the method might be possible. Of course, you first have to compile your D code to see what templates to generate! So this is another extra step. It could be as easy as generating a mock C++ template for vector, that then has a symbol that d++ recognizes and both replaces with a real call AND helps you figure out what C++ template to generate. -vcg-ast may help here. Whatever this is going to be, it ain't going to be fast... -Steve
Re: Destructor call
On Tuesday, April 10, 2018 18:52:19 kinke via Digitalmars-d-learn wrote: > On Tuesday, 10 April 2018 at 18:34:54 UTC, n0fun wrote: > > Why the destructor is called in the second case and why not in > > the first? > > The first case is RAII, where destruction isn't done for not > fully constructed instances. Yeah, which is arguably a bug: https://issues.dlang.org/show_bug.cgi?id=14246 > The second case is GC finalization at program shutdown and looks > like a bug, as the GC should probably immediately reclaim the > allocated heap memory if construction wasn't successful. Maybe it should reclaim the memory immediately, but I don't see how it could be argued to be a bug. When memory is freed by the GC is an implementation detail, and it's never guaranteed that a finalizer will actually ever run. - Jonathan M Davis
Re: Destructor call
On Tuesday, 10 April 2018 at 18:34:54 UTC, n0fun wrote: Why the destructor is called in the second case and why not in the first? The first case is RAII, where destruction isn't done for not fully constructed instances. The second case is GC finalization at program shutdown and looks like a bug, as the GC should probably immediately reclaim the allocated heap memory if construction wasn't successful.
[Issue 11997] rdmd should search its binary path for the compiler
https://issues.dlang.org/show_bug.cgi?id=11997 --- Comment #6 from github-bugzi...@puremagic.com --- Commit pushed to master at https://github.com/dlang/tools https://github.com/dlang/tools/commit/2e516ab51a5d1c0329312aa56960281c95e57a33 rdmd: Append binExt to the compiler path to check from the same directory Fixes using the compiler from rdmd's directory (issue 11997) on Windows. --
Re: #include C headers in D code
On Tuesday, 10 April 2018 at 18:01:37 UTC, Steven Schveighoffer wrote: On 4/10/18 12:51 PM, Atila Neves wrote: On Tuesday, 10 April 2018 at 13:53:34 UTC, Steven Schveighoffer wrote: If you get to the point where you can #include , it will be doubly impressive! Not *if*, *when*. ;) I hope you are right, but I remain skeptical :) If I may throw a curveball back at you, I recall a question at last year's dconf during the talk about interfacing with C++ STL about using emplace_back instead of push_back. And the questioner who happened to be sitting next to me said "meh, push_back isn't very useful, nobody uses push_back any more" :P -Steve Haha, I remember. I do plan on dealing with emplace_back, but I have no idea how just yet and I was hoping nobody was going to call me on it until then. Busted! :P Atila
Re: Migrating an existing more modern GC to D's gc.d
On 2018-04-10 08:47, Jonathan M Davis wrote: Regardless, I think that it's clear that in order to do anything with thread-local pools, we'd have to lock down the type system even further to disallow casts to or from shared or immutable, and that would really be a big problem given the inherent restrictions on those types and how shared is intended to be used. Apple's GC for Objective-C (before it had ARC) was using thread-local pools. I wonder how they manged to do that in a language that doesn't have a type system that differentiates between TLS and shared memory. -- /Jacob Carlborg
Destructor call
import std.stdio; struct S(alias n) { this(int) { throw new Exception("Exception"); } ~this() { writeln("destructor " ~ n); } } void main() { writeln("--- 1 ---"); try { auto s = S!"1"(0); } catch (Exception) {} writeln("--- 2 ---"); try { auto s = new S!"2"(0); } catch (Exception) {} } Output: --- 1 --- --- 2 --- destructor 2 Why the destructor is called in the second case and why not in the first? How to design structs with such different behavior?
Re: What are AST Macros?
On 2018-04-09 18:39, Cym13 wrote: On Monday, 9 April 2018 at 15:30:33 UTC, Stefan Koch wrote: On Friday, 6 April 2018 at 21:45:45 UTC, Zach Tollen wrote: I think Walter's reason was that such macros would hide too many idiosyncrasies in how they were programmed, such that a lot of code which seems simple on the surface will actually obfuscate complicated and arbitrary macro-programming patterns. Thus, code that uses them will become much less maintainable, because it is liable to do so many different and hidden things. Also, the tasks for which AST-macros would typically be used are already largely accommodated by templates and other features. Thus, the real need for them isn't that high. I think it's time to revisit this. The reason being that templates are only well suited to very specific types of meta-programs which have a low degree of parameterization and a low degree of abstraction. Using templates to introspect and manipulate types is like using a hammmer's flat back to remove a nail. It _can_ be done but with an absurd amount of work. You just have to remove all of the wall around the nail by pounding it until the wall has around the nail is disintegrated :) This is not an exaggeration. Templates used for introspection (or anything else really that's modestly complex) are equally hard to reason about for compilers and for programmers. I guess programmers have an advantage when it comes to _efficient_ pattern recognition. Wouldn't AST macros require either to standardize (and freeze) AST representation within the compiler or to maintain an equally frozen alternate representation to be exposed? Yes. It can have two separate ASTs, one internal for the compiler and one external that are used together with the AST macros. They would probably quite similar but they don't need to be exactly the same. I can't see how that wouldn't make the compiler's development slower since all of a sudden changing the internal representation would impact user code, especially given the low number of breaking changes that are accepted today. We already have three clients using the AST: LDC, GDC and the DMD Dub package. -- /Jacob Carlborg
Re: #include C headers in D code
On 4/10/18 12:51 PM, Atila Neves wrote: On Tuesday, 10 April 2018 at 13:53:34 UTC, Steven Schveighoffer wrote: If you get to the point where you can #include , it will be doubly impressive! Not *if*, *when*. ;) I hope you are right, but I remain skeptical :) If I may throw a curveball back at you, I recall a question at last year's dconf during the talk about interfacing with C++ STL about using emplace_back instead of push_back. And the questioner who happened to be sitting next to me said "meh, push_back isn't very useful, nobody uses push_back any more" :P -Steve
d2sqlite3 db.run, where lies the bug?
/+ Not sure where to report this, nor of where the bug lies. I hope SQLite (and d2sqlite3) is used widely enough for this to be of interest here. I have sets of document files that are broken up and placed (inserted) into an sqlite3 db, some of which fail with what is to me an inexplicable utf-8 error as they contain no special characters and it is "corrected" without the removal of any character in particular, and I so far, cannot predict them. Below I have concocted a sample string that fails and variations of it that pass (with one character removed or added). Note, (i) There is no problem inserting the string in question into sqlite3 directly (i.e. using sqlite3 directly). (ii) Likewise there is no problem using d2sqlite3 with a prepared statement on the string (.execute), but,... But for the use case, each document has several thousand content strings for each of which sqlite3 then requires a data locks and releases for the insertion of the next, thousands per document and this makes the operation conservatively several tens of time slower, than: generating a prepared sql statement inserting all document rows (objects/paragraphs) as a single sql statement with db.run begin and commit. Basically, it makes a significant difference that this works. (iii) There do not appear to be any offending utf-8 characters Assumption, most likely candidate for blame is the d2sqlite3 wrapper (or my code, (something that needs to be escaped in certain circumstances? please tell me)); sqlite3 does not have a problem with the string in question, and the C api for which d2sqlite3 provides a wrapper is much used and seems unlikely to be to blame. The exact location of problem may be provided in the error statement "core.exception.UnicodeException@src/rt/util/utf.d(292): invalid UTF-8 sequence". >From a laymans perspecive it would appear that db.run the passing of an sql statement as a string to sqlite3 should be the simplest type of transaction; pass a statement/string unchanged to sqlite3 Sample offending text used: "Contrary to Peter’s cake; all versions of Peter’s, custard. Eating without the cook’s permission is, of course, naughty. Now, a quick check of my menu shows that sure enough, a number of files have Peter’s recipe in them. John had better tell us if he ate Peter’s lunch. You didn’t eat Peter’s berries; funny.", The prepared sql statement that fails with d2sqlite3 (but succeeds using sqlite3 directly): BEGIN; DROP TABLE IF EXISTS test; CREATE TABLE test ( lid BIGINT PRIMARY KEY, txt TEXT NULL ); INSERT INTO test (txt) VALUES ('Contrary to Peter’s cake; all versions of Peter’s, custard. Eating without the cook’s permission is, of course, naughty. Now, a quick check of my menu shows that sure enough, a number of files have Peter’s recipe in them. John had better tell us if he ate Peter’s lunch. You didn’t eat Peter’s berries; funny.'); COMMIT; core.exception.UnicodeException@rt/util/utf.d(292): invalid UTF-8 sequence in the sample problem text/string/statement for d2sqlite3 (above): - utf-8 error goes away on removal of either: - one of the semi-colons (of which there are 2) - any of the closing single quote mark symbols ’ occurring between the two semi-colons (of which there are 6) - comments - placing a random semi-colon within the two offending semi-colons sometimes works - double semi-colon does not help Mock problem string with test code follows (d2sqlite3 required): +/ module d2sqlite3_utf8.issue; import std.conv : to; import std.format; import std.stdio; import d2sqlite3; void main() { string[] info_tag = ["pass", "fault"]; foreach (t, tests; [ok_check, faults]) { foreach (i, insert_test; tests) { // auto db = Database("test.sqlite"); auto db = Database(":memory:"); string _sql_statement = format(q"¶ BEGIN; DROP TABLE IF EXISTS test; CREATE TABLE test ( lid BIGINT PRIMARY KEY, txt TEXT NULL ); INSERT INTO test (txt) VALUES ('%s'); COMMIT; ¶", insert_test[0], ); writeln( (i + 1), ". ", info_tag[t], ": ", insert_test[1], "\n", _sql_statement); db.run(_sql_statement); foreach (parse; db.execute("SELECT txt FROM test;")) { foreach (s; parse) { writeln( " (test string == sqlite database content): ", (insert_test[0] == s.to!string), "\n"); assert(insert_test[0] == s.to!string); // writeln(s); } } assert(db.totalChanges == 1); db.close; } } } string[][] faults = [ [ "Contrary to Peter’s cake; all versions of Peter’s, custard. Eating without the cook’s permission is, of course, naughty. Now, a quick check of my menu shows that sure enough, a number of files have Peter’s recipe in them. John had better tell us if he ate
Re: Is std.variant.visit not @nogc?
On 4/10/18 12:59 PM, Paul Backus wrote: On Tuesday, 10 April 2018 at 12:34:07 UTC, aliak wrote: Awesome! this is a neat trick: union { AliasSeq!(T0, T1) values; } Is that usage documented somewhere, or is it somewhere in phobos maybe? Also, can Algebraic be fully replaced with this version then or is there some functionality that would stop it going through? It's called "type sequence instantiation", and it's documented in the "Compile-time Sequences" article [1] on dlang.org. I discovered it reading the source of the 'tagged_union' dub package [2]. It's not mentioned anywhere in the language spec, as far as I can tell. Ooh! that's really cool. I've put AliasSeq of types into a struct, but never considered putting it into a union. This has a lot of potential when you want to auto-generate unions. Nice trick! -Steve
Re: Range length property
On Tuesday, April 10, 2018 14:25:52 Nordlöw via Digitalmars-d-learn wrote: > Should ranges always provide a length property? > > If so, in which cases is a length property an advantage or a > requirement? Whether a range has a length property or not is primarily dependent on how efficient it is to implement length. https://dlang.org/phobos/std_container.html lists the Big-O complexity of the various functions and properties that are expected for containers, and in the case of length, that also applies to ranges. It lists O(log n) as the Big-O complexity of length, so length should only be implemented if its Big-O complexity is no worse than O(log n). In most cases, that means implementing it only if it's O(1) (I think that it's O(log n) rather than O(1) because of binary trees), and length should certainly never be implemented if it's O(n). Basically, if you can just return the length without calculating it, then it makes sense to implement it, but if you have to calculate it, then in most cases, it shouldn't be there. Range-based functions are going to expect length to be very cheap to call if it is present, and any function that needs to ascertain the length of a range even if it doesn't have length will call walkLength (which returns length if present and iterates the entire range to count it if it's not). As iterating the entire range to count it, is O(n), most algorithms won't do that are more likely to require length if they need to know how many elements there are in the range, but that depends on what they're doing. A function that requires a length property or which has a path optimized for ranges that have a length property checks for that with std.range.primitives.hasLength. Random access ranges are required to either be infinite or provide length, but for other range types, it's optional and must be checked for if an algorithm is going to use it. And actually, a large percentage of ranges are lazy, in which case, it's pretty rare that they can have a length property, because you usually have no way of knowing how long they're going to be without actually iterating through the range. So, while it's not uncommon for a range to define length, it's very common that they don't. - Jonathan M Davis
Re: code-d 0.17.0 + serve-d 0.1.2
Am 10.04.2018 um 14:27 schrieb WebFreak001: > On Monday, 9 April 2018 at 21:45:57 UTC, Johannes Loher wrote: >> Am 04.04.2018 um 20:34 schrieb greatsam4sure: >>> [...] >> I just tried to get this to work, too, but I was not able to get it to >> work correctly. It seems that running dub fails somehow: >> >> [...] > > hm before it would have completely crashed workspace-d/serve-d to a > point where nothing would work, now you basically only get stdlib and a > guess of further import paths. Can you make a minimal test case where > this happens? It is probably due to some dub.json settings. But as I use > dub as a library it should work the same as just calling `dub build` You are right, it indeed seems to be a dub problem. Running `dub build` gives me "Could not resolv configuration for package vibe-d". The strange thing is, it workls correctly on Linux / OS X with the same dub/dmd versions... I tried it with another project with a more simple dub.json and it works fine out of the box. Very nice job!
[Issue 18737] An assert(0) should be a leaf in constructor flow analysis
https://issues.dlang.org/show_bug.cgi?id=18737 github-bugzi...@puremagic.com changed: What|Removed |Added Status|NEW |RESOLVED Resolution|--- |FIXED --
[Issue 18737] An assert(0) should be a leaf in constructor flow analysis
https://issues.dlang.org/show_bug.cgi?id=18737 --- Comment #2 from github-bugzi...@puremagic.com --- Commits pushed to master at https://github.com/dlang/dmd https://github.com/dlang/dmd/commit/88f48d698e19da62c0246e7f74e60477a4804ee6 fix Issue 18737 - An assert(0) should be a leaf in constructor flow analysis https://github.com/dlang/dmd/commit/e84c0a07e61a6317c4de74fe072c7387fa411e1a Merge pull request #8144 from WalterBright/fix18737 fix Issue 18737 - An assert(0) should be a leaf in constructor flow a… merged-on-behalf-of: Razvan Nitu--
Re: Is std.variant.visit not @nogc?
On Tuesday, 10 April 2018 at 12:34:07 UTC, aliak wrote: Awesome! this is a neat trick: union { AliasSeq!(T0, T1) values; } Is that usage documented somewhere, or is it somewhere in phobos maybe? Also, can Algebraic be fully replaced with this version then or is there some functionality that would stop it going through? It's called "type sequence instantiation", and it's documented in the "Compile-time Sequences" article [1] on dlang.org. I discovered it reading the source of the 'tagged_union' dub package [2]. It's not mentioned anywhere in the language spec, as far as I can tell. SumType should be capable of doing anything that Algebraic can do (if it's not, please open an issue on Github!), but it's not a drop-in replacement, and it's still a work in progress. Documentation for the current version (more or less) is available at http://sumtype.dpldocs.info/index.html. If there are any particular features you'd like to see, let me know, and I'll do my best to add them. [1] https://dlang.org/articles/ctarguments.html#type-seq-instantiation [2] https://github.com/Superstar64/tagged_union/blob/master/source/tagged_union.d
Re: #include C headers in D code
On Tuesday, 10 April 2018 at 13:53:34 UTC, Steven Schveighoffer wrote: On 4/9/18 7:03 AM, Atila Neves wrote: [...] Awesome. Can't say I will use it, as I don't use C much, but I understand how difficult a task this is. Thanks! If you get to the point where you can #include , it will be doubly impressive! Not *if*, *when*. ;) Atila
[Issue 17991] ICE with imports without module
https://issues.dlang.org/show_bug.cgi?id=17991 --- Comment #3 from github-bugzi...@puremagic.com --- Commits pushed to master at https://github.com/dlang/dmd https://github.com/dlang/dmd/commit/bed9bf405d1e743e8a594185cd9f40f1b2db92ad Fix Issue 17991 - ICE with imports without module https://github.com/dlang/dmd/commit/9398ee965054f327d85e2229d679ac09d1272f00 Merge pull request #8126 from wilzbach/fix-17991 Fix Issue 17991 - ICE with imports without module merged-on-behalf-of: Razvan Nitu--
[Issue 18753] chunkBy compile error causes ICE
https://issues.dlang.org/show_bug.cgi?id=18753 hst...@quickfur.ath.cx changed: What|Removed |Added Keywords||ice --
[Issue 18753] chunkBy compile error causes ICE
https://issues.dlang.org/show_bug.cgi?id=18753 hst...@quickfur.ath.cx changed: What|Removed |Added See Also||https://issues.dlang.org/sh ||ow_bug.cgi?id=14909 --
[Issue 14909] Template argument of std.algoirthm.iteration.chunkBy cannot access a local variable
https://issues.dlang.org/show_bug.cgi?id=14909 hst...@quickfur.ath.cx changed: What|Removed |Added See Also||https://issues.dlang.org/sh ||ow_bug.cgi?id=18753 --
[Issue 18753] chunkBy compile error causes ICE
https://issues.dlang.org/show_bug.cgi?id=18753 hst...@quickfur.ath.cx changed: What|Removed |Added See Also||https://issues.dlang.org/sh ||ow_bug.cgi?id=18751 --
[Issue 18753] New: chunkBy compile error causes ICE
https://issues.dlang.org/show_bug.cgi?id=18753 Issue ID: 18753 Summary: chunkBy compile error causes ICE Product: D Version: D2 Hardware: x86_64 OS: Linux Status: NEW Severity: critical Priority: P1 Component: dmd Assignee: nob...@puremagic.com Reporter: hst...@quickfur.ath.cx Code: -- unittest { import std.algorithm.iteration : chunkBy; auto n = 3; auto s = [1,2,3].chunkBy!(a => a+n); } -- Compiler output: -- /usr/src/d/phobos/std/algorithm/iteration.d(1774): Error: function test.__unittest_L1_C1.ChunkByImpl!(__lambda1, int[]).ChunkByImpl.__lambda11 cannot access frame of function test.__unittest_L1_C1 /usr/src/d/phobos/std/algorithm/iteration.d(1774): Error: function test.__unittest_L1_C1.ChunkByImpl!(__lambda1, int[]).ChunkByImpl.__lambda11 cannot access frame of function test.__unittest_L1_C1 /usr/src/d/phobos/std/algorithm/iteration.d(1801):instantiated from here: ChunkByGroupImpl!(__lambda11, int[], Impl) /usr/src/d/phobos/std/algorithm/iteration.d(1945):instantiated from here: ChunkByImpl!(__lambda1, int[]) test.d(5):instantiated from here: chunkBy!((a) => a + n, int[]) /usr/src/d/phobos/std/range/primitives.d(884): Error: template instance `std.range.primitives.isInputRange!(ChunkByGroupImpl!(__lambda11, int[], Impl))` error instantiating /usr/src/d/phobos/std/algorithm/iteration.d(1762):instantiated from here: isForwardRange!(ChunkByGroupImpl!(__lambda11, int[], Impl)) core.exception.AssertError@dmd/declaration.d(686): Assertion failure dmd() [0x539e57] dmd(dmd.declaration.AliasDeclaration dmd.declaration.AliasDeclaration.__ctor(dmd.globals.Loc, dmd.identifier.Identifier, dmd.mtype.Type)+0x4c) [0x53766c] dmd(_ZN25ExpressionSemanticVisitor5visitEP5IsExp+0xc39) [0x5b6c39] dmd(_ZN5IsExp6acceptEP7Visitor+0x1d) [0x5a5dc5] dmd(_Z18expressionSemanticP10ExpressionP5Scope+0x43) [0x5c44e3] dmd(bool dmd.staticcond.evalStaticCondition(dmd.dscope.Scope*, dmd.expression.Expression, dmd.expression.Expression, ref bool)+0x150) [0x64c6e8] dmd(_ZN17StaticIfCondition7includeEP5Scope+0xc5) [0x5190fd] dmd(_ZN22ConditionalDeclaration7includeEP5Scope+0x45) [0x5111b5] dmd(_ZN19StaticIfDeclaration7includeEP5Scope+0x56) [0x5113de] dmd(_ZN22DsymbolSemanticVisitor14attribSemanticEP17AttribDeclaration+0x33) [0x57bd13] dmd(_ZN22DsymbolSemanticVisitor5visitEP19StaticIfDeclaration+0xd) [0x57cab5] dmd(_ZN19StaticIfDeclaration6acceptEP7Visitor+0x1d) [0x511515] dmd(_Z15dsymbolSemanticP7DsymbolP5Scope+0x3d) [0x57860d] dmd(_ZN16TemplateInstance13expandMembersEP5Scope+0xdd) [0x5973bd] dmd(_ZN16TemplateInstance16tryExpandMembersEP5Scope+0x5c) [0x59742c] dmd(void dmd.dsymbolsem.templateInstanceSemantic(dmd.dtemplate.TemplateInstance, dmd.dscope.Scope*, dmd.root.array.Array!(dmd.expression.Expression).Array*)+0x8cd) [0x5867fd] dmd(_ZN22DsymbolSemanticVisitor5visitEP16TemplateInstance+0x16) [0x57e6ce] dmd(_ZN16TemplateInstance6acceptEP7Visitor+0x1d) [0x5974cd] dmd(_Z15dsymbolSemanticP7DsymbolP5Scope+0x3d) [0x57860d] dmd(_ZN14ResolveVisitor5visitEP12TypeInstance+0x45) [0x62cf15] dmd(_ZN12TypeInstance6acceptEP7Visitor+0x1d) [0x60014d] dmd(_Z7resolveP4TypeRK3LocP5ScopePP10ExpressionPS0_PP7Dsymbolb+0x56) [0x62c596] dmd(_ZN19TypeSemanticVisitor5visitEP12TypeInstance+0x51) [0x62acc1] dmd(_ZN12TypeInstance6acceptEP7Visitor+0x1d) [0x60014d] dmd(_Z12typeSemanticP4Type3LocP5Scope+0x4f) [0x62804f] dmd(_ZN4Type11trySemanticERK3LocP5Scope+0x3c) [0x5f79bc] dmd(_ZN25ExpressionSemanticVisitor5visitEP5IsExp+0xad) [0x5b60ad] dmd(_ZN5IsExp6acceptEP7Visitor+0x1d) [0x5a5dc5] dmd(_Z18expressionSemanticP10ExpressionP5Scope+0x43) [0x5c44e3] dmd(_ZN25ExpressionSemanticVisitor5visitEP10LogicalExp+0x155) [0x5c28dd] dmd(_ZN10LogicalExp6acceptEP7Visitor+0x1d) [0x5a9985] dmd(_Z18expressionSemanticP10ExpressionP5Scope+0x43) [0x5c44e3] dmd(_ZN22DsymbolSemanticVisitor5visitEP14VarDeclaration+0x2157) [0x57ae37] dmd(_ZN14VarDeclaration6acceptEP7Visitor+0x1d) [0x539135] dmd(_Z15dsymbolSemanticP7DsymbolP5Scope+0x3d) [0x57860d] dmd(_ZN16TemplateInstance13expandMembersEP5Scope+0xdd) [0x5973bd] dmd(_ZN16TemplateInstance16tryExpandMembersEP5Scope+0x5c) [0x59742c] dmd(void dmd.dsymbolsem.templateInstanceSemantic(dmd.dtemplate.TemplateInstance, dmd.dscope.Scope*, dmd.root.array.Array!(dmd.expression.Expression).Array*)+0x8cd) [0x5867fd] dmd(_ZN22DsymbolSemanticVisitor5visitEP16TemplateInstance+0x16) [0x57e6ce] dmd(_ZN16TemplateInstance6acceptEP7Visitor+0x1d) [0x5974cd] dmd(_Z15dsymbolSemanticP7DsymbolP5Scope+0x3d) [0x57860d] dmd(_ZN25ExpressionSemanticVisitor5visitEP8ScopeExp+0x3c6) [0x5b0136] dmd(_ZN8ScopeExp6acceptEP7Visitor+0x1d) [0x5a44e5] dmd(_Z18expressionSemanticP10ExpressionP5Scope+0x43) [0x5c44e3] dmd(bool dmd.staticcond.evalStaticCondition(dmd.dscope.Scope*, dmd.expression.Expression, dmd.expression.Expression, ref bool)+0x150) [0x64c6e8]
[Issue 18751] chunkBy predicate cannot access local variable
https://issues.dlang.org/show_bug.cgi?id=18751 hst...@quickfur.ath.cx changed: What|Removed |Added See Also||https://issues.dlang.org/sh ||ow_bug.cgi?id=18753 --
Re: stirling numbers and multidimensional arrays
On Sunday, 8 April 2018 at 16:51:14 UTC, ag0aep6g wrote: On 04/08/2018 06:15 PM, popgen wrote: [...] [...] [...] [...] [...] Should it be `q <= k` here? You're using q as an index into an array of length k + 1. If you go up to i, you'll exceed that and go out of bounds. That you're seeing a segfault instead of a range error indicates that you're compiling with -release. Better not do that when debugging. Thank you for your help! And I learned two things, the error in the code and not to use -release while debugging.
[Issue 18742] std.regex: Using CodePointSet in AAs breaks if reference count changes
https://issues.dlang.org/show_bug.cgi?id=18742 Jack Stoufferchanged: What|Removed |Added Blocks||17206 Referenced Issues: https://issues.dlang.org/show_bug.cgi?id=17206 [Issue 17206] [Tracking] Check that opEquals and toHash are both defined or neither are defined --
[Issue 17206] [Tracking] Check that opEquals and toHash are both defined or neither are defined
https://issues.dlang.org/show_bug.cgi?id=17206 Jack Stoufferchanged: What|Removed |Added Depends on||18742 Referenced Issues: https://issues.dlang.org/show_bug.cgi?id=18742 [Issue 18742] std.regex: Using CodePointSet in AAs breaks if reference count changes --
trouble building dlang.org
I'm trying to update the language spec. I have the standard dmd installed on my Mac in `~/dlang/dmd` using the install script from the website "curl -fsS https://dlang.org/install.sh | bash -s dmd". Okay, good, done. Now, according to: dlang.org/CONTRIBUTING.md: "git clone https://github.com/dlang/dlang.org cd dlang.org" Okay, done. Now: "make -f posix.mak html" This first errored out with "No package file found in /Users/zach/dlang/dmd/, expected one of dub.json/dub.sdl/package.json make: *** [.generated/ddoc_preprocessor] Error 2" I didn't know why the dub.sdl wasn't already installed, so I manually copied it from github. But now the error for "make -f posix.mak html" is: ".generated/stable_dmd-2.078.2/dmd2/osx/bin/dub build --compiler=.generated/stable_dmd-2.078.2/dmd2/osx/bin/dmd --root=ddoc && \ mv ddoc/ddoc_preprocessor .generated/ddoc_preprocessor Invalid source/import path: /Users/zach/dlang/dmd/src/dmd Invalid source/import path: /Users/zach/dlang/dmd/generated/dub" So I'm here wondering wuzzup? The basic instructions in CONTRIBUTING.md aren't working. Anyone?
Re: DUB: Only fetch and cache packages in dub.json without running build
On Tuesday, 10 April 2018 at 13:50:38 UTC, Clinton wrote: Hi all, I'm setting up a CircleCI config for my project. Right now I'm trying to cache dependencies before running builds. This way I can run "dub build --nodeps" immediately after the packages are cached to avoid extra network calls and speed it up. I'm wondering if there's a way to isolate the part that downloads and caches all of the dependencies in dub.json without running the build. Right now I have to run the build twice. First one, for the sake of downloading the dependencies and later for running if the cache exists. Having the build run the first time takes up a lot of time. I'm going for the "npm install" type of effect. The reason the cache needs to be rebuilt each time is because CircleCI runs docker images. Once the deployment is finished, the image fs is destroyed so there's no way to hold onto the cache for future builds. As far as I understand it, `dub describe` fetches everything. Then you can cache `~/.dub/packages/`. Alternatively you can do `dub describe --cache=local` to put the packages in the current directory. You could then use `dub add-path .` or add `--cache=local` to all future calls to use those locally fetched packages. Even better: % mkdir cache % cd cache % dub describe --root=../ --cache=local and then either % dub build --root=../ --cache=local or % dub add-path . % cd ../ % dub build which keeps things nice and clean
Re: DUB: Only fetch and cache packages in dub.json without running build
On Tuesday, 10 April 2018 at 15:31:41 UTC, John Colvin wrote: On Tuesday, 10 April 2018 at 13:50:38 UTC, Clinton wrote: Hi all, I'm setting up a CircleCI config for my project. Right now I'm trying to cache dependencies before running builds. This way I can run "dub build --nodeps" immediately after the packages are cached to avoid extra network calls and speed it up. I'm wondering if there's a way to isolate the part that downloads and caches all of the dependencies in dub.json without running the build. Right now I have to run the build twice. First one, for the sake of downloading the dependencies and later for running if the cache exists. Having the build run the first time takes up a lot of time. I'm going for the "npm install" type of effect. The reason the cache needs to be rebuilt each time is because CircleCI runs docker images. Once the deployment is finished, the image fs is destroyed so there's no way to hold onto the cache for future builds. As far as I understand it, `dub describe` fetches everything. Then you can cache `~/.dub/packages/`. Alternatively you can do `dub describe --cache=local` to put the packages in the current directory. You could then use `dub add-path .` or add `--cache=local` to all future calls to use those locally fetched packages. Even better: % mkdir cache % cd cache % dub describe --root=../ --cache=local and then either % dub build --root=../ --cache=local or % dub add-path . % cd ../ % dub build which keeps things nice and clean As per Sönke's advice, you can replace `dub describe` with `dub upgrade --missing-only` to avoid generating the description.
Re: DUB: Only fetch and cache packages in dub.json without running build
Am 10.04.2018 um 15:50 schrieb Clinton: Hi all, I'm setting up a CircleCI config for my project. Right now I'm trying to cache dependencies before running builds. This way I can run "dub build --nodeps" immediately after the packages are cached to avoid extra network calls and speed it up. I'm wondering if there's a way to isolate the part that downloads and caches all of the dependencies in dub.json without running the build. Right now I have to run the build twice. First one, for the sake of downloading the dependencies and later for running if the cache exists. Having the build run the first time takes up a lot of time. I'm going for the "npm install" type of effect. The reason the cache needs to be rebuilt each time is because CircleCI runs docker images. Once the deployment is finished, the image fs is destroyed so there's no way to hold onto the cache for future builds. "dub upgrade --missing-only" should have the desired effect. It downloads everything and also resolved any possible missing version selections.
Re: Homebrew dmd betas
On 4/10/18 1:46 AM, John Colvin wrote: On Saturday, 7 April 2018 at 18:39:12 UTC, Martin Nowak wrote: First beta for the 2.079.1 patch release. Comes with a handful of fixes. http://dlang.org/download.html#dmd_beta http://dlang.org/changelog/2.079.1.html Please report any bugs at https://issues.dlang.org - -Martin Available now on homebrew :) [snip] I haven't tried the betas yet, but many thanks for keeping homebrew up to date with the regular releases!
Re: SMTP Mail
On Tuesday, 10 April 2018 at 15:10:44 UTC, Vino wrote: The variable "to" is of type string[] but we need it as Array!string The variable "Subject" but we need it as Array!string. You'll have to convert them yourself if that is a must, but why would you need that?
Re: SMTP Mail
On Tuesday, 10 April 2018 at 13:51:02 UTC, Adam D. Ruppe wrote: On Tuesday, 10 April 2018 at 11:09:56 UTC, Vino wrote: Now the program works, but the attachment does not work as expected, message.addAttachment("text/plain", "C:\\Temp\\Test\Test1.txt", "Test"); What did you expect that "Test" argument to do if it was going to read the file as the content? I guess I should change the documents on this. The way it works is the filename argument is just what is seen in the email as a suggestion name for the user to download the attachment, and the content argument is what is what's inside that attachment. Since the attachment name just suggests a name, and the user decides where to put it, it should NOT have a path name. So try this instead: addAttachment("text/plain", "Test1.txt", std.file.read("C:\Temp\Test\Test1.txt")); so the name argument is JUST the name to suggest to the user, then the content argument gives the content of your file to attach - which here is read from the file on disk via the phobos std.file read function. Hi Adam, Thank you very much, the program now works, but i need to make some adjustment, if possible can you please help me on this. The variable "to" is of type string[] but we need it as Array!string The variable "Subject" but we need it as Array!string. From, Vino.B
Re: DUB: Only fetch and cache packages in dub.json without running build
On Tuesday, 10 April 2018 at 13:50:38 UTC, Clinton wrote: Hi all, I'm setting up a CircleCI config for my project. Right now I'm trying to cache dependencies before running builds. This way I can run "dub build --nodeps" immediately after the packages are cached to avoid extra network calls and speed it up. [...] If I remember correctly I used dub upgrade exactly for this purpose. Kind regards Andre
Re: Range length property
On Tuesday, 10 April 2018 at 14:25:52 UTC, Nordlöw wrote: Should ranges always provide a length property? No. If so, in which cases is a length property an advantage or a requirement? Just provide it whenever it is cheap to do so. If you need to do complex calculations or especially loop over contents to figure out the length, do NOT provide it. But if it is as simple as returning some value, provide it and algorithms can take advantage of it for optimizations etc. as needed.
Range length property
Should ranges always provide a length property? If so, in which cases is a length property an advantage or a requirement?
Re: DUB: Only fetch and cache packages in dub.json without running build
On Tuesday, 10 April 2018 at 13:50:38 UTC, Clinton wrote: Hi all, I'm setting up a CircleCI config for my project. Right now I'm trying to cache dependencies before running builds. This way I can run "dub build --nodeps" immediately after the packages are cached to avoid extra network calls and speed it up. [...] Thanks. That's a good idea. It would be great to have "dub fetch --all" or something like that to fetch all packages from the project dub.json.
Re: Thoughts on Herb Sutter's Metaclasses?
On Tuesday, 10 April 2018 at 09:32:49 UTC, Chris Katko wrote: Wow, that thread had very little discussion, and a huge amount of bickering over whether someone actually understood what someone else might have said. My take-away was that it can be done in D, but would be simpler with AST macros and Walter is against AST macros.
Re: code-d 0.17.0 + serve-d 0.1.2
On Tuesday, 10 April 2018 at 13:11:16 UTC, evilrat wrote: On Tuesday, 10 April 2018 at 11:54:47 UTC, WebFreak001 wrote: fyi "deprecated" code-d beta and normal code-d is exactly the same plugin right now using exactly the same serve-d versions, except for the deprecation message. I wouldn't be complaining if it's not the case. With normal code-d it does remove everything in %appdata%/code-d on start, re-setting config paths(even though for exapmle dub is in PATH), downloading git repo, fails to build, and repeat, while with beta there is no such issues. I would also suggest you to add explicit --compiler=dmd switch to build invocation since for example in my case dmd was in PATH env after ldc and so ldc used by default, which of course doesn't have x86_mscoff arch. I also think it is probably better to add --build=release too, since users usually don't do debug on that binaries. No dmd has an optimization issue that it removes code making the program completely broken and freeze on IO if compiled with -O, which is implied by --build=release. I will never use build=release with dmd. What about workspaces? Let for exapmle have main project (really just a dub project with single app.d for testing library) and library project in one workspace. I don't get any autocompletion from both projects. It also doesn't seems to work with dependency that has path property set, at least not when it's relative. Is this ok? Everything dub dependency related should work, I literally use dub as a library for this. Multi workspaces in vscode aren't implemented yet though.
Re: How to destruct class instances allocated by a Region-allocator over a single GC block
On 11/04/2018 1:56 AM, Eduard Staniloiu wrote: On Monday, 9 April 2018 at 14:51:24 UTC, Per Nordlöw wrote: On Monday, 9 April 2018 at 13:51:47 UTC, Steven Schveighoffer wrote: Well, you know the type, because make returned it no? The contract is, you call obj = make!X(args), then you have to call dispose(obj), where obj is of the type X. That's how it knows. If you are thinking you want to destroy the whole block at once (typed as void[]), that's not how it works. stdx.allocator is not going to help you with GC collection, it's not geared towards that purpose. Ok, thanks! If you are using a custom allocator to allocate memory then you also have to manually dispose of the memory when it is no longer needed. You can't have a custom allocator to supply you with the memory and then have the GC track and dispose of it. I get the feeling that this is what you were looking for? As long as you can use libc's free, sure you can :)
Re: How to destruct class instances allocated by a Region-allocator over a single GC block
On Monday, 9 April 2018 at 14:51:24 UTC, Per Nordlöw wrote: On Monday, 9 April 2018 at 13:51:47 UTC, Steven Schveighoffer wrote: Well, you know the type, because make returned it no? The contract is, you call obj = make!X(args), then you have to call dispose(obj), where obj is of the type X. That's how it knows. If you are thinking you want to destroy the whole block at once (typed as void[]), that's not how it works. stdx.allocator is not going to help you with GC collection, it's not geared towards that purpose. Ok, thanks! If you are using a custom allocator to allocate memory then you also have to manually dispose of the memory when it is no longer needed. You can't have a custom allocator to supply you with the memory and then have the GC track and dispose of it. I get the feeling that this is what you were looking for?
Re: DUB: Only fetch and cache packages in dub.json without running build
On 11/04/2018 1:50 AM, Clinton wrote: Hi all, I'm setting up a CircleCI config for my project. Right now I'm trying to cache dependencies before running builds. This way I can run "dub build --nodeps" immediately after the packages are cached to avoid extra network calls and speed it up. I'm wondering if there's a way to isolate the part that downloads and caches all of the dependencies in dub.json without running the build. Right now I have to run the build twice. First one, for the sake of downloading the dependencies and later for running if the cache exists. Having the build run the first time takes up a lot of time. I'm going for the "npm install" type of effect. The reason the cache needs to be rebuilt each time is because CircleCI runs docker images. Once the deployment is finished, the image fs is destroyed so there's no way to hold onto the cache for future builds. You should be able to do this by using ``dub describe`` and ``dub fetch`` with a simple script. But a reasonable feature request to make it default for fetch command.
Re: #include C headers in D code
On 4/9/18 7:03 AM, Atila Neves wrote: Here's my blog post about my project that allows directly #including C headers in D* https://atilanevesoncode.wordpress.com/2018/04/09/include-c-headers-in-d-code/ The summary is that, modulo bugs, things like this work: #include void main() { printf("Hello world\n".ptr); } So far it's successfully compiled whilst #including pthread, libcurl, openssl and others. The blog and the github README have more information, and feel free to reply to this with questions. dub: http://code.dlang.org/packages/dpp reddit: https://www.reddit.com/r/programming/comments/8axj53/include_c_headers_in_d_code/ hacker news: It's in there somewhere, search around. Atila * Technically, "D + #include directives + C macros" Awesome. Can't say I will use it, as I don't use C much, but I understand how difficult a task this is. If you get to the point where you can #include , it will be doubly impressive! -Steve
Re: SMTP Mail
On Tuesday, 10 April 2018 at 11:09:56 UTC, Vino wrote: Now the program works, but the attachment does not work as expected, message.addAttachment("text/plain", "C:\\Temp\\Test\Test1.txt", "Test"); What did you expect that "Test" argument to do if it was going to read the file as the content? I guess I should change the documents on this. The way it works is the filename argument is just what is seen in the email as a suggestion name for the user to download the attachment, and the content argument is what is what's inside that attachment. Since the attachment name just suggests a name, and the user decides where to put it, it should NOT have a path name. So try this instead: addAttachment("text/plain", "Test1.txt", std.file.read("C:\Temp\Test\Test1.txt")); so the name argument is JUST the name to suggest to the user, then the content argument gives the content of your file to attach - which here is read from the file on disk via the phobos std.file read function.
DUB: Only fetch and cache packages in dub.json without running build
Hi all, I'm setting up a CircleCI config for my project. Right now I'm trying to cache dependencies before running builds. This way I can run "dub build --nodeps" immediately after the packages are cached to avoid extra network calls and speed it up. I'm wondering if there's a way to isolate the part that downloads and caches all of the dependencies in dub.json without running the build. Right now I have to run the build twice. First one, for the sake of downloading the dependencies and later for running if the cache exists. Having the build run the first time takes up a lot of time. I'm going for the "npm install" type of effect. The reason the cache needs to be rebuilt each time is because CircleCI runs docker images. Once the deployment is finished, the image fs is destroyed so there's no way to hold onto the cache for future builds.
[Issue 18584] Undefined identifier when not specifying 'this'
https://issues.dlang.org/show_bug.cgi?id=18584 RazvanNchanged: What|Removed |Added CC||razvan.nitu1...@gmail.com --- Comment #2 from RazvanN --- Alternate attempted fix : https://github.com/dlang/dmd/pull/8159 --
Re: code-d 0.17.0 + serve-d 0.1.2
On Tuesday, 10 April 2018 at 11:54:47 UTC, WebFreak001 wrote: fyi "deprecated" code-d beta and normal code-d is exactly the same plugin right now using exactly the same serve-d versions, except for the deprecation message. I wouldn't be complaining if it's not the case. With normal code-d it does remove everything in %appdata%/code-d on start, re-setting config paths(even though for exapmle dub is in PATH), downloading git repo, fails to build, and repeat, while with beta there is no such issues. I would also suggest you to add explicit --compiler=dmd switch to build invocation since for example in my case dmd was in PATH env after ldc and so ldc used by default, which of course doesn't have x86_mscoff arch. I also think it is probably better to add --build=release too, since users usually don't do debug on that binaries. What about workspaces? Let for exapmle have main project (really just a dub project with single app.d for testing library) and library project in one workspace. I don't get any autocompletion from both projects. It also doesn't seems to work with dependency that has path property set, at least not when it's relative. Is this ok?
Re: Thoughts on Herb Sutter's Metaclasses?
On Tuesday, 10 April 2018 at 09:32:49 UTC, Chris Katko wrote: On Tuesday, 10 April 2018 at 05:55:06 UTC, Joakim wrote: On Tuesday, 10 April 2018 at 01:21:07 UTC, Chris Katko wrote: [...] See previous forum thread on the topic, with Walter chiming in a bit too: https://forum.dlang.org/thread/kglnxqbcugerhynng...@forum.dlang.org Wow, that thread had very little discussion, and a huge amount of bickering over whether someone actually understood what someone else might have said. ...I'm sorry?
[Issue 18734] bitnum parameter of core.bitop.bt should be signed
https://issues.dlang.org/show_bug.cgi?id=18734 --- Comment #2 from ag0aep6g--- (In reply to uplink.coder from comment #1) > DMD does not recognize bodies only function signatures. > So change it all you like :) it's only going to be used on systems where the > intrinsic can't work. core.bitop.bt is not an intrinsic. The expression in the body is recognized by the optimizer. --
Re: Space before parens in all function definitions
On 04/09/2018 02:50 PM, Seb wrote: On Monday, 9 April 2018 at 16:22:15 UTC, Andrei Alexandrescu wrote: On 04/07/2018 07:01 AM, Sönke Ludwig wrote: Am 07.04.2018 um 04:23 schrieb Andrei Alexandrescu: Why is there a space before "(" in our /library/ docs? https://dlang.org/library/std/stdio/file.tmpfile.html The paren here has role similar to that in mathematics, not literary. Thanks, Andrei Has been a regression during the diet-ng transition. Fix in DDOX: https://github.com/rejectedsoftware/ddox/pull/203 Thanks! When will that be live? Should happen soon -> https://github.com/dlang/dlang.org/pull/2335 Thanks folks!
Re: Is std.variant.visit not @nogc?
On Tuesday, 10 April 2018 at 03:48:25 UTC, Paul Backus wrote: Nope! It's just a tagged union, almost exactly the same as what you'd write by hand in C. You can take a look at the source yourself, if you're curious---it's actually pretty simple: https://github.com/pbackus/sumtype/blob/master/src/sumtype.d#L27 Awesome! this is a neat trick: union { AliasSeq!(T0, T1) values; } Is that usage documented somewhere, or is it somewhere in phobos maybe? Also, can Algebraic be fully replaced with this version then or is there some functionality that would stop it going through?
Re: code-d 0.17.0 + serve-d 0.1.2
On Monday, 9 April 2018 at 21:45:57 UTC, Johannes Loher wrote: Am 04.04.2018 um 20:34 schrieb greatsam4sure: [...] I just tried to get this to work, too, but I was not able to get it to work correctly. It seems that running dub fails somehow: [...] hm before it would have completely crashed workspace-d/serve-d to a point where nothing would work, now you basically only get stdlib and a guess of further import paths. Can you make a minimal test case where this happens? It is probably due to some dub.json settings. But as I use dub as a library it should work the same as just calling `dub build`
Re: Migrating an existing more modern GC to D's gc.d
On 4/10/18 4:37 AM, David Bennett wrote: On Tuesday, 10 April 2018 at 08:10:32 UTC, Jonathan M Davis wrote: Yes. They expect it to work, and as the language is currently designed, it works perfectly well. In fact, it's even built into the language. e.g. int[] foo() pure { return [1, 2, 3, 4]; } void main() { immutable arr = foo(); } compiles thanks to the fact that the compiler can guarantee from the signature of foo that its return value is unique. Oh is that run at runtime? I thought D was just smart and did it using CTFE. Well, D could be smart enough and call a runtime function that says it's moving data from thread-local to shared (or vice versa). We also have std.exception.assumeUnique (which is just a cast to immutable) as a way to document that you're guaranteeing that a reference to an object is unique and therefore can be safely cast to immutable. Can't say I've used std.exception.assumeUnique, but I guess other people have a use for it as it exists. Would be nice if you could inject type checking information at compile time without effecting the storage class. But thats a bit OT now. assumeUnique is a library function, it could be instrumented to do the right thing. I think it's possible to do this in D, but you need language support. -Steve
[Issue 18734] bitnum parameter of core.bitop.bt should be signed
https://issues.dlang.org/show_bug.cgi?id=18734 uplink.co...@googlemail.com changed: What|Removed |Added CC||uplink.co...@googlemail.com --- Comment #1 from uplink.co...@googlemail.com --- DMD does not recognize bodies only function signatures. So change it all you like :) it's only going to be used on systems where the intrinsic can't work. --
Re: #include C headers in D code
On Tuesday, 10 April 2018 at 09:36:39 UTC, Atila Neves wrote: On Monday, 9 April 2018 at 20:19:35 UTC, Seb wrote: On Monday, 9 April 2018 at 19:36:23 UTC, Atila Neves wrote: On Monday, 9 April 2018 at 18:15:33 UTC, kinke wrote: [...] This whole idea came about because a couple of years ago I was in a team that was responsible for legacy code written in C which had no tests. To write tests, we needed both to write the tests themselves and some fakes/mocks/doubles for the code that we depended on - essentially a whole operating system. I wasn't going to write that in C, since life is too short for that. [...] Speaking of dstep - it has greatly improved over the last years. I'm interested what stop you from using it or improving it (instead of rolling your own tool)? I tried using dstep as the translation engine to avoid reinventing the wheel. I'm lazy, I don't want to write code that doesn't neeed to be written! Nice work. I prefer the DStep approach of translating the headers to D, but obviously it's not going to be as easy for the user as this, so this approach has its uses too. Regarding "reinventing the wheel," I liked this recent blog post giving reasons why it can be a viable approach: https://blog.cerebralab.com/#!/blog/11
[Issue 18752] New: std.file.read runnable example fails
https://issues.dlang.org/show_bug.cgi?id=18752 Issue ID: 18752 Summary: std.file.read runnable example fails Product: D Version: D2 Hardware: All OS: All Status: NEW Severity: minor Priority: P1 Component: dlang.org Assignee: nob...@puremagic.com Reporter: basti...@veelo.net Pressing "Run" on https://dlang.org/library/std/file/read.html gives ``` core.exception.AssertError@onlineapp.d(8): Assertion failure ??:? _d_assertp [0x9dda8549] ??:? _Dmain [0x9dd9cd58] === Bypassed === std.file.FileException@std/file.d(351): /tmp/deleteme.dmd.unittest.pid24: No such file or directory ??:? @safe bool std.file.cenforce!(bool).cenforce(bool, lazy const(char)[], immutable(char)[], ulong) [0x9ddaeeb7] ??:? @trusted void[] std.file.readImpl(const(char)[], const(char)*, ulong) [0x9ddad5db] ??:? @safe void[] std.file.read!(immutable(char)[]).read(immutable(char)[], ulong) [0x9dd9e3ad] ??:? _Dmain [0x9dd9] === ~Bypassed === /tmp/deleteme.dmd.unittest.pid241234 ``` Best regards, Bastiaan. --
Re: SMTP Mail
On Monday, 9 April 2018 at 19:19:53 UTC, Adam D. Ruppe wrote: On Monday, 9 April 2018 at 15:38:55 UTC, Vino.B wrote: Thank you very much, I copied your folder arsd under the phobes folder in c:\D\... and the program was placed on my desktop and tried to execute it from the desktop via rdmd. I don't think rdmd is seeing the dependency on htmltotext.d. Try importing it explicitly from your main: import arsd.email; import arsd.htmltotext; /* the rest of your code */ Just that way rdmd will find it easier. Hi Adam, Now the program works, but the attachment does not work as expected, message.addAttachment("text/plain", "C:\\Temp\\Test\Test1.txt", "Test"); It takes the full path as file name eg: If the attachment file resides on the path C:\Temp\Test\Test1.txt" the attachment name file name that we receive is as "CTempTestTest1.txt" and also it does not attached the real file, instead the content of the file is "Test" We Tried the below message.addAttachment("text/plain", "Test1.txt", "C:\\Temp\\Test\Test1.txt"); After the above change the attachment file name is "Test1.txt" with the content "C:\Temp\Test\Test1.txt" The orignal content of the file is "Hi This is Test Attachment". From, Vino.B
[Issue 18199] Error with lambda in struct initializer
https://issues.dlang.org/show_bug.cgi?id=18199 --- Comment #10 from github-bugzi...@puremagic.com --- Commits pushed to master at https://github.com/dlang/dmd https://github.com/dlang/dmd/commit/019f0016cf7a6e11584fe0188f9e692215cce212 fix Issue 18199 - Error with lambda in struct initializer Allow struct initializers to include all function literal forms. Previously, a function literal containing semicolon or return tokens would cause the containing struct initializer to be incorrectly treated as a parameterless funtion literal (i.e. {statements...}). The issue is resolved by only aborting the struct initializer lookahead when statement tokens appear at the top curly bracket scope. A bug in the converse case, where a function literal containing no semicolon or return tokens would be incorrectly parsed as a struct initializer, is also addressed. Also, document another ambiguous case in function literal vs. struct initializer, as well as explain why these are resolved as struct initializer. https://github.com/dlang/dmd/commit/1edd074334f9f65d75d318df347f377d69eb002e Merge pull request #8051 from belm0/fix-18199 fix Issue 18199 - Error with lambda in struct initializer merged-on-behalf-of: Mike Franklin--
[Issue 18199] Error with lambda in struct initializer
https://issues.dlang.org/show_bug.cgi?id=18199 github-bugzi...@puremagic.com changed: What|Removed |Added Status|NEW |RESOLVED Resolution|--- |FIXED --
Re: #include C headers in D code
On Tuesday, 10 April 2018 at 08:45:06 UTC, Walter Bright wrote: On 4/9/2018 4:03 AM, Atila Neves wrote: Here's my blog post about my project that allows directly #including C headers in D* Very nice work, and great article! Thanks!
Re: Thoughts on Herb Sutter's Metaclasses?
On Tuesday, 10 April 2018 at 05:55:06 UTC, Joakim wrote: On Tuesday, 10 April 2018 at 01:21:07 UTC, Chris Katko wrote: [...] See previous forum thread on the topic, with Walter chiming in a bit too: https://forum.dlang.org/thread/kglnxqbcugerhynng...@forum.dlang.org Wow, that thread had very little discussion, and a huge amount of bickering over whether someone actually understood what someone else might have said.
Re: Migrating an existing more modern GC to D's gc.d
On Tuesday, April 10, 2018 08:37:47 David Bennett via Digitalmars-d wrote: > On Tuesday, 10 April 2018 at 08:10:32 UTC, Jonathan M Davis wrote: > > Yes. They expect it to work, and as the language is currently > > designed, it works perfectly well. In fact, it's even built > > into the language. e.g. > > > > int[] foo() pure > > { > > return [1, 2, 3, 4]; > > } > > > > void main() > > { > > immutable arr = foo(); > > } > > > > compiles thanks to the fact that the compiler can guarantee > > from the signature of foo that its return value is unique. > > Oh is that run at runtime? I thought D was just smart and did it > using CTFE. CTFE only ever happens when it must happen. The compiler never does it as an optimization. So, if you did enum arr = foo(); or static arr = foo(); then it would use CTFE, because an enum's value must be known at compile time, and if a static variable is directly initialized instead of initialized via a static constructor, its value must be known at compile time. But if you're initializing a variable whose value does not need to be known at compile time, then no CTFE occurs. It would be a serious rabbit hole for the compiler to attempt CTFE when it wasn't told to, particularly since it can't look at a function and know whether it's going to work with CTFE or not. It has to actually call it with a specific set of arguments to find out (and depending on what the function does, it might even work with CTFE with some arguments and not with others - e.g. if a particular branch of an if statement works with CTFE while another does an operation that doesn't work with CTFE). - Jonathan M Davis
Re: #include C headers in D code
On 4/9/2018 4:03 AM, Atila Neves wrote: Here's my blog post about my project that allows directly #including C headers in D* Very nice work, and great article!
Re: Migrating an existing more modern GC to D's gc.d
On Tuesday, 10 April 2018 at 08:10:32 UTC, Jonathan M Davis wrote: Yes. They expect it to work, and as the language is currently designed, it works perfectly well. In fact, it's even built into the language. e.g. int[] foo() pure { return [1, 2, 3, 4]; } void main() { immutable arr = foo(); } compiles thanks to the fact that the compiler can guarantee from the signature of foo that its return value is unique. Oh is that run at runtime? I thought D was just smart and did it using CTFE. We also have std.exception.assumeUnique (which is just a cast to immutable) as a way to document that you're guaranteeing that a reference to an object is unique and therefore can be safely cast to immutable. Can't say I've used std.exception.assumeUnique, but I guess other people have a use for it as it exists. Would be nice if you could inject type checking information at compile time without effecting the storage class. But thats a bit OT now. Because of how restrictive shared and immutable are, you frequently have to build them from thread-local, mutable data. And while it's preferable to have as little in your program be shared as possible and to favor solutions such as doing message passing with std.concurrency, there are situations where you pretty much need to have complex shared objects. And since D is a systems language, we're a lot more restricted in the assumptions that we can make in comparison to a language such as Java or C#. Yeah i agree that any solution should keep in mind that D is a systems language and should allow you to do stuff when you need to. Oh, I just had a much simpler idea that shouldn't have any issues, I'll see if that makes the GC faster to allocate. (everything else is the same)
Re: Migrating an existing more modern GC to D's gc.d
On Tuesday, April 10, 2018 07:55:00 David Bennett via Digitalmars-d wrote: > On Tuesday, 10 April 2018 at 06:47:53 UTC, Jonathan M Davis wrote: > > As it stands, it's impossible to have thread-local memory > > pools. It's quite legal to construct an object as shared or > > thread-local and cast it to the other. In fact, it's _highly_ > > likely that that's how any shared object of any complexity is > > going to be constructed. Similarly, it's extremely common to > > allocate an object as mutable and then cast it to immutable > > (either using assumeUnique or by using a pure function where > > the compiler does the cast implicitly for you if it can > > guarantee that the return value is unique), and immutable > > objects are implicitly shared. > > (Honest question:) Do people really cast from local to > shared/immutable and expect it to work? > (when ever I cast something more complex then a size_t I almost > expect it to blow up... or break sometime in the future) Yes. They expect it to work, and as the language is currently designed, it works perfectly well. In fact, it's even built into the language. e.g. int[] foo() pure { return [1, 2, 3, 4]; } void main() { immutable arr = foo(); } compiles thanks to the fact that the compiler can guarantee from the signature of foo that its return value is unique. We also have std.exception.assumeUnique (which is just a cast to immutable) as a way to document that you're guaranteeing that a reference to an object is unique and therefore can be safely cast to immutable. > That said, I can understanding building a shared object from > parts of local data... though I try to keep my thread barriers as > thin as possible myself. (meaning I tend to copy stuff to the > shared and have as few shared's as possible) Because of how restrictive shared and immutable are, you frequently have to build them from thread-local, mutable data. And while it's preferable to have as little in your program be shared as possible and to favor solutions such as doing message passing with std.concurrency, there are situations where you pretty much need to have complex shared objects. And since D is a systems language, we're a lot more restricted in the assumptions that we can make in comparison to a language such as Java or C#. - Jonathan M Davis
Re: Migrating an existing more modern GC to D's gc.d
On Tuesday, 10 April 2018 at 06:47:53 UTC, Jonathan M Davis wrote: As it stands, it's impossible to have thread-local memory pools. It's quite legal to construct an object as shared or thread-local and cast it to the other. In fact, it's _highly_ likely that that's how any shared object of any complexity is going to be constructed. Similarly, it's extremely common to allocate an object as mutable and then cast it to immutable (either using assumeUnique or by using a pure function where the compiler does the cast implicitly for you if it can guarantee that the return value is unique), and immutable objects are implicitly shared. (Honest question:) Do people really cast from local to shared/immutable and expect it to work? (when ever I cast something more complex then a size_t I almost expect it to blow up... or break sometime in the future) That said, I can understanding building a shared object from parts of local data... though I try to keep my thread barriers as thin as possible myself. (meaning I tend to copy stuff to the shared and have as few shared's as possible) At minimum, there would have to be runtime hooks to do something like move an object between pools when it is cast to shared or immutable (or back) in order to ensure that an object was in the right pool, but if that requires copying the object rather than just moving the memory block, then it can't be done, because every pointer or reference pointing to that object would have to be rewritten (which isn't supported by the language). A hook for local to cast(shared) could work... but would require a DIP I guess. I was hoping to make a more incremental improvement the the GC. Also, it would be a disaster for shared, because the typical way to use shared is to protect the shared object with a mutex, cast away shared so that it can be operated on as thread-local within that section of code, and then before the mutex is released, all thread-local references then need to be gone. e.g. synchronized(mutex) { auto threadLocal = cast(MyType)mySharedObject; // do something with threadLocal... // threadLocal leaves scope and is gone without being cast back } // all references to the shared object should now be shared Yeah thats why I was still scanning all thread stacks and pages when marking global data. So a shared -> local is a no op but the other way needs thought. You really _don't_ want the shared object to move between pools because of that cast (since it would hurt performance), and in such a situation, you don't usually cast back to shared. Rather, you have a shared reference, cast it to get a thread-local reference, and then let the thread-local reference leave scope. So, the same object temporarily has both a thread-local and a shared reference to it, and if it were moved to the thread-local pool with the cast, it would never be moved back when the thread-local references left scope and the mutex was released. Having synchronized classes as described in TDPL would make the above code cleaner in the cases where a synchronized class would work, but the basic concept is the same. It would still be doing a cast underneath the hood, and it would still have the same problems. It just wouldn't involve explicit casting. shared's design inherently requires casting away shared, so it just plain isn't going to play well with anything that doesn't play well with such casts - such as having thread-local heaps. I would think a shared class would never be marked as a THREAD_LOCAL as it has a shared member. Also, IIRC, at one point, Daniel Murphy explained to me some problem with classes with regards to the virtual table or the TypeInfo that inherently wouldn't work with trying to move it between threads. Unfortunately, I don't remember the details now, but I do remember that there's _something_ there that wouldn't work with thread-local heaps. And if anyone were to seriously try it, I expect that he could probably come up with the reasons again. Regardless, I think that it's clear that in order to do anything with thread-local pools, we'd have to lock down the type system even further to disallow casts to or from shared or immutable, and that would really be a big problem given the inherent restrictions on those types and how shared is intended to be used. So, while it's a common idea as to how the GC could be improved, and it would be great if we could do it, I think that it goes right along with all of the other ideas that require stuff like read and write barriers everywhere and thus will never be in D's GC. - Jonathan M Davis Yeah I thought it would have issues, thanks for your feedback! I'll see if I can come up with a better idea that doesn't break as much stuff.
Re: Migrating an existing more modern GC to D's gc.d
On Tuesday, 10 April 2018 at 06:43:28 UTC, Dmitry Olshansky wrote: On Tuesday, 10 April 2018 at 06:10:10 UTC, David Bennett wrote: I was thinking about messing with the GC in my free time just yesterday... how hard would it be: [snip] Lost immutable and that thread-local is often casted to immutable, sometimes by compiler. See assumeUnique and its ilk in Phobos. Same with shared - it’s still often the case that you allocate thread-local then cast to shared. People cast from thread local to shared? ...okay thats no fun... :( I can understand the other way, thats why i was leaning on the conservative side and putting more stuff in the global pools. Lastly - thanks to 0-typesafety of delegates it’s trivial to share a single GC-backed stack with multiple threads. So what you deemed thread-local might be used in other thread, transitively so. Oh thats a good point I didn't think of! D is thread-local except when it’s not. If thats possible we could also Just(TM) scan the current thread stack and mark/sweep only those pages. (without a stop the world) That is indeed something we should at some point have. Needs cooperation from the language such as explicit functions for shared<->local conversions that run-time is aware of. So the language could (in theory) inject a __move_to_global(ref local, ref global) when casting to shared and the GC would need to update all the references in the local pages to point to the new global address? And when a thread ends we could give the pages to the global pool without a mark/sweep. The idea is it works like it does currently unless something is invisible to other threads, Or am i missing something obvious? (quite likely) Indeed there are ugly details that while would allow per thread GC in principle will in general crash and burn on most non-trivial programs. Okay, thanks for the points they were very clear so I assume you have spent a lot more brain power on this then I have.
[Issue 18749] bt instruction using 64-bit register for 32-bit offset
https://issues.dlang.org/show_bug.cgi?id=18749 Ketmar Darkchanged: What|Removed |Added CC||ket...@ketmar.no-ip.org --
[Issue 18748] bt instruction with immediate offset uses 64-bit variant for 32-bit data
https://issues.dlang.org/show_bug.cgi?id=18748 Ketmar Darkchanged: What|Removed |Added CC||ket...@ketmar.no-ip.org --
Re: Migrating an existing more modern GC to D's gc.d
On Tuesday, April 10, 2018 06:10:10 David Bennett via Digitalmars-d wrote: > On Tuesday, 10 April 2018 at 05:26:28 UTC, Dmitry Olshansky wrote: > > On Monday, 9 April 2018 at 19:50:16 UTC, H. S. Teoh wrote: > >> Last I remembered, you were working on a GC prototype for D? > > > > Still there, but my spare time is super limited lately, the > > other project preempted that for the moment. > > > >> Any news on that, or have you basically given it up? > > > > Might try to hack to the finish line in one good night, it was > > pretty close to complete. Debugging would be fun though ;) > > I was thinking about messing with the GC in my free time just > yesterday... how hard would it be: > > Add a BlkAttr.THREAD_LOCAL, and set it from the runtime if the > type or it's members are not shared or __gshared. > > Then we could store BlkAttr.THREAD_LOCAL memory in different > pages (per thread) without having to setting a mutex. (if we need > to get new page from the global pool we set a mutex for that) > > If thats possible we could also Just(TM) scan the current thread > stack and mark/sweep only those pages. (without a stop the world) > > And when a thread ends we could give the pages to the global pool > without a mark/sweep. > > The idea is it works like it does currently unless something is > invisible to other threads, Or am i missing something obvious? > (quite likely) As it stands, it's impossible to have thread-local memory pools. It's quite legal to construct an object as shared or thread-local and cast it to the other. In fact, it's _highly_ likely that that's how any shared object of any complexity is going to be constructed. Similarly, it's extremely common to allocate an object as mutable and then cast it to immutable (either using assumeUnique or by using a pure function where the compiler does the cast implicitly for you if it can guarantee that the return value is unique), and immutable objects are implicitly shared. At minimum, there would have to be runtime hooks to do something like move an object between pools when it is cast to shared or immutable (or back) in order to ensure that an object was in the right pool, but if that requires copying the object rather than just moving the memory block, then it can't be done, because every pointer or reference pointing to that object would have to be rewritten (which isn't supported by the language). Also, it would be a disaster for shared, because the typical way to use shared is to protect the shared object with a mutex, cast away shared so that it can be operated on as thread-local within that section of code, and then before the mutex is released, all thread-local references then need to be gone. e.g. synchronized(mutex) { auto threadLocal = cast(MyType)mySharedObject; // do something with threadLocal... // threadLocal leaves scope and is gone without being cast back } // all references to the shared object should now be shared You really _don't_ want the shared object to move between pools because of that cast (since it would hurt performance), and in such a situation, you don't usually cast back to shared. Rather, you have a shared reference, cast it to get a thread-local reference, and then let the thread-local reference leave scope. So, the same object temporarily has both a thread-local and a shared reference to it, and if it were moved to the thread-local pool with the cast, it would never be moved back when the thread-local references left scope and the mutex was released. Having synchronized classes as described in TDPL would make the above code cleaner in the cases where a synchronized class would work, but the basic concept is the same. It would still be doing a cast underneath the hood, and it would still have the same problems. It just wouldn't involve explicit casting. shared's design inherently requires casting away shared, so it just plain isn't going to play well with anything that doesn't play well with such casts - such as having thread-local heaps. Also, IIRC, at one point, Daniel Murphy explained to me some problem with classes with regards to the virtual table or the TypeInfo that inherently wouldn't work with trying to move it between threads. Unfortunately, I don't remember the details now, but I do remember that there's _something_ there that wouldn't work with thread-local heaps. And if anyone were to seriously try it, I expect that he could probably come up with the reasons again. Regardless, I think that it's clear that in order to do anything with thread-local pools, we'd have to lock down the type system even further to disallow casts to or from shared or immutable, and that would really be a big problem given the inherent restrictions on those types and how shared is intended to be used. So, while it's a common idea as to how the GC could be improved, and it would be great if we could do it, I think that it goes right along with all of the other ideas that require stuff like read and write barriers
Re: Migrating an existing more modern GC to D's gc.d
On Tuesday, 10 April 2018 at 06:10:10 UTC, David Bennett wrote: On Tuesday, 10 April 2018 at 05:26:28 UTC, Dmitry Olshansky wrote: On Monday, 9 April 2018 at 19:50:16 UTC, H. S. Teoh wrote: Last I remembered, you were working on a GC prototype for D? Still there, but my spare time is super limited lately, the other project preempted that for the moment. Any news on that, or have you basically given it up? Might try to hack to the finish line in one good night, it was pretty close to complete. Debugging would be fun though ;) I was thinking about messing with the GC in my free time just yesterday... how hard would it be: Add a BlkAttr.THREAD_LOCAL, and set it from the runtime if the type or it's members are not shared or __gshared. Then we could store BlkAttr.THREAD_LOCAL memory in different pages (per thread) without having to setting a mutex. (if we need to get new page from the global pool we set a mutex for that) Lost immutable and that thread-local is often casted to immutable, sometimes by compiler. See assumeUnique and its ilk in Phobos. Same with shared - it’s still often the case that you allocate thread-local then cast to shared. Lastly - thanks to 0-typesafety of delegates it’s trivial to share a single GC-backed stack with multiple threads. So what you deemed thread-local might be used in other thread, transitively so. D is thread-local except when it’s not. If thats possible we could also Just(TM) scan the current thread stack and mark/sweep only those pages. (without a stop the world) That is indeed something we should at some point have. Needs cooperation from the language such as explicit functions for shared<->local conversions that run-time is aware of. And when a thread ends we could give the pages to the global pool without a mark/sweep. The idea is it works like it does currently unless something is invisible to other threads, Or am i missing something obvious? (quite likely) Indeed there are ugly details that while would allow per thread GC in principle will in general crash and burn on most non-trivial programs.
Re: #include C headers in D code
On Monday, 9 April 2018 at 11:03:48 UTC, Atila Neves wrote: Here's my blog post about my project that allows directly #including C headers in D* neat!