Re: From the D Blog: Crafting Self-Evident Code in D
On Monday, 2 October 2023 at 17:28:19 UTC, Mike Parker wrote: It's been a long, long while since I published anything on the blog. I do intend to get pick it up again down the road, but Walter recently surprised me with plans of his own. He's taken the topic of his DConf '23 talk and derived a blog post from it: https://dlang.org/blog/2023/10/02/crafting-self-evident-code-with-d/ I guess he got impatient with the pace at which I'm getting the talk videos uploaded :-) And for anyone who'd like to engage in any Reddit discussion that comes up: https://www.reddit.com/r/programming/comments/16y2h36/crafting_selfevident_code_in_dlang/ Good talk. Many very clever people would achieve more if they tried to understand why a v. experienced developer would care to spend so much time talking about what might appear to be such basic points. The key challenge: If this stuff was so obvious & everyone did it or it didn't matter so much that they didn't, why would Walter care about it so much?
Re: mutable pointers as associative array keys
On Monday, 10 April 2023 at 20:31:43 UTC, Steven Schveighoffer wrote: On 4/10/23 4:25 PM, Steven Schveighoffer wrote: It's also completely useless. Having const keys does nothing to guarantee unchanging keys. Another half-assed attempt to be encode correct semantics but fails completely in its goal. In case you wonder how old this is: https://issues.dlang.org/show_bug.cgi?id=11477 https://issues.dlang.org/show_bug.cgi?id=12491#c2 -Steve Oh dear.
mutable pointers as associative array keys
It seems that it isn't possible, am I missing something? alias Q = int[int*]; pragma(msg, Q); // int[const(int)*] Also, is this documented somewhere?
Re: text based file formats
On Wednesday, 21 December 2022 at 04:19:46 UTC, 9il wrote: On Tuesday, 20 December 2022 at 19:46:36 UTC, John Colvin wrote: On Tuesday, 20 December 2022 at 00:40:07 UTC, H. S. Teoh wrote: [...] We use this at work with some light tweaks, it’s done a lot work It has already been replaced with [mir.csv](https://github.com/libmir/mir-ion/blob/master/source/mir/csv.d). Mir is faster, SIMD accelerated, and supports numbers and timestamp recognition. Hah, so it has! Well anyway, it did do a lot of hard work for us for a long time, so thanks :)
Re: text based file formats
On Tuesday, 20 December 2022 at 00:40:07 UTC, H. S. Teoh wrote: On Mon, Dec 19, 2022 at 04:16:57PM -0800, Walter Bright via Digitalmars-d-announce wrote: On 12/19/2022 4:35 AM, Adam D Ruppe wrote: > On Monday, 19 December 2022 at 09:55:47 UTC, Walter Bright > wrote: > > Curious why CSV isn't in the list. > > Maybe std.csv is already good enough? LOL, learn something every day! I've even written my own, but it isn't very good. There's also my little experimental csv parser that was designed to be as fast as possible: https://github.com/quickfur/fastcsv However it can only handle input that fits in memory (using std.mmfile is one possible workaround), has a static limit on field sizes, and does not do validation. T We use this at work with some light tweaks, it’s done a lot work
Re: Beerconf October 2022
On Sunday, 30 October 2022 at 01:50:33 UTC, Steven Schveighoffer wrote: On 10/29/22 2:00 PM, FeepingCreature wrote: On Saturday, 29 October 2022 at 10:14:31 UTC, rikki cattermole wrote: And now for some good news! Its almost Halloween, so grab your candy and any spooky brews you may have, and join us for a ghostly chat! https://meet.jit.si/Dlang2022OctoberBeerConf I wish you'd announce the time a bit in advance. :) I don't want to announce a time, because I don't know what time it can be started. I'm in the US, so I'm usually asleep when it's started. But I do try to announce 2 weeks before and then 2 days before. -Steve Quiet here, I’m around for a couple of hours, come say hi!
Re: Symmetry looking for D programmers in Singapore/Hong Kong/Australia/New Zealand
On Wednesday, 16 June 2021 at 17:13:35 UTC, russhy wrote: For what kind of project? need more info It might help to look at https://jobs.symmetryinvestments.dev/ and https://github.com/symmetryinvestments/
Re: From the D Blog -- Interfacing D with C: Strings Part One
On Monday, 24 May 2021 at 16:16:53 UTC, Steven Schveighoffer wrote: On 5/24/21 10:02 AM, Mike Parker wrote: The latest post in the D and C series dives into the weeds of D and C strings: how they're implemented, when you need to NUL-terminate your D strings and when you don't, and how the storage of literals in memory allows you to avoid NUL termination in one case you might not have considered and another case that you shouldn't rely on but can in practice with the current compilers. There are at least two more posts worth of information to go into on this topic, but everything in this post is enough to cover many use cases of D to C string interop. The blog: https://dlang.org/blog/2021/05/24/interfacing-d-with-c-strings-part-one/ Reddit: https://www.reddit.com/r/programming/comments/njyf76/interfacing_d_with_c_strings_part_one/ Nice article! Note that there is a huge pitfall awaiting you if you use `toStringz`: garbage collection. You may want to amend the article to identify this pitfall. And I'm not talking about requiring `@nogc`, I'm talking about the GC collecting the data while C is still using it. In your example: ```d puts(s1.toStringz()); ``` This leaves a GC-collectible allocation in C land. For `puts`, it's fine, as the data is not used past the call, but in something else that might keep it somewhere not accessible to the GC, you'll want to assign that to a variable that lasts as long as the resource is used. -Steve It’s worse than that, no? If the only reference to GC data isn’t on the stack of a tracked thread, in GC allocated memory or in a tracked root then it can be freed. Even in D: void foo(int* a) { int** b = cast(int**) malloc((int*).sizeof); *b = a; a = null; GC.collect(); **b = 4; // whoops!! } foo(new int); Right? Obviously that collection could be from calling another function (e.g. a callback from C to D code) or from another thread. Or am I missing something?
Re: Printing shortest decimal form of floating point number with Mir
On Monday, 4 January 2021 at 17:22:55 UTC, John Colvin wrote: On Monday, 4 January 2021 at 13:47:17 UTC, Ola Fosheim Grøstad wrote: [...] I have a longer reply I'm trying to write, but just to make sure I'm on the right track: template Foo(T) { alias Foo = T; } template Q(A : Foo!T, T) { pragma(msg, A.stringof, " ", T.stringof); } alias X = Q!(Foo!int); in your opinion, this should compile and msg `int int`, yes? I'm trying to make a really concise example without using IFTI. and presumably the same for alias X = Q!(int); yes?
Re: Printing shortest decimal form of floating point number with Mir
On Monday, 4 January 2021 at 13:47:17 UTC, Ola Fosheim Grøstad wrote: On Monday, 4 January 2021 at 12:35:12 UTC, John Colvin wrote: What's the simplest example that doesn't work and is that simple example just indirection through an alias or is it actually indirection through a template that *when instantiated* turns out to be just an alias? Indirection through a parametric alias. This is the simplest I have come up with so far: struct Foo(T) {} alias Bar(T) = Foo!T; void f(T)(Bar!T x) {} void main() { f(Bar!int()); } I created a thread for it: https://forum.dlang.org/post/nxrfrizqdmhzhivxp...@forum.dlang.org I have a suspicion that what you're asking for here is the type-inference to have x-ray vision in to uninstantiated templates that works for a few simple cases. Am I wrong? No, just substitute: "Bar!int" with "Foo!int". To be clear, a really useful special case can be really useful and worthwhile, but I'm not convinced this is the principled "type system bug" you are saying it is. Why are you not convinced? An alias is a short hand. If it is possible to discriminate by the alias and the actual object then that it a semantic problem. I have a longer reply I'm trying to write, but just to make sure I'm on the right track: template Foo(T) { alias Foo = T; } template Q(A : Foo!T, T) { pragma(msg, A.stringof, " ", T.stringof); } alias X = Q!(Foo!int); in your opinion, this should compile and msg `int int`, yes? I'm trying to make a really concise example without using IFTI.
Re: Printing shortest decimal form of floating point number with Mir
On Monday, 4 January 2021 at 09:21:02 UTC, Ola Fosheim Grøstad wrote: On Monday, 4 January 2021 at 09:18:50 UTC, Ola Fosheim Grøstad wrote: On Monday, 4 January 2021 at 05:55:37 UTC, Ola Fosheim Grostad wrote: On Monday, 4 January 2021 at 04:37:22 UTC, 9il wrote: I suppose the answer would be that D doesn't pretend to support all C++ template features and the bug is not a bug because we live with this somehow for years. But it is a bug even if there was no C++... An alias should work by simple substitution, if it does not, then it is no alias... Here is an even simpler example that does not work: struct Foo(T){} void foo(T)(T!int x) {} alias FooInt = Foo!int; void main() { foo(FooInt()); } Oh, now wait, it does: struct Foo(T){} void foo(alias T)(T!int x) {} alias FooInt = Foo!int; void main() { foo(FooInt()); } My mistake. What's the simplest example that doesn't work and is that simple example just indirection through an alias or is it actually indirection through a template that *when instantiated* turns out to be just an alias? I have a suspicion that what you're asking for here is the type-inference to have x-ray vision in to uninstantiated templates that works for a few simple cases. Am I wrong? To be clear, a really useful special case can be really useful and worthwhile, but I'm not convinced this is the principled "type system bug" you are saying it is.
Re: Printing shortest decimal form of floating point number with Mir
On Thursday, 24 December 2020 at 14:14:33 UTC, 9il wrote: On Thursday, 24 December 2020 at 14:08:32 UTC, welkam wrote: On Wednesday, 23 December 2020 at 18:05:40 UTC, 9il wrote: It was a mockery executed by Atila Read the all comments and didnt saw any mockery Yes, it wasn't explicit. He didn't write bad words, he did a bad decision. Bad for D. Big difference between bad decision and mockery. It's very possible he was wrong, but I don't think he wasn't taking it seriously.
Re: MIR vs. Numpy
On Wednesday, 18 November 2020 at 13:01:42 UTC, Bastiaan Veelo wrote: On Wednesday, 18 November 2020 at 10:05:06 UTC, Tobias Schmidt wrote: Dear all, to compare MIR and Numpy in the HPC context, we implemented a multigrid solver in Python using Numpy and in D using Mir and perforemd some benchmarks with them. You can find our code and results here: https://github.com/typohnebild/numpy-vs-mir Nice numbers. I’m not a Python guy but I was under the impression that Numpy actually is written in C, so that when you benchmark Numpy you’re mostly benchmarking C, not Python. Therefore I had expected the Numpy performance to be much closer to D’s. An important factor I think, which I’m not sure you have discussed (didn’t look too closely), is the compiler backend that was used to compile D and Numpy. Then again, as a user one is mostly interested in the out-of-the-box performance, which this seems to be a good measure of. — Bastiaan. A lot of numpy is in C, C++, fortran, asm etc But when you chain a bunch of things together, you are going via python. The language boundary (and python being slow) means that internal iteration in native code is a requirement for performance, which leads to eager allocation for composability via python, which then hurts performance. Numpy makes a very good effort, but is always constrained by this. Clever schemes with laziness where operations in python are actually just composing operations for execution later/on-demand can work as an alternative, but a) that's hard and b) even if you can completely avoid calling back in to python during iteration you would still need JIT to really unlock the performance. Julia fixes this by having all/most in one language which is JIT'd D can do the same with templates AOT, like C++/Eigen does but more flexible and less terrifying code. That's (one part of) what mir provides.
Highlight general point about software dev and design in general.
On Tuesday, 20 October 2020 at 21:58:16 UTC, Johan Engelen wrote: On Tuesday, 20 October 2020 at 20:21:56 UTC, aberba wrote: On Tuesday, 20 October 2020 at 17:36:11 UTC, kinke wrote: On Tuesday, 20 October 2020 at 16:08:47 UTC, aberba wrote: It's an option but doesn't fill the need for an installer. Not sure why its hasn't been done. See https://github.com/ldc-developers/ldc/issues/1754. From the discussions, it seems you still don't see the value of an installer...backing it with the idea that LDC is for "developers". I'm a developer myself and I use installers all the time when on Windows...there are very few people I personally know who would go for an archive file to set it up themselves. So not everyone is like you. The reason why I personally go for DMD over LDC is convenience (especially when introducing D to newbies)...even though LDC is more optimized for performance. Unless what you guys are doing is an artificial barrier to get others to not use it. Guys, all points have been made, there is no wrong and right here, let's stop arguing over this. What is needed is someone who thinks it is useful to have an exe installer and wants to do the work. It cannot be done by someone who thinks it is not useful, because there are decisions to be made (like which folder to install it in, whether to overwrite old or not), that can only be made by someone who actually cares about it. There is no point in trying to convince kinke or me. I'm sure noone will be against uploading the installer exe onto github release page once it's been made and checked. -Johan Johan hits an important nail right on the head here. While it is possible to design for others who are unlike you, it's much harder than designing for yourself or those who have similar values and priorities w.r.t. the thing in question. A lot of talk about "we (and by we I mean you) should do this thing I think is important" isn't pushing in the most productive direction, because _*_*_{ even if one becomes convinced that there is value in something, that does not mean one has the relevant understanding necessary for good design of that thing }_*_*_ Either the person with the problem works on understanding the tools to fix the problem, or the person with the tools works on understanding the problem. When values and "user experience" and "ease of use" are in play, I think the latter usually gets harder than normal, because understanding what will be easy or pleasing for others who are unlike us is not something everyone is good at.* This shifts the balance towards preferring the former approach where the person with the problem works towards doing at least a significant part of the design.** There will always be other considerations of course, this is just one force out of many. This is not to say that developers shouldn't be thoughtful about their users - they definitely should be - but that doing a good job of that when the users are unlike the developer is _hard_. * Perhaps in practice that ability is negatively associated with a strong sense of personal taste, e.g. great musicians writing the music _they_ want, not trying to specifically please people; the magic isn't that they understand other people, it's that their particular tastes resonate with others strongly. Maybe truly great mass-market businesses come from people who both have that magic _and_ a strong ability to experience their work from other's perspectives, the combination being rare and the ability to integrate the two effectively being even rarer (Steve Jobs comes to mind). ** Design and implementation often don't separate very cleanly in practice, so this probably means implementing it too, at least to proof-of-concept quality.
Re: Beta 2.094.0
On Friday, 18 September 2020 at 13:35:34 UTC, Jacob Carlborg wrote: On 2020-09-17 12:10, John Colvin wrote: I personally think it's not so bad as long as the commit gets written to the dub.selections.json It doesn't. I know. But it should be. But then again a lot of things “should be” with dub.
Re: Beta 2.094.0
On Wednesday, 16 September 2020 at 18:52:23 UTC, Jacob Carlborg wrote: On 2020-09-16 19:20, mw wrote: Why it's deprecated? can we revive it? It was deprecated because it's a bad idea to not lock versions. Using `~master` would fetch the latest code from the "master" branch when compiling. You never know which version you get. You don't get reproducible builds. I personally think it's not so bad as long as the commit gets written to the dub.selections.json
Re: Decimal string to floating point conversion with correct half-to-even rounding
On Tuesday, 7 July 2020 at 15:08:33 UTC, Adam D. Ruppe wrote: On Tuesday, 7 July 2020 at 13:00:04 UTC, Steven Schveighoffer wrote: Doing that these days would be silly. You can depend on a specific version of a repository without problems. I always have problems when trying to do that. git submodules bring pretty consistent pain in my experience. But it probably isn't so bad if the submodule rarely changes. Just for 100% control anyway nothing beats copy/paste. Then there's zero difference between you writing it yourself. I kinda wish the D upstream were more willing to do that. My view is it shouldn't be on independent developers to add stuff to Phobos, for example, instead the Phobos team should just be copying and testing modules they are interested in on their own. git subtree it's like submodules but also like copy-paste.
Re: Rationale for accepting DIP 1028 as is
On Wednesday, 27 May 2020 at 05:49:49 UTC, Walter Bright wrote: On 5/26/2020 9:31 AM, Bruce Carneal wrote: Currently a machine checked @safe function calling an unannotated extern C routine will error out during compilation. This is great as the C routine was not machine checked, and generally can not be checked. Post 1028, IIUC, the compilation will go through without complaint. This seems quite clear. What am I missing? Nothing at all. But I doubt there is much legacy non-compiling code around. The point isn't that incorrect legacy code that didn't compile now does (although that does matter a bit), it's that newly written code will compile when it shouldn't. Existing code will be full of extern(C) declarations that are implicitly and correctly @system now and will become @safe with dip1028, which means that when I write new @safe code calling those (could be through a deep dependency chain of inferred-@safety APIs, multiple dub packages...) I could easily find my new code compiling when it shouldn't. Effectively, by silently @safe-ing things you can't infer, you will be changing APIs from @system to @trusted without any checks. Just in case there's any confusion, here's a timeline: 1. library A is written containing a dangerous but useful extern(C) declaration assuming @system by default. 2. application B is written for and compiled with dip1028, @safe: at the top of every file. 3. B adds a dependency on A. It continues to compile as @safe, calling an unsafe C function. This seems like one of those things where it's either wrong or a showstopper.
Re: Objective C protocols
On Saturday, 16 May 2020 at 19:14:51 UTC, John Colvin wrote: What's the best way to implement an Objective C protocol in D? I see mention here https://dlang.org/changelog/2.085.0.html#4_deprecated_objc_interfaces but it's not clear where things are these days. Based on some experimentation, I'm starting to wonder do protocols actually have any runtime component in Objective C? Because if I pass in an extern(Objective-C) class with the right interface to a function expecting a protocol everything just works.
Objective C protocols
What's the best way to implement an Objective C protocol in D? I see mention here https://dlang.org/changelog/2.085.0.html#4_deprecated_objc_interfaces but it's not clear where things are these days.
Re: Luneta: terminal fuzzy finder
On Tuesday, 5 May 2020 at 07:31:18 UTC, Panke wrote: On Monday, 4 May 2020 at 22:49:49 UTC, Felipe wrote: Hi, I develop an interactive terminal fuzzy finder in D with ncurses. Feel free to check it out and contribute. Any feedback is welcome. Thanks, Felipe [1] https://github.com/fbeline/luneta [2] https://code.dlang.org/packages/luneta [3] https://code.dlang.org/packages/fuzzyd What's the difference to fzf? Seems like this is being discussed here: https://github.com/fbeline/luneta/issues/28
Re: dmdcache
On Saturday, 25 April 2020 at 10:17:50 UTC, Ali Çehreli wrote: A colleague of mine has written dmdcache which may be very useful for some projects: https://github.com/seeraven/dmdcache It drops our build time from 8 minutes to 45 seconds on a particular build environment for about half a dozen D programs, one of which ends up being a 2G executable! WAT! :) And the total cache size is 5.5G. Wow! This build is with dmd 2.084.1 and that one particular application uses tons of template instantiations most of which are in generated source code. If I remember correctly, 2.084.1 does not contain template symbol name improvements and that may be the reason for the large size. Enjoy! Ali Perhaps I'm being very dumb, but how does this differ from just using make?
Re: DConf 2019 Pictures
On Tuesday, 7 January 2020 at 13:37:24 UTC, Ethan wrote: On Tuesday, 7 January 2020 at 09:04:04 UTC, Ali Çehreli wrote: This one is Laeeth introducing Andrei at Symmetry Investments: http://acehreli.org/photo/dconf_2019/DSC04839.html Ali And if you start here you get to the important bits: BeerConf! http://acehreli.org/photo/dconf_2019/DSC04853.html Damn... I miss beerconf.
Re: code.dlang.org downtime
On Wednesday, 18 December 2019 at 10:18:03 UTC, Sebastiaan Koppe wrote: On Wednesday, 18 December 2019 at 09:29:50 UTC, John Colvin wrote: This is still down for me, regardless of using the IP or address. I don't think it's just me either: https://stats.uptimerobot.com/6mQX4Crw2L/783838659 Anytime you see the metadata working you can add `--registry=https://dub.bytecraft.nl` to dub. I am really tempted to cache the metadata as well. Although that brings up the question of how to purge it when new versions are released. (I could setup a job to import the dump every now and then, hmm). This stuff just begs to be fixed. can't get metadata, so no good right now.
Re: code.dlang.org downtime
On Monday, 16 December 2019 at 11:04:38 UTC, Sönke Ludwig wrote: As you may have already noticed, the main registry server, code.dlang.org got unreachable yesterday. This was caused by an old VPS of mine getting terminated. The registry had already moved to a different server years ago, but, without me realizing it, the DNS entry still pointed to the old one, with a "temporary" HTTP proxy forwarding to the new server being set up. By now the DNS entry has been corrected, an up-to-date TLS certificate is in place, and the registry is running stable. There are still reports of people not being able to access code.dlang.org, which is apparently caused by intermediate DNS servers still reporting the old IP address and should start working during the next few hours. A temporary workaround is to specify --registry=http://31.15.67.41/ on the dub command line. Unfortunately both fallback servers have been down for a while now, so that this resulted in a total blackout. I plan to move the main registry to a powerful dedicated server in January, which will fix all memory resource related issues that sometimes show up, and could then keep the current VPS as a relatively reliable fallback server. Both together should guarantee virtually 100% uptime, although more fallback servers are of course highly desirable. In addition to that, I plan to separate the repository polling process form the web and REST frontend, as the former appears to be the main cause for failures (a GC memory leak of some kind and a possibly codegen related crash when being compiled with DMD being the two known issues, which both need further investigation). This is still down for me, regardless of using the IP or address. I don't think it's just me either: https://stats.uptimerobot.com/6mQX4Crw2L/783838659
Re: A proper WAT moment
On Monday, 14 October 2019 at 19:45:11 UTC, Paul Backus wrote: On Monday, 14 October 2019 at 17:00:56 UTC, John Colvin wrote: Different ability to access a property depending if I'm inside something else when I look? [snip] You're attempting to call one of S's member functions without an instance of S to call it on. Reduced version: struct S { int a; int e() @property { return a; } } void foo(S s) { pragma(msg, __LINE__, " ", __traits(compiles, S.e)); // true (???) S.e; // Error: need `this` for `e` of type `@property int()` } struct C { void foo(S s) { pragma(msg, __LINE__, " ", __traits(compiles, S.e)); // false S.e; // Error: `this` for `e` needs to be type `S` not type `C` } } The real issue here is that the first `__traits(compiles)` check succeeds, even though the actual expression fails. And all the other ones in my example that access members without an instance that also compile? There's something pretty strange about the rules here.
A proper WAT moment
Different ability to access a property depending if I'm inside something else when I look? struct S { int a; static int b; int c() { return a; } static int d() { return 3; } int e() @property { return a; } static int f() @property { return 3; } } void foo(S s) { pragma(msg, __LINE__, " ", __traits(compiles, __traits(getMember, s, "a"))); pragma(msg, __LINE__, " ", __traits(compiles, __traits(getMember, S, "a"))); pragma(msg, __LINE__, " ", __traits(compiles, __traits(getMember, s, "b"))); pragma(msg, __LINE__, " ", __traits(compiles, __traits(getMember, S, "b"))); pragma(msg, __LINE__, " ", __traits(compiles, __traits(getMember, s, "c"))); pragma(msg, __LINE__, " ", __traits(compiles, __traits(getMember, S, "c"))); pragma(msg, __LINE__, " ", __traits(compiles, __traits(getMember, s, "d"))); pragma(msg, __LINE__, " ", __traits(compiles, __traits(getMember, S, "d"))); pragma(msg, __LINE__, " ", __traits(compiles, __traits(getMember, s, "e"))); pragma(msg, __LINE__, " ", __traits(compiles, __traits(getMember, S, "e"))); pragma(msg, __LINE__, " ", __traits(compiles, __traits(getMember, s, "f"))); pragma(msg, __LINE__, " ", __traits(compiles, __traits(getMember, S, "f"))); } struct C(S) { void foo(S s) { pragma(msg, __LINE__, " ", __traits(compiles, __traits(getMember, s, "a"))); pragma(msg, __LINE__, " ", __traits(compiles, __traits(getMember, S, "a"))); pragma(msg, __LINE__, " ", __traits(compiles, __traits(getMember, s, "b"))); pragma(msg, __LINE__, " ", __traits(compiles, __traits(getMember, S, "b"))); pragma(msg, __LINE__, " ", __traits(compiles, __traits(getMember, s, "c"))); pragma(msg, __LINE__, " ", __traits(compiles, __traits(getMember, S, "c"))); pragma(msg, __LINE__, " ", __traits(compiles, __traits(getMember, s, "d"))); pragma(msg, __LINE__, " ", __traits(compiles, __traits(getMember, S, "d"))); pragma(msg, __LINE__, " ", __traits(compiles, __traits(getMember, s, "e"))); // ALL True except for this one: pragma(msg, __LINE__, " ", __traits(compiles, __traits(getMember, S, "e"))); pragma(msg, __LINE__, " ", __traits(compiles, __traits(getMember, s, "f"))); pragma(msg, __LINE__, " ", __traits(compiles, __traits(getMember, S, "f"))); } } alias C0 = C!S;
How to find what is causing a closure allocation
I have a function that allocates a closure somewhere in it (as shown by the result of -profile=gc). I can't make the function nogc as it calls a lot of other GC using code. profilegc.log only gives me the line number of the function signature, which doesn't give me any hint as to where in the function the closure is allocated. Anyone have any nice tricks to help narrow this down.
Re: Abstract classes vs interfaces, casting from void*
On Sunday, 11 August 2019 at 20:15:34 UTC, Alex wrote: On Sunday, 11 August 2019 at 16:05:20 UTC, John Colvin wrote: I'm trying to narrow down exactly what patterns work with each and how they overlap. What I was trying to get at with the abstract method thing is that abstract class C { void foo(); } is an abstract class with a non-abstract method, whose implementation is going to come from somewhere else (not a common pattern in D). class C { abstract void foo(); } is an abstract class with an abstract method foo, which means you have to override it in a inheriting class to get a non-abstract class. As I see this, everything you wrote is correct. :) But you compared abstractness with interface usage, initially. So... I would say, interfaces are more like the abstract method case without any function body. But then, you will have to use "override" all across the inherited classes. Ok. So that means the difference is pretty subtle, give or take a few extra keywords. Which leaves multiple inheritance as the only significant difference? From my perspective it looks like there are two massively overlapping features with some quite arbitrary feeling restrictions and differences. E.g. why can I not inherit from multiple 100% abstract empty classes? Wouldn't that be the same as inheriting from multiple interfaces?
Re: Abstract classes vs interfaces, casting from void*
On Sunday, 11 August 2019 at 15:16:03 UTC, Alex wrote: On Sunday, 11 August 2019 at 13:09:43 UTC, John Colvin wrote: Ok. What would go wrong (in D) if I just replaced every interface with an abstract class? I think there's some confusion here, because B.foo is not abstract. abstract on a class is not inherited by its methods. https://dlang.org/spec/attribute.html#abstract Now, I'm confused, as you asked about abstract classes. So, yes, you can define the abstractness of classes differently. And what is your point? I'm trying to narrow down exactly what patterns work with each and how they overlap. What I was trying to get at with the abstract method thing is that abstract class C { void foo(); } is an abstract class with a non-abstract method, whose implementation is going to come from somewhere else (not a common pattern in D). class C { abstract void foo(); } is an abstract class with an abstract method foo, which means you have to override it in a inheriting class to get a non-abstract class.
Re: Abstract classes vs interfaces, casting from void*
On Saturday, 10 August 2019 at 17:28:32 UTC, Alex wrote: ´´´ void main(){} interface A { void fun(); } abstract class B{ void fun(); } class C : A{ void fun(){} } class D : B{ /*override*/ void fun(){} } ´´´ case 1: interface A and class C implementing interface A: You don't need to "override" anything. You are forced to provide an implementation of the function inside the class. case 2: abstract class B and class D inheriting from it: You can but not have to provide an implementation of a function inside the abstract class. If I don't and do not provide any implementation inside D I get a linker error. Don't how this case behaves on your system. If you provide an implementation inside the abstract class, you don't have to provide any in the derived one. In any case, if you want to provide an implementation inside the derived class you have to literally "override", as in D implicit overrides are not allowed. I think there's some confusion here, because B.foo is not abstract. abstract on a class is not inherited by its methods. https://dlang.org/spec/attribute.html#abstract
Re: Abstract classes vs interfaces, casting from void*
On Saturday, 10 August 2019 at 17:46:37 UTC, Timon Gehr wrote: On 10.08.19 16:29, John Colvin wrote: Ok. What would go wrong (in D) if I just replaced every interface with an abstract class? interface A{} interface B{} class C: A,B{ } Yes, I know, I guess it wasn't clear unless you read my previous question, I said "apart from multiple inheritance".
Re: Abstract classes vs interfaces, casting from void*
On Saturday, 10 August 2019 at 10:11:15 UTC, Alex wrote: On Saturday, 10 August 2019 at 08:20:46 UTC, John Colvin wrote: On Friday, 9 August 2019 at 13:39:53 UTC, Simen Kjærås wrote: Thanks for the extra detail. Is there a solid reason to ever use an interface over an abstract class? (Other than multiple inheritance). I'm such a noob at anything related to OO. The general question is tricky, as different languages differ in details what is forced and what is allowed for abstract classes and interfaces. But roughly speaking, my opinion is: if you can/want to provide some default behavior than you are about to write an abstract class. If you are about to provide information/restriction of behavior, then this is more like an interface. Ok. What would go wrong (in D) if I just replaced every interface with an abstract class?
Re: Abstract classes vs interfaces, casting from void*
On Saturday, 10 August 2019 at 10:02:02 UTC, Antonio Corbi wrote: On Saturday, 10 August 2019 at 08:20:46 UTC, John Colvin wrote: On Friday, 9 August 2019 at 13:39:53 UTC, Simen Kjærås wrote: Thanks for the extra detail. Is there a solid reason to ever use an interface over an abstract class? (Other than multiple inheritance). I'm such a noob at anything related to OO. Hi John. One reason could be data. Abstract classes can hold data, interfaces can't. Antonio That's a reason to use an abstract class, not a reason to use an interface.
Re: Abstract classes vs interfaces, casting from void*
On Friday, 9 August 2019 at 13:39:53 UTC, Simen Kjærås wrote: Thanks for the extra detail. Is there a solid reason to ever use an interface over an abstract class? (Other than multiple inheritance). I'm such a noob at anything related to OO.
Re: Abstract classes vs interfaces, casting from void*
On Friday, 9 August 2019 at 13:39:53 UTC, Simen Kjærås wrote: We're getting into somewhat advanced topics now. This is described in the Application Binary Interface page of the documentation[0]. In short: classes and interfaces both use a vtable[1] that holds pointers to each of their methods. When we cast a class instance to an interface, the pointer is adjusted, such that the interface's vtable is the first member. Casting via `void*` bypasses this adjustment. Using `__traits(classInstanceSize)`, we can see that `C` has a size of 12 bytes, while `D` only is 8 bytes (24 and 16 on 64-bit). This corresponds to the extra interface vtable as described above. When we first cast to `void*`, no adjustment happens, because we're not casting to an interface. When we later cast the `void*` to an interface, again no adjustment happens - in this case because the compiler doesn't know what we're casting from. If we use `__traits(allMembers, C)`, we can figure out which methods it actually has, and implement those with some extra debug facilities (printf): class C : I { override void foo() { writeln("hi"); } override string toString() { writeln("toString"); return ""; } override hash_t toHash() { debug printf("toHash"); return 0; } override int opCmp(Object o) { writeln("opCmp"); return 0; } override bool opEquals(Object o) { writeln("opEquals"); return false; } } If we substitute the above in your program, we see that the `toString` method is the one being called. This is simply because it's at the same location in the vtable as `foo` is in `I`'s vtable. When casting from a class to a superclass, no pointer adjustment is needed, as the vtable location is the same for both. We can look closer at the vtable, and see that for a new subclass, additional entries are simply appended at the end: class C { void foo() {} } class D : C { void bar() {} } unittest { import std.stdio; C c = new C(); D d = new D(); writeln("Pointer to foo(): ", ().funcptr); writeln("Pointer to bar(): ", ().funcptr); writeln("Pointer to foo() in C's vtable: ", c.__vptr[5]); writeln("Pointer to foo() in D's vtable: ", d.__vptr[5]); writeln("Pointer to bar() in D's vtable: ", d.__vptr[6]); } As we see, `foo()` has the position in the vtable for both `c` and `d`, while `D`'s new `bar()` method is added as the next entry. -- Simen [0]: https://dlang.org/spec/abi.html [1]: https://en.wikipedia.org/wiki/Virtual_method_table Thanks for the extra detail. Is there a solid reason to ever use an interface over an abstract class? (Other than multiple inheritance). I'm such a noob at anything related to OO.
Re: Abstract classes vs interfaces, casting from void*
On Friday, 9 August 2019 at 13:19:14 UTC, kinke wrote: On Friday, 9 August 2019 at 12:26:59 UTC, John Colvin wrote: Why is there no "hi" between 0 and 1? Because you are treating the unadjusted object pointer as interface pointer and then call the only virtual function of that interface, in the 2nd vtbl slot (after the TypeInfo ptr). Casting a class ref to an interface offsets the pointer, so that the interface ref points to the interface vptr for that object instance. This is missing in that line, and so you are invoking the first virtual function of class C, which is some base function in `Object`. Ok, makes sense, thanks.
Abstract classes vs interfaces, casting from void*
import std.stdio; interface I { void foo(); } class C : I { override void foo() { writeln("hi"); } } abstract class AC { void foo(); } class D : AC { override void foo() { writeln("hi"); } } void main() { auto c = new C(); writeln(0); (cast(I)cast(void*)c).foo(); writeln(1); (cast(C)cast(void*)c).foo(); writeln(2); (cast(I)cast(C)cast(void*)c).foo(); auto d = new D(); writeln(3); (cast(AC)cast(void*)d).foo(); writeln(4); (cast(D)cast(void*)d).foo(); writeln(5); (cast(AC)cast(D)cast(void*)d).foo(); } This produces the output: 0 1 hi 2 hi 3 hi 4 hi 5 hi Why is there no "hi" between 0 and 1?
Re: bolts meta programming library version 1.0.0 - including the from idiom
On Tuesday, 16 July 2019 at 18:18:50 UTC, Atila Neves wrote: On Tuesday, 16 July 2019 at 00:10:19 UTC, Aliak wrote: On Monday, 15 July 2019 at 21:20:16 UTC, Atila Neves wrote: On Monday, 15 July 2019 at 11:13:10 UTC, aliak wrote: I've been using a set of meta tools for a while now, so decided to release it as 1.0.0 with a few enhancements chucked on. [...] Nice! I'm working on something similar but with a different goal. Thanks! How’s the thing similar and what’s the goal (if you don’t mind me asking)? Similar: One-stop shop for reflection unifying the disparate APIs. Goal: allow "regular" code for reflection purposes by (also) returning everything as strings. Is this related to the talk Andrei gave at a recent dconf?
Re: Compiler/Phobos/Types problem — panic level due to timing.
On Wednesday, 8 May 2019 at 11:53:34 UTC, Russel Winder wrote: On Mon, 2019-05-06 at 15:53 +, John Colvin via Digitalmars-d-learn wrote: […] pretty please show people it with UFCS: recurrence!((a, n) => a[n-1] + a[n-2])(zero, one) .dropExactly(n) .front Any particular reason for preferring this form over the original? Not big benefit in this case, very big benefit with longer chains. It reads in the order of operations, as opposed to inside out.
Re: Compiler/Phobos/Types problem — panic level due to timing.
On Monday, 6 May 2019 at 13:05:27 UTC, Russel Winder wrote: On Sunday, 5 May 2019 at 19:34:05 UTC, Nicholas Wilson wrote: On Sunday, 5 May 2019 at 19:18:47 UTC, lithium iodate wrote: [...] Yep https://run.dlang.io/is/XsLrRz works for me, https://run.dlang.io/is/KxY0e9 doesn't. Thanks people. I now have a working code. :-) pretty please show people it with UFCS: recurrence!((a, n) => a[n-1] + a[n-2])(zero, one) .dropExactly(n) .front
Re: shared - i need it to be useful
On Monday, 22 October 2018 at 00:22:19 UTC, Manu wrote: On Sun, Oct 21, 2018 at 2:35 PM Walter Bright via Digitalmars-d wrote: On 10/21/2018 2:08 PM, Walter Bright wrote: > On 10/21/2018 12:20 PM, Nicholas Wilson wrote: >> Yes, but the problem you describe is arises from implicit >> conversion in the other direction, which is not part of the >> proposal. > > It's Manu's example. Then I don't know what the proposal is. Pieces of it appear to be scattered over numerous posts, mixed in with other text, No no, they're repeated, not scattered, because I seem to have to keep repeating it over and over, because nobody is reading the text, or perhaps imaging there is a lot more text than there is. I can go look at the original post - and I have - but while it may strictly speaking contain all the information I need, the amount of time and brain power it would take for me to comprehend the consequences is pretty large. I assume you have done a lot of that work already and could save everyone a lot of time by putting together a quick document that covers some of that, with good examples. I'm not going to read {1,2,3}00 messages full of irritated bidirectional miscommunication to try and understand this unless I really have to, and I assume others feel similarly.
Re: John Regehr on "Use of Assertions"
On Monday, 3 September 2018 at 06:26:59 UTC, Jonathan M Davis wrote: Well, if that were the intention, then -release could not remove assertions from @safe code. -release does not remove bounds checking from @safe code. You have to use -boundscheck=off to disable assertions in @safe code (which is of course discouraged, since it makes the code not @safe). So, if we were to decide that assertions had to be left in for code to stay @safe, then we would have to start leaving them in in @safe code when -release is used and only compile them out with a new flag specifically for compiling out assertions in @safe code. And that would have pretty far-reaching effects given that it's very much understood right now that -release removes assertions. And personally, I'd probably use assertions a lot less if they were going to be left in with -release. So, while I think that that's a better approach that allowing @system optimizations in @safe code when assertions are removed, I can't say that I think that it's a great idea - though the folks who pretty much always want assertions enabled would probably like it (though they can already just skip -release). - Jonathan M Davis Yes, the command line interface needs to make it easy and obvious to do the right thing.
Re: John Regehr on "Use of Assertions"
On Sunday, 2 September 2018 at 02:32:31 UTC, Jonathan M Davis wrote: On Saturday, September 1, 2018 2:15:15 PM MDT Walter Bright via Digitalmars- d wrote: https://blog.regehr.org/archives/1091 As usual, John nails it in a particularly well-written essay. "ASSERT(expr) Asserts that an expression is true. The expression may or may not be evaluated. If the expression is true, execution continues normally. If the expression is false, what happens is undefined." Note the "may or may not be evaluated." We've debated this here before. I'm rather pleased that John agrees with me on this. I.e. the optimizer can assume the expression is true and use that information to generate better code, even if the assert code generation is turned off. Personally, my concern about letting the compiler optimize based on assertions has to do with whether it violates @safe. IMHO, it defeats the purpose of @safe if adding an assertion can result in @system code due to optimizations. I'm fine with it optimizing so long as the optimizations will not result in @safe code becoming @system in the case where the assertion would have failed if it were compiled in. If @safe allows @system optimizations than it isn't actually @safe, because while we don't want assertions to ever turn out to be false, they sometimes do turn out to be false, and if they're not compiled in, it's not going to be caught. That then is obviously a bug, but at least it isn't one that's going to corrupt memory (at least if it's in @safe code), but if the compiler is allowed to optimize based on the assertion to the point that the code could corrupt memory if the assertion would have failed, then that's a serious problem and a total violation of the promises made by @safe. And actually, it can't add @system optimizations even in @system code, because that completely defeats the ability of the programmer to verify the code for @safety in order to use @trusted. If the compiler can add @safe optimizations based on assertions, then that's fine with me (though I know that some others don't agree), but they have to be @safe even when the assertion would have failed if it were compiled in. If they're ever @system, then @safe isn't actually @safe. - Jonathan M Davis I believe asserts are the general case of which bounds checking is a specific instance. @safe code is only @safe if bounds-checking is enabled for @safe. void foo(int[] a) @safe { a[0] = 1; } is only really guaranteed safe if a bounds check is done, because [] is a valid array for a caller to pass. void foo(int[] a) @safe { assert(a.length == 1); a[0] = 1; } if asserts can be used as guarantees for the optimiser even when removed, this code is only @safe when asserts are enabled (because otherwise the bounds checks would be elided as they are guaranteed to pass). So, essentially we just have to treat asserts like bounds checks and @safe will work as expected. P.S. // assert debug assert(cond, msg); // assume assert(cond, msg);
Re: C++ Expected converted to idiomatic D
On Thursday, 16 August 2018 at 20:37:33 UTC, Per Nordlöw wrote: In https://www.youtube.com/watch?v=nVzgkepAg5Y Andrei describes his proposal for STL `Expected` planned to be included in C++20. Have anybody converted the C++ proposal to idiomatic D, yet? Hopefully without the pointer-legacy which unfortunately was allowed into `std:optional`. Andrei claims we should it as return types for non-throwing variants of parse() and to() in the works at https://github.com/dlang/phobos/pull/6665 I get the feeling from the talk that Andrei has some opinions about how it should be done that aren't completely in line with what has been proposed for the C++ standard.
Re: Dpp on run.dlang.io
On Saturday, 4 August 2018 at 01:27:49 UTC, Laeeth Isharc wrote: Thanks to Seb and Atila it is now very easy to show a D program just #includeing C headers. If just works. Modulo bugs. In time I am hopeful Atila will start to have more of C++ headers working too. https://run.dlang.io/is/JlH3Th Very cool. It seems like it's on by default with no option to turn it off. Is that a good idea? Also, it appears to have broken for me in the last couple of minutes. It worked initially, then I clicked the link again and ran it, got: Error: Could not execute `dmd onlineapp.d -ofonlineapp`: onlineapp.d(49): Error: no identifier for declarator `typedef` onlineapp.d(49): Error: semicolon expected, not `int` onlineapp.d(53): Error: semicolon expected, not `char` onlineapp.d(54): Error: semicolon expected, not `short` onlineapp.d(54): Error: no identifier for declarator `short` onlineapp.d(55): Error: semicolon expected, not `int` onlineapp.d(56): Error: semicolon expected, not `long` onlineapp.d(56): Error: no identifier for declarator `long` onlineapp.d(59): Error: semicolon expected, not `char` onlineapp.d(60): Error: semicolon expected, not `char` onlineapp.d(61): Error: semicolon expected, not `short` onlineapp.d(61): Error: no identifier for declarator `short` onlineapp.d(62): Error: semicolon expected, not `short` onlineapp.d(62): Error: no identifier for declarator `short` onlineapp.d(63): Error: semicolon expected, not `int` onlineapp.d(64): Error: semicolon expected, not `int` onlineapp.d(66): Error: semicolon expected, not `long` onlineapp.d(66): Error: no identifier for declarator `long` onlineapp.d(67): Error: semicolon expected, not `long` onlineapp.d(67): Error: no identifier for declarator `long` Program exited with code 1
Re: Bolts 0.4 meta programming library
On Thursday, 2 August 2018 at 08:40:55 UTC, John Colvin wrote: On Thursday, 2 August 2018 at 07:47:19 UTC, aliak wrote: Hi, just a release of a meta programming library (https://bolts.dub.pm) that has utilities that I use in personal projects, and that I find in phobos, and or in the forums. A notable difference is that functions here try to operate on any compile time entities if they can be resolved. I.e.: int i; void g0(int) {} struct S { void g1(int) {} } alias g2 = (int a) => a; static assert(isFunctionOver!(g0, int)); static assert(isFunctionOver!(S.g1, 3)); static assert(isFunctionOver!(g2, i)); And there's a "doth" super template that tries to contain most things under what I feel is a nicer api ("is" was taken, so i looked to Shakespearian gibberish :p) and also allows for easier use with meta functions: E.g.: int *pi = null; static assert( doth!3.of!int); static assert(!doth!pi.nullable); static assert( doth!((a, b, c, d) => a).functionOver!(int, int, int, int)); int i; import std.meta: allSatisfy; static assert(allSatisfy!(doth!int.of, 3, 4, int, i)); Here's an example of a gem adapted from inside the forms/phobos sources as well: alias a = AliasPack!(1, 2, 3); alias b = AliasPack!(4, 5, 6); alias c = AliasPack!(7, 8, 9); alias d = staticZip!(a, b, c); static assert(d.length == 3); static assert(d.Unpack[0].equals!(1, 4, 7)); static assert(d.Unpack[1].equals!(2, 5, 8)); static assert(d.Unpack[2].equals!(3, 6, 9)) static assert(AliasPack!(d.UnpackDeep).equals!(1, 4, 7, 2, 5, 8, 3, 6, 9)); Cheers, - Ali This looks cool. Lots of things that lots of people have reimplemented lots of times over the years, but all in one place and documented. 2 points: 1) Are you aware of this: https://github.com/dlang/phobos/blob/master/std/meta.d ? I think if a bunch of good motivating examples are given, making this public would be possible. Then everyone would be using the same one and your library would truly just be utilities. woops, pressed send too early: 2) I don't think "doth" is synonymous with "is" how you're using it. "doth" is for doing, e.g. "Methinks he doth protest too much" or "This code doth stink" is OK "Green doth a colour" or "strstr doth a function" is not OK.
Re: Bolts 0.4 meta programming library
On Thursday, 2 August 2018 at 07:47:19 UTC, aliak wrote: Hi, just a release of a meta programming library (https://bolts.dub.pm) that has utilities that I use in personal projects, and that I find in phobos, and or in the forums. A notable difference is that functions here try to operate on any compile time entities if they can be resolved. I.e.: int i; void g0(int) {} struct S { void g1(int) {} } alias g2 = (int a) => a; static assert(isFunctionOver!(g0, int)); static assert(isFunctionOver!(S.g1, 3)); static assert(isFunctionOver!(g2, i)); And there's a "doth" super template that tries to contain most things under what I feel is a nicer api ("is" was taken, so i looked to Shakespearian gibberish :p) and also allows for easier use with meta functions: E.g.: int *pi = null; static assert( doth!3.of!int); static assert(!doth!pi.nullable); static assert( doth!((a, b, c, d) => a).functionOver!(int, int, int, int)); int i; import std.meta: allSatisfy; static assert(allSatisfy!(doth!int.of, 3, 4, int, i)); Here's an example of a gem adapted from inside the forms/phobos sources as well: alias a = AliasPack!(1, 2, 3); alias b = AliasPack!(4, 5, 6); alias c = AliasPack!(7, 8, 9); alias d = staticZip!(a, b, c); static assert(d.length == 3); static assert(d.Unpack[0].equals!(1, 4, 7)); static assert(d.Unpack[1].equals!(2, 5, 8)); static assert(d.Unpack[2].equals!(3, 6, 9)) static assert(AliasPack!(d.UnpackDeep).equals!(1, 4, 7, 2, 5, 8, 3, 6, 9)); Cheers, - Ali This looks cool. Lots of things that lots of people have reimplemented lots of times over the years, but all in one place and documented. 2 points: 1) Are you aware of this: https://github.com/dlang/phobos/blob/master/std/meta.d ? I think if a bunch of good motivating examples are given, making this public would be possible. Then everyone would be using the same one and your library would truly just be utilities.
Re: Declaring a pointer to a function returning a ref
On Tuesday, 31 July 2018 at 21:29:26 UTC, Jean-Louis Leroy wrote: How do I declare a variable that contains a pointer to a function returning a reference? import std.stdio; int foo(return ref int a) { a = 42; return a; } ref int bar(return ref int a) { a = 42; return a; } void main() { int x; auto apf = writeln(typeid(apf)); // int function(return ref int)* int function(return ref int) xpf = auto apb = writeln(typeid(apb)); // int function(return ref int) ref* // int function(return ref int) ref xpb = // Error: no identifier for declarator `int function(return ref int)` // ref int function(return ref int) xpb = // Error: variable `castfunc.main.xpb` only parameters or `foreach` declarations can be `ref` } alias RefFuncT = ref int function(return ref int a); or alias RefFuncT = typeof(); then RefFuncT xpb = or you can skip that and do typeof() xpb = P.S. next time this sort of question would be more appropriate in the the Learn forum
Re: Moving druntime into the DMD repository
On Friday, 27 July 2018 at 12:04:18 UTC, Jonathan M Davis wrote: On Friday, July 27, 2018 5:03:50 AM MDT Seb via Digitalmars-d wrote: What do you think? -- - Has the dmd/druntime split being annoying you too? - Do you have a better suggestion? - Would this break your workflow in a drastic way? It would break all existing tools and scripts that are used to build the existing repos - many of which are not official tools. So, yes, it would be very annoying. That's not necessarily a good enough reason not to do it, but IMHO, it really needs to provide solid benefits to rearrange things like that for it to be worth breaking all of the existing tools that anyone uses for building dmd, druntime, and Phobos. Not necessarily. The druntime repo could just contain makefiles that forward to the dmd ones.
Re: Struct Initialization syntax
On Monday, 23 July 2018 at 16:57:20 UTC, H. S. Teoh wrote: On Mon, Jul 23, 2018 at 04:26:42PM +, Seb via Digitalmars-d wrote: tl;dr: the currently proposed syntax options are: --- struct S { int a = 2, b = 4, c = 6; } void foo() { bar(S({c: 10})); // Option 1 bar(S(c: 10)); // Option 2 bar(S{c: 10}); // Option 3 } --- So the struct-initialization DIP has been stalled for too long and I think it's time we finally get this story done. +1. I personally prefer option 2, but this might be in conflict to named arguments which we hopefully see in the near future too. Yeah. Hence, I'm leaning forward to proposing Option 1 as the recommended Option for the DIP (that's also what the PoC DMD PR implements). What's your take on this? [...] I don't like option 1 because it resembles anonymous function syntax and AA initialization syntax, but is actually neither. Seeing as we already have S s = { c : 10 }; I'd say it would be fairer to say it resembles anonymous function syntax and AA initialisation syntax, but mostly it resembles the existing struct initialisation syntax.
Re: opCmp / opEquals do not actually support partial orders
On Tuesday, 17 July 2018 at 18:21:26 UTC, H. S. Teoh wrote: As we know, when opCmp is defined for a user type, then opEquals must also be defined in order for == to work, even though in theory the compiler could translate x==y into x.opCmp(y)==0. In the past, it was argued that this was so that partial orders could be made to work, i.e., it could be the case that x and y are incomparable, then x.opCmp(y) would return 0, and x.opEquals(y) would be false. Supposedly, this would allow us to, say, model the subset relation (which is a partial order) using the comparison operators. However, this supposition is in fact false. The reason is that `<=` and `>=` *only* check the return value of opCmp(); they do not check opEquals at all. So suppose we define a Set type, and we'd like to use the comparison operators to model the subset relation. How would we define opCmp and opEquals? opEquals is obvious, of course. It's true if x and y have the same elements, false otherwise. But opCmp turns out to be a tarpit. Here's why: - If x is a (strict) subset of y, then obviously we should return -1. - If x is a (strict) superset of y, then obviously we return 1. - If x and y have the same elements, then obviously we should return 0, since we'd like x <= y and x >= y to be true when x == y is true. - If x and y are not subsets of each other, then what should we return? According to the original claim, it should also return 0, for "incomparable". However, this leads to problems: - Since `x <= y` in D means `x.opCmp(y) <= 0`, this will return TRUE when x and y are incomparable. - Similarly, `x >= y` in D means `x.opCmp(y) >= 0`, so it will also return TRUE when x and y are incomparable. - Therefore, `x <= y` cannot distinguish between x being a non-strict subset of y vs. x and y being incomparable. Similarly for `x >= y`. So we have the counterintuitive semantics that <= and >= will return true for non-comparable sets. There is no return value of opCmp for which both <= and >= will be false, as we need it to be if we are to map <= to ⊆ and >= to ⊇. Just do what std.typecons.Proxy does and return float.nan for the incomparable case.
std.experimental.allocator and const etc.
Currently the API's don't support const(void)[], e.g. import std.experimental.allocator : makeArray, theAllocator, dispose; import std.experimental.allocator.mallocator : Mallocator; void main() { const a = theAllocator.makeArray!ubyte(100); theAllocator.dispose(a); // can't call RCIAllocator.deallocate(void[] b) with const(ubyte)[] const(void)[] b = Mallocator.instance.allocate(100); Mallocator.instance.deallocate(b); // can't call Mallocator.deallocate(void[] b) with const(void)[] } Is this deliberate? It's pretty annoying.
Re: Multiple functions, same signature
On Wednesday, 11 July 2018 at 15:58:05 UTC, Luís Marques wrote: I was surprised to find out today that this compiles: void foo() {} void foo() {} void main() {} Is it a bug, or just a weird design decision? "alphaglosined" on IRC seemed to think it was a regression. Please confirm, so that I can file a bug, or understand the design decision rationale. Definitely a change, but it always compiled, it just used to fail to link https://run.dlang.io/is/b0JxD9
Re: string file = __FILE__ considered harmful (and solution)
On Wednesday, 30 May 2018 at 14:40:50 UTC, Steven Schveighoffer wrote: On 5/30/18 4:27 AM, FeepingCreature wrote: There's a very common idiom where in order to report line numbers of an error or a log line at the callsite of a function, you pass __FILE__ and __LINE__ as default parameters: void foo(string file = __FILE__, size_t line = __LINE__); What's wrong with this? Say you add a string parameter, such as void foo(string msg, string file = __FILE__, size_t line = __LINE__); foo("Hello World"); Now when you accidentally grab an old version of the library, your new code will still run, but it will believe that it's being called from file "Hello World", line 15. Not good. Luckily there's a fix. Just stick this in some common header file in your project: struct CallerInfo { string file; size_t line; } void foo(string msg, CallerInfo caller = CallerInfo(__FILE__, __LINE__)); Now you cannot accidentally invoke foo with a string, or in fact any type except another instance of CallerInfo. Awesome idea! Unfortunately, it doesn't work. The __FILE__ and __LINE__ there are not from the caller, but from the line that defines foo. See here: https://run.dlang.io/is/siz9YZ https://run.dlang.io/is/oMe7KQ Less elegant, but solves the problem of accidental argument adding (CallerFile acts as a barrier). Unfortunately, while it works in theory, in practice the compiler crashes LOL
Re: T opImplCast(T)() so we can add @disable to it?
On Thursday, 24 May 2018 at 07:37:40 UTC, Sjoerd Nijboer wrote: On Thursday, 24 May 2018 at 07:06:03 UTC, Bastiaan Veelo wrote: On Thursday, 24 May 2018 at 06:42:51 UTC, Sjoerd Nijboer wrote: On Thursday, 24 May 2018 at 01:39:56 UTC, Jonathan M Davis wrote: If you don't want an implict cast, then why did you declare an alias this? Because I wanted an inconvertible type which was exactly like the int in the example but didn't want the implicit cast. Doesn’t std.typecons.Typedef do that? https://dlang.org/phobos/std_typecons.html#Typedef I didn't know this existed. Cool! If you need more control, use std.typecons.Proxy to build your own.
Re: Online impersonation
On Thursday, 24 May 2018 at 06:32:23 UTC, Dukc wrote: On Wednesday, 23 May 2018 at 17:31:40 UTC, Steven Schveighoffer wrote: The IP address is included in the headers of the newsgroup. All of them came from the same IP. I have a filter on my thunderbird client to flag certain IPs, and his was added to the list recently. Then again, it's possible they're family members or neighbours using the same IP. How likely this is, I won't comment. I don't this is a case of inpersonation if you're right, since the aliases have not been trying to inpersonate any real, exact person. But dishonourable action nonetheless. There was a post impersonating Steven, but I can't see it now so I guess it was removed.
Re: #include C headers in D code
On Wednesday, 11 April 2018 at 18:36:56 UTC, Walter Bright wrote: On 4/11/2018 3:25 AM, Atila Neves wrote: I did the best I could having seen some macros. It's likely there are cases I've missed, or that maybe the translation in the link above doesn't work even for what it's supposed to be doing (I have no confidence about catching all the C casts for instance). If there are other cases, I'll fix them as they're encountered. It's possible some of them can't be fixed and the user will have to work around them. Right now I have a feeling it will probably be ok. Time will tell (assuming I have users!). That's right. There is no general solution. One can only look for common patterns and do those. For example, #define X 15 is a common pattern and can be reliably rewritten as: enum X = 15; If I understand it correctly, dpp doesn't do that. Instead, it runs the pre-processor on the source code, just like in C, so // test.dpp #define X 15 int foo() { return X; } becomes // test.d int foo() { return 15; } The upside of this approach: all macros just work, unless they use C (not C pre-processor, C proper) features that dpp can't handle. `sizeof(...)` is a special case that is handled in dpp.cursor.macro.translateToD and more could be added. The downside: macros can't be directly used outside .dpp files.
Re: I used to be able to use a bffer for toUTF operation, what happened ?
On Wednesday, 11 April 2018 at 12:04:24 UTC, deadalnix wrote: This used to be an option: dchar val = ...; char[4] buf; toUTF8(buf, val); Now I'm getting an error. Looking at the doc, it seems that there are only option returning a string, which I assume is allocated on the GC. Has the function moved somewhere else ? If not, what's going on ? std.utf.encode ?
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: rvalues -> ref (yup... again!)
On Monday, 26 March 2018 at 14:40:03 UTC, Atila Neves wrote: On Friday, 23 March 2018 at 22:01:44 UTC, Manu wrote: Forked from the x^^y thread... There are too many replies on this thread, addressing all the comments would take forever and pollute the thread itself. So forgive me if I say something that was covered already by someone else. AFAIK being able to bind rvalues to `ref const(T)`, only makes sense when calling C++ functions that take `const T&` (especially since that is common). I have not yet heard any other use for them. I'd be in favour of allowing it _only_ for `extern(C++)` functions. Otherwise use `auto ref` or have overloads for pass-by-value and pass-by-ref. I too, once a recent immigrant from the lands of C++, used to keep writing `ref const(T)`. I just pass by value now. C++ T&& (forwarding reference) -> D auto ref T C++ T&& (Rvalue reference) -> D T C++ const T& -> D T C++ T& -> D ref T If replacing const T& with T chafes, I understand. I used to feel that way too. It's _possible_ that would incur a penalty in copying/moving, but IME the cost is either 0, negligible, or negative (!). I'm tearing my remaining stubs of hair out trying to understand why memory copies (not talking about copy constructors) are needed when passing an rvalue to a non-ref function: https://stackoverflow.com/questions/49474685/passing-rvalue-to-non-ref-parameter-why-cant-the-compiler-elide-the-copy
Re: rvalues -> ref (yup... again!)
On Saturday, 24 March 2018 at 17:30:35 UTC, Manu wrote: On 24 March 2018 at 04:57, John Colvin via Digitalmars-d <digitalmars-d@puremagic.com> wrote: On Friday, 23 March 2018 at 22:01:44 UTC, Manu wrote: Forked from the x^^y thread... On 23 March 2018 at 12:16, Walter Bright via Digitalmars-d <digitalmars-d@puremagic.com> wrote: On 3/23/2018 11:09 AM, Manu wrote: [...] Rvalue references are not trivial and can have major unintended consequences. They're a rather ugly feature in C++, with weirdities. I doubt D will ever have them. Can you please explain these 'weirdities'? What are said "major unintended consequences"? Explain how the situation if implemented would be any different than the workaround? This seems even simpler than the pow thing to me. Rewrite: func(f()); as: { auto __t0 = f(); func(__t0); } I understand what you want, but I'm struggling to understand why it's such a huge deal. Because it makes this kind of D code that interacts with C++ objectively worse than C++, and there's no reason for it. You can't say to someone who just frustrated-ly doubled their line count by manually introducing a bunch of temporaries in a tiny function that appears to do something so simple as 'call a function', that "oh yeah, isn't it cool that you can't just call your functions anymore! isn't D cool! we should switch to D right?" It's embarrassing. I've been put in the position where I have to try and 'explain' this feature quite some number of times... they usually just give me 'the look'™; ya know, quietly wondering if I'm still sane, and all I end up with is someone who's about 95% less convinced that D is cool than they were 5 seconds beforehand. What pisses me off is that's such a pointless thing to happen, because this issue is so trivial! In my experience, people are evaluating how D will materially impact the exact same code they're already writing in C++. This is one of those ways that they will be materially impacted, and it's almost enough all on its own to cause people to dismiss the entire thing on the spot. Pretty much the best case at this phase is that the D code is exactly the same as C++. If we can trim off a few parens here and there (ufcs?), maybe remove some '::' operators (modules that don't suck), that's a huge win. The reason you want to pass by reference is for performance, to avoid copying the data at the call boundary. So there are 2 cases: an lvalue needs to be passed, or an rvalue needs to be passed. 1. The address of the lvalue is passed. 2. The rvalue is copied to a local, then the address of that local is passed. So in the rvalue case, you're not getting the performance benefit of passing by reference, because you have to copy to a local anyway. What I would do in D currently to get the same performance and API: void foo(float[32] v) { foo(v); } void foo(ref float[32] v) { ... } or void foo()(auto ref float[32] v) { ... } Can't be extern(C++), can't be virtual either (both is likely). I said before; you're talking about Scott Meyers 'universal references' as a language concept, and I'm just talking about calling a function. but I dont' get how or why. It's exactly D's solution to the problem. It doesn't solve the problem... it doesn't even address the problem. You're talking about a totally different thing >_< Auto ref allows the unnecessary copy to be avoided for lvalues and creates a temporary (as part of passing the value) for rvalues. It has downsides (virtual functions and extern(C++), but it does directly address the problem you're talking about, unless I have totally misunderstood you. Here is a small proof of concept I made to demonstrate how easy it seems to be to use `auto ref` to call a C++ virtual const& function without incurring any more copies than would happen with the same calls from C++. I'm sure it could be improved a lot, but does the basic concept match what you would need? // D source file: /// mix this in to your extern(C++) class with a list of the functions where you /// want to be able to pass rvalues to ref parameters. auto rValueRefCalls(Funcs ...)() { string ret; foreach (foo; Funcs) ret ~= `extern(D) void ` ~ __traits(identifier, foo) ~ `(Args ...)(auto ref Args args) if (__traits(compiles, (` ~ __traits(identifier, foo) ~ `)(args))) { ()(args); }`; return ret; } extern(C++) { class A { void foo(const ref int v); mixin(rValueRefCalls!foo); } A makeA(); } void main() { int x = 3; auto a = makeA(); a.foo(x); a.foo(3); } // C++ source file: #include class A { public: virtual void foo(const int& v) { printf("%d\n", v); } }; A *makeA() { return new A; }
Re: rvalues -> ref (yup... again!)
On Friday, 23 March 2018 at 22:01:44 UTC, Manu wrote: Forked from the x^^y thread... On 23 March 2018 at 12:16, Walter Bright via Digitalmars-dwrote: On 3/23/2018 11:09 AM, Manu wrote: [...] Rvalue references are not trivial and can have major unintended consequences. They're a rather ugly feature in C++, with weirdities. I doubt D will ever have them. Can you please explain these 'weirdities'? What are said "major unintended consequences"? Explain how the situation if implemented would be any different than the workaround? This seems even simpler than the pow thing to me. Rewrite: func(f()); as: { auto __t0 = f(); func(__t0); } I understand what you want, but I'm struggling to understand why it's such a huge deal. The reason you want to pass by reference is for performance, to avoid copying the data at the call boundary. So there are 2 cases: an lvalue needs to be passed, or an rvalue needs to be passed. 1. The address of the lvalue is passed. 2. The rvalue is copied to a local, then the address of that local is passed. So in the rvalue case, you're not getting the performance benefit of passing by reference, because you have to copy to a local anyway. What I would do in D currently to get the same performance and API: void foo(float[32] v) { foo(v); } void foo(ref float[32] v) { ... } or void foo()(auto ref float[32] v) { ... } What is so totally unacceptable about those solutions? I personally like the second because it scales better to multiple parameters. I know you have said it's not relevant and annoying that people bring up auto ref, but I dont' get how or why. It's exactly D's solution to the problem. There's a little more work to be done when thinking about extern(C++) and/or virtual functions, but most code for most people isn't made of virtual extern(C++) functions that take large value types can't accept the cost of copying a few lvalues.
Re: help cast
On Monday, 19 March 2018 at 11:20:05 UTC, Steven Schveighoffer wrote: Let me adjust your example a bit, and see if you still agree: auto bytes = cast(ubyte[])[55_444, 289, 1_000_000, 846, 123_456_789]; writeln(bytes); // [148, 33, 64, 78, 21] I have used cast(ubyte[]) to get ubytes as well, but I normally would do this for values that actually *could be* ubytes. for values higher than ubytes, I would not have expected implicit truncation. It's especially confusing to someone who has seen when you cast an int[] to a ubyte[], and gets the bytes for that same data. When I use cast(ubyte[]), I took it to mean "pretend this is a ubyte[] literal", not "cast each element to ubyte". I can also see this biting someone who has a long set of ubytes, and accidentally does one that is larger than 255. -Steve Raw `cast` is just nasty. It's overloaded and confusing. Wrapper template functions like `reinterpretBitsAs` can help alleviate the pain, e.g. `assert([1, 2, 3].reinterpretBitsAs!(ubyte[]).length == 12);`. I feel like C++ got it right (or just less wrong) with casts.
Re: DIP 1006 - Preliminary Review Round 1
On Tuesday, 6 March 2018 at 02:05:58 UTC, Walter Bright wrote: On 3/5/2018 2:30 PM, John Colvin wrote: This just feels bad. Adding extra failsafes for my debug program shouldn't make my release program less safe. Then use `enforce()`. So, to clarify, adding asserts to my code makes my release builds violate @safe?
Re: DIP 1006 - Preliminary Review Round 1
On Monday, 5 March 2018 at 10:30:12 UTC, Walter Bright wrote: The idea behind removal of the runtime checks is as a performance optimization done on a debugged program. It's like turning on or off array bounds checking. Many leave asserts and array bounds checking on even in released code to ensure memory safety. At a minimum, turning it off and on will illuminate just what the checks are costing you. It's at the option of the programmer. void safeCode1(int a, ref int[2] b) @safe { assert(a < 2); b[a] = 0; } So, if I compile this with `-release -O`, the compiler is free to remove the bounds-check, which will cause a buffer overrun if `a > 1`. Ok. void safeCode2(int a, ref int[2] b) @safe { b[a] = 0; } And here the compiler is *not* free to remove the bounds check. This just feels bad. Adding extra failsafes for my debug program shouldn't make my release program less safe.
Re: PackedAliasSeq?
On Thursday, 22 February 2018 at 19:26:54 UTC, Andrei Alexandrescu wrote: After coding https://github.com/dlang/phobos/pull/6192 with AliasSeq, the experience has been quite pleasurable. However, in places the AliasSeq tends to expand too eagerly, leading to a need to "keep it together" e.g. when you need to pass two of those to a template. I worked around the issue by nesting templates like this: template Merge(T...) { template With(U...) { static if (T.length == 0) alias With = U; else static if (U.length == 0) alias With = T; else static if (T[0] < U[0] || T[0] == U[0] && T[1].stringof <= U[1].stringof) alias With = AliasSeq!(T[0], T[1], Merge!(T[2 .. $]).With!U); else alias With = AliasSeq!(U[0], U[1], Merge!T.With!(U[2 .. $])); } } So instead of the unworkable Merge!(AliasSeq!(...), AliasSeq!(...)), one would write Merge!(AliasSeq!(...)).With!(AliasSeq!(...)). The problem remains for other use cases, so I was thinking of adding to std.meta this simple artifact: template PackedAliasSeq!(T...) { alias expand = AliasSeq!T; } That way, everything stays together and can be expanded on demand. Andrei Yes, I love this stuff, lots of possibilities. E.g. import std.traits : isInstanceOf; import std.meta : allSatisfy, AliasSeq, staticMap, Alias; template Pack(T ...) { alias expand = T; enum length = expand.length; } enum isPack(alias T) = isInstanceOf!(Pack, T); template Head(alias P) if (isPack!P) { alias Head = Alias!(P.expand[0]); } template Tail(alias P) if (isPack!P) { alias Tail = Pack!(P.expand[1 .. $]); } template staticZip(Seqs ...) if (Seqs.length >= 2 && allSatisfy!(isPack, Seqs)) { enum len = Seqs[0].length; static foreach (Seq; Seqs[1 .. $]) static assert(Seq.length == len, "All arguments to staticZip must have the same length"); static if (len == 0) alias staticZip = AliasSeq!(); else alias staticZip = AliasSeq!(Pack!(staticMap!(Head, Seqs)), staticZip!(staticMap!(Tail, Seqs))); }
Re: Workaround for https://issues.dlang.org/show_bug.cgi?id=18422?
On Sunday, 11 February 2018 at 15:34:07 UTC, Andrei Alexandrescu wrote: I'm trying to sketch a simple compile-time reflection system, and https://issues.dlang.org/show_bug.cgi?id=18422 is a blocker of the entire approach. My intent is to have a struct Module, which can be initialized with a module name; then: struct Module { private string name; Data[] data(); // all data declarations Function[] functions(); Struct[] structs(); Class[] classes(); Union[] unions(); Enum[] enums(); } Then each of those types carries the appropriate information. Notably, there are no templates involved, although all code is evaluated during compilation. Non-data information (types, qualifiers etc) is carried as strings. This allows for simple arrays to convey heterogeneous information such as "all functions in this module", even though their signatures are different. This makes for a simple and easy to use system for introspecting things during compilation. Clearly in order to do that some of these compile-time strings must be mixed in, which is why https://issues.dlang.org/show_bug.cgi?id=18422 is so problematic. Until we discuss a fix, are there any workarounds? Thanks, Andrei I'm not 100% sure I follow what you need, but maybe one of these two will help: `interface FunctionBase` and `class Function(string name) : FunctionBase`. or Use a templated constructor `this(string name)()`, so the fields are filled during ctfe using "template-time" information. This way the type stays the same.
Re: Channeling memory model experts...
On Wednesday, 24 January 2018 at 18:37:54 UTC, Andrei Alexandrescu wrote: ... to review https://github.com/dlang/druntime/pull/2057/. Thanks! -- Andrei Which memory model would that be? D's?
Re: LDC 1.7.0
On Saturday, 6 January 2018 at 16:25:46 UTC, German Diago wrote: - want no gc? Ok, at least there is BetterC, so if I invest myself quite a bit on D (I am the kind of programmer that likes to squeeze power out of machines, so this always means that I will not consider VM languages), I will always have. Also, it's perfectly possible to avoid most of the downsides of the GC (and keep some of the upsides) without worrying about BetterC. @nogc where you need it is great, BetterC is a much more extreme solution.
Re: Some Observations on the D Development Process
On Friday, 5 January 2018 at 04:26:25 UTC, Walter Bright wrote: I can't agree with the "just close older bugs and PRs." There's good stuff in them. Even if the PR is no good, it provides insight to someone working on a better fix. Closing it means nobody will ever be aware of it or look at it again. Relying on the original author to revive it will not work. It's similar with older bugs. They still have discussion on them that contributes valuable information and insight to anyone wishing to work on it. Closing them with no action means the information is all lost. As for autotester resources, it should be easy enough to have it skip testing any PRs that have had no activity for XXX days. I don't believe "Logan's Run" makes a good foundation for a functioning QA system. +1 A perfect project would be able to make quick decisions on PRs, but that doesn't mean closing PRs makes a better project. It's a little bit cargo-culty.
Re: toChars Bug?
On Tuesday, 12 December 2017 at 15:19:48 UTC, ketmar wrote: p.s.: but no, i am wrong. foo(-42); this is perfectly valid for `foo (uint n)`, as D converts negative ints to uints without any warnings. so no, overloads won't fit. hmm yes, it seems it is not possible.
Re: toChars Bug?
On Tuesday, 12 December 2017 at 12:49:32 UTC, ketmar wrote: see documentation: http://dpldocs.info/experimental-docs/std.conv.toChars.html "...Can be uint or ulong. If radix is 10, can also be int or long." 45 is int, not uint. so no radices except `10` will work. I think it would be possible to alter toChars such that it had a set of overloads, such that value range propagation would allow an implicit conversion here.
Re: @ctfeonly
On Thursday, 7 December 2017 at 01:21:11 UTC, Nicholas Wilson wrote: I'd like to add an attribute to indicate that the annotated function is only available at compile time so that in cases where the operation is invalid at runtime (strings and concatenation on a GPU for instance) but the result is only used at compile time (for a mixin) the compiler is free to not codegen that function. I can add this to LDC pretty easily, but does anyone else have a use for this (e.g. shrinking binary sizes for mixin heavy codebases) and would benefit having this as a standard thing? How would such a thing interact with __traits(compiles, ...) and is-expressions?
Re: gdc is in
On Saturday, 7 October 2017 at 16:46:44 UTC, Iain Buclaw wrote: On 7 October 2017 at 15:00, jmh530 via Digitalmars-dwrote: On Saturday, 7 October 2017 at 10:24:38 UTC, Joakim wrote: [...] Also, maybe it will be easier to get people to help him if they know that it's up-to-date. Why would that change anything? Because language geeks are often motivated by the new and shiny and don't like to put effort in to things that don't feel like "the future".
Re: gdc is in
On Friday, 6 October 2017 at 17:04:39 UTC, Iain Buclaw wrote: On 6 October 2017 at 17:21, jmh530 via Digitalmars-dwrote: On Friday, 6 October 2017 at 15:04:25 UTC, Joakim wrote: I assume you mean ddmd and static foreach, the mailing list post linked from my link implies it includes both. I would think this would be bigger news...I mean LDC isn't even on 2.076 yet... Really? Well, maintenance should be rather small now that the patch / diff is relatively tiny for GDC. Rebasing only against dmd/stable branch on a weekly basis or so should help things along also. A lot of (most, even?) D users ignore GDC because it's been substantially behind the cutting edge for so long. Managing to catch up and become relevant to them is big news, if you want users. To clarify: this includes Phobos, right?
Re: Proposal: Object/?? Destruction
On Wednesday, 4 October 2017 at 10:03:56 UTC, aberba wrote: Upon reading this, It triggered an idea. On Saturday, 30 September 2017 at 16:10:44 UTC, Jonathan Marler wrote: https://wiki.dlang.org/DIP88 I'd like to see DIP88 (Named Parameters) revived. Was this proposal rejected or is it just stale and needs a refresh? Named parameters can be implemented in a library, however, in my opinion they are useful enough to warrant a clean syntax with language support. I'd be willing to refresh the DIP so long as I know the idea has not already been rejected. DIP reminds me of object destruction. /* extracts success & message from returned type. Could be tuple or structure, etc. May even eliminate use of tuples for multiple return */ auto {success, message} = callVoldermortFunction(); This is concept is used in Kotlin. JavaScript es6 takes it even further (function parameters and arguments support object destruction) People often call this "destructuring" or "unpacking" to avoid confusion with destructors.
Re: Should we add `a * b` for vectors?
On Friday, 22 September 2017 at 17:11:56 UTC, Ilya Yaroshenko wrote: Should we add `a * b` to ndslice for 1d vectors? Discussion at https://github.com/libmir/mir-algorithm/issues/91 Unless it's always just simple element-wise, make it a different type. N-dimensional rectangular data structures are only sometimes matrices. Also, if you did two different types I have concerns about code that mixed the two, it would become quite unclear which ones were matrix operations and which were element-wise.
Re: code.dlang.org is offline?
On Friday, 22 September 2017 at 08:14:43 UTC, Szabo Bogdan wrote: Hi, Is there a reason why code.dlang.org is offline? Thanks, Bogdan Works for me
Re: Specifying @nogc on structs seems to have no effect
On Tuesday, 19 September 2017 at 13:11:03 UTC, Craig Black wrote: I've recently tried coding in D again after some years. One of my earlier concerns was the ability to code without the GC, which seemed difficult to pull off. To be clear, I want my programs to be garbage collected, but I want to use the GC sparingly so that the mark and sweep collections will be fast. So I want guarantees that certain sections of code and certain structs will not require the GC in any way. I realize that you can allocate on the non-GC heap using malloc and free and emplace, but I find it troubling that you still need to tell the GC to scan your allocation. What I would like is, for example, to be able to write a @nogc templated struct that guarantees that none of its members require GC scanning. Thus: @nogc struct Array(T) { ... } class GarbageCollectedClass { } void main() { Array!int intArray; // fine } @nogc has nothing to do with whether something needs scanning. It guarantees that code will never allocate with the GC or trigger a GC collection (because the only way to do that is to allocate or to call the functions in core.memory.GC, which are deliberately not marked @nogc).
Re: D std.regex is so slow
On Tuesday, 19 September 2017 at 10:14:05 UTC, Dmitry Olshansky wrote: On Tuesday, 19 September 2017 at 07:53:27 UTC, Daniel Kozak wrote: https://github.com/mariomka/regex-benchmark#performance Do you know why? Here is a code: https://github.com/mariomka/regex-benchmark/blob/master/d/benchmark.d I have try it with ldc too, but is still much slower (10x) than PHP Well I'd be interested in getting the data. The benchmark looks fine. --- Dmitry Olshansky As mentioned in the REAME: https://raw.githubusercontent.com/mariomka/regex-benchmark/master/input-text.txt
Re: Hong Kong dlang Meetup
On Monday, 4 September 2017 at 19:25:59 UTC, Jonathan M Davis wrote: Several of us from the D community will be in Hong Kong on a business trip next week (me, John Colvin, Atila Neves, and Ilya Yaroshenko), and our client, Symmetry Investments[1], has offered to sponsor a dlang meetup. We haven't decided when exactly to meet up yet, but we're looking to meet up sometime during the week of the 11th - 15th (probably on Thursday or Friday evening) and figured that we should see if anyone here was interested in showing up and would thus have some stake in when during the week it happened. The current plan is that the meetup will take place at Symmetry's main office in Chater House in Central Hong Kong. - Jonathan M Davis [1] http://symmetryinvestments.com/about-us/ Some open source dlang stuff whose developement was paid for by Symmetry: https://github.com/kaleidicassociates Of note is https://github.com/kaleidicassociates/excel-d which Atila talked about at dconf this year. We have a date and time: https://www.meetup.com//Dlang-Hong-Kong/events/243198527/?showDescription=true Sorry to those who can't make it, we really wanted to make it after the Codeaholics meetup
Re: Hong Kong dlang Meetup
On Wednesday, 6 September 2017 at 00:48:07 UTC, Lionello Lunesu wrote: Let's occupy codeaholics: https://www.meetup.com/Codeaholics/events/242640432/ Good idea. I'll be there :)
Re: Templates, D way
On Tuesday, 5 September 2017 at 12:41:45 UTC, Computermatronic wrote: On Tuesday, 5 September 2017 at 12:20:14 UTC, crimaniak wrote: [...] I find it very strange that this works, as a non-mixin template should not be able to capture the context of where it was instantiated. If you take the alias template parameters out it behaves how it should (that is an error message saying this is not accessible). https://issues.dlang.org/show_bug.cgi?id=17809
Re: Templates, D way
On Tuesday, 5 September 2017 at 11:08:57 UTC, Void-995 wrote: Hi, everyone. I'm pretty new to D and trying my first steps in it. Currently I'm trying to port some code from C/C++ with pretty weird data structures and don't like idea of making boilerplate functions for accessing sub-lists in main binary structure (lets not talk about it's design, it's from legacy thing I want to deal with and I can't change the format itself or writing a lot of additional parsing code). With hour I spent on trying I've ended with what you may see below, but I wonder if there is more pleasant variant of re-writing that template as I haven't found anything better in either books or online documentation yet: template DataList(const char[] listName, T, alias dataOffset, alias listLength) { const char[] DataList = format(q{ %s[] %s() { return (cast(%s *)(cast(byte *)() + %s))[0 .. %s]; } }, T.stringof, listName, T.stringof, dataOffset.stringof, listLength.stringof); } struct MyBinarySubStructAForA { int someIntegerFieldA; float someFloatFieldA; } struct MyBinarySubStructBForA { int someIntegerFieldB; float someFloatFieldB; } struct MyBinaryStructA { int firstSublistMembersCount; int firstSublistMembersOffset; int secondSublistMembersCount; int secondSublistMembersOffset; @property mixin(DataList!("firstSublist", MyBinarySubStructAForA, firstSublistMembersCount, firstSublistMembersOffset)); @property mixin(DataList!("secondSublist", MyBinarySubStructBForA, secondSublistMembersCount, secondSublistMembersOffset)); } ... MyBinaryStructA *binaryData = cast(MyBinaryStructA *)fileData.ptr; mixin template DataList(string listName, T, alias dataOffset, alias listLength) { mixin( q{T[] } ~ listName ~ q{() @property { return (cast(T*)(cast(ubyte*) + dataOffset))[0 .. listLength]; }} ); } struct MyBinarySubStructAForA { int someIntegerFieldA; float someFloatFieldA; } struct MyBinarySubStructBForA { int someIntegerFieldB; float someFloatFieldB; } struct MyBinaryStructA { int firstSublistMembersCount; int firstSublistMembersOffset; int secondSublistMembersCount; int secondSublistMembersOffset; mixin DataList!("firstSublist", MyBinarySubStructAForA, firstSublistMembersCount, firstSublistMembersOffset); mixin DataList!("secondSublist", MyBinarySubStructBForA, secondSublistMembersCount, secondSublistMembersOffset); }
Re: D as a Better C
On Wednesday, 23 August 2017 at 13:12:04 UTC, Mike Parker wrote: To coincide with the improvements to -betterC in the upcoming DMD 2.076, Walter has published a new article on the D blog about what it is and why to use it. A fun read. And I'm personally happy to see the love this feature is getting. I have a project I'd like to use it with if I can ever make the time for it! The blog: https://dlang.org/blog/2017/08/23/d-as-a-better-c/ Reddit: https://www.reddit.com/r/programming/comments/6viswu/d_as_a_better_c/ "D polymorphic classes will not, as they rely on the garbage collector." They do? Don't have to allocate classes on the GC heap.
Re: threads, fibers and GPU kernels
On Monday, 7 August 2017 at 08:57:35 UTC, Nicholas Wilson wrote: On Monday, 7 August 2017 at 07:38:34 UTC, Suliman wrote: Modern GPU have thousands of GPU kernels, it's far from CPU kernels, but it's interesting for me is there any chance that in future they be used in same maner as CPU kernels? Do you mean threads? Not really, they are more like SIMD lanes that together are more analogous to a CPU thread. See John Colvin's 2015/2016 DConf talks. As deadalnix reminded me after my 2016 talk, the wider picture of the GPU is SIMT, not SIMD, but from a computation point of view I find I don't need to conceptually separate the two so much. In my experience, most things that work well on GPU end up working very like SIMD on an OoO CPU when you do them right, even if they don't look like it in the code.
Re: Problem of undefined behaviour with overloaded methods and overloaded delegate's invokers
On Tuesday, 1 August 2017 at 11:07:59 UTC, knex wrote: I came across a strange thing and I am not sure if this is a bug or just an undefined behaviour of a compiler. Here is some sample code to present the case: // alias BoolFirst = void delegate(bool b, string s); alias StringFirst = void delegate(string s, bool b); class Caller { void call(BoolFirst bs) { bs(true, "text"); } void call(StringFirst sb) { sb("text", true); } } class Writer { import std.stdio; void write(bool b, string s) { writeln("bool+string:", b, "/", s); } void write(string s, bool b) { writeln("string+bool:", s, "/", b); } } void main() { new Caller().call( Writer().write); } // As you can see, I have two classes, both having two overloaded methods. Writer has some dummy printing methods for bool and string, differing with the order of the arguments, while Caller takes one of these methods as a delegate and invokes it. In main() I create objects of these classes and call Caller's call() with Writer's write(). But - as far as I understand - this call is ambiguous, and compiler does not know what should be done here: calling call/write pair for bool+string or for string+bool parameters. Nevertheless the code compiles and the program runs the fist variant. The funny thing is that swapping write() methods in the source file causes calling the second one. But OK, suppose that this is and should be treated as an undefined behaviour. What is actually disturbing here, is that casting like c.call(cast(BoolFirst) ) compiles, although is not necessary, because not casting works the same way, but casting c.call(cast(StringFirst) ) - which should help here in calling string+bool variant - does not compile, and the compiler says that "Caller.call called with argument types (void delegate(string s, bool b)) matches both (...)", which is clearly true. Moreover, swapping write() methods again causes the exact opposite behaviour: cast(StringFirst) compiles, but is useless, and cast(BoolFirst) does not compile at all. So, is this a bug, or am I just not getting something? In the first case, is there some kind of a workaround for the possibility of calling both variants (without changing the code of Caller and Writer classes)? In the last case, how should I do it properly? I am using DMD32 D Compiler v2.075.0 on Linux. looks like a bug to me. Please report at issues.dlang.org
Re: why no statements inside mixin teplates?
On Friday, 12 May 2017 at 00:20:13 UTC, سليمان السهمي (Soulaïman Sahmi) wrote: Is there a rational behind not allowing statements inside mixin templates? I know mixin does accept code containing statements, but using mixin is much uglier. so I was wondering. example use case: //- int compute(string) { return 1; } mixin template testBoilerPlate(alias arg, alias expected) { { import std.format : format; auto got = compute(arg); assert(got == expected, "expected %s got %s".format(expected, got)); } } unittest { mixin testBoilerPlate("12345", 1); mixin testBoilerPlate("00" ~ "0", 2 - 1); } // If you can put up with the limitation of what can be done in a nested function then this convention works (choose whatever names you want, A and __ are just for example): mixin template A() { auto __() { ++a; } } void main() { int a = 0; mixin A!() __; __.__; assert (a == 1); }
Re: scope pointers in @safe code
On Wednesday, 26 July 2017 at 08:20:42 UTC, Shachar Shemesh wrote: void fn(scope int* var) @safe { (*var)++; } void fn2() @safe { int a; fn(); } The above program does not compile: d.d(8): Error: cannot take address of local a in @safe function fn2 I propose that the scope keyword be activated to mean "I do not pass the pointer you gave me out of the function", which would make this code compile (as it should, as it is not doing anything unsafe). Shachar compile with -dip1000
Re: Boston D Meetup: Strawman Structs
On Sunday, 2 July 2017 at 10:35:49 UTC, Steven Schveighoffer wrote: I'll have a short presentation on a weird trick I discovered while writing some MySQL serialization code. Hope you can attend! https://www.eventbrite.com/e/d-lang-presentation-strawman-structs-tickets-35120523431 -Steve Is there a written summary of the idea? Or is there a specific point in the video someone could point me to?
Re: proposed @noreturn attribute
On Monday, 17 July 2017 at 23:01:40 UTC, Walter Bright wrote: On 7/16/2017 5:41 AM, Timon Gehr wrote: struct S{ T x; Bottom everything; } turns the entire struct into an empty type. It is therefore most natural to say that Bottom.sizeof == ∞. (It's the only choice for which S.sizeof == Bottom.sizeof.) Another way to think about it: If something of type A* converts to something of type B* without problems, then one would expect B.sizeof <= A.sizeof. This would imply that Bottom.sizeof >= size_t.max. (Because Bottom* converts to all other pointer types.) One small issue is that one needs to avoid overflow for the size of a struct that has multiple fields where one of them is of type Bottom. But if Bottom does not exist, then S doesn't exist either, and hence the < size relationship has no meaning. (Reminds me of divide by 0 discussions in calculus class.) Strictly speaking it just shouldn't have a sizeof, because sizeof is shorthand for "size of an instance of" (types don't really have sizes, how do I store the type "int" in memory?) and Bottom has no instances. Infinity - or the next best applicable thing size_t.max - is a reasonable standin for an invalid value, except that people will do silly things like `auto paddedSpace = (ReturnType!foo).sizeof + 1;` and then you're in trouble. Better to just not define it. Is there some magic that can be done where all code that makes reference to an instance of Bottom just isn't compiled? I.e. if there happens to be a situation where a function returns Bottom then all code that touches that return type is just ignored?
Re: DCompute: GPGPU with Native D for OpenCL and CUDA
On Tuesday, 18 July 2017 at 00:49:11 UTC, Nicholas Wilson wrote: On Monday, 17 July 2017 at 13:50:22 UTC, Mike Parker wrote: Nicholas Wilson has put together a blog post on his progress with DCompute, expanding on his DConf talk. I have to admit that this is one of the D projects I'm most excited about, even though I'll probably never have a need to use it. I'd love to find an excuse to do so, though! Blog: https://dlang.org/blog/2017/07/17/dcompute-gpgpu-with-native-d-for-opencl-and-cuda/ Reddit: https://www.reddit.com/r/programming/comments/6nt4ba/dcompute_gpgpu_with_native_d_for_opencl_and_cuda/ Thanks for that. Oh and @JohnColvin do you like the solution for the lambdas? I do, very nice :) You're essentially achieving what I set out to do and got stuck with, just much better.
Re: static foreach is now in github master
On Monday, 17 July 2017 at 18:14:35 UTC, Andrei Alexandrescu wrote: For those who want to play with our new static foreach feature and are willing to take the steps to building their own dmd, the feature is now merged in master: https://github.com/dlang/dmd/pull/6760 Happy hacking! Andrei or for those using homebrew: `brew install dmd --HEAD`
Re: Idiomatic FFT(W) Wrapper
On Thursday, 13 July 2017 at 12:49:40 UTC, Per Nordlöw wrote: Have anybody constructed an idiomatic D wrapper for FFTW? No, sorry, although I have used the library quite a bit in D. http://www.fftw.org/fftw3_doc/Tutorial.html#Tutorial I'm specifically concerned about - `RefCounted`-wrapping of the C structures `fftw_complex` and `fftw_plan` Sounds useful perhaps for fftw_plan. fftw_complex is just `typedef double fftw_complex[2];` so I'm not sure what you're getting at there. It's worth remembering that "wisdom" is separate from (and shared between) plans in fftw, so constructing and destroying plans can be very cheap and there's often no need to have multiple owners of a single plan. - range semantics, lazy evaluation and caching of result in stream-based architectures; `fftw_plan`, `fftw_execute` The discrete fourier transform is a global algorithm that can be lazy in input or output, but not both. I'm pretty sure the fast fourier transform algorithm for DFT cannot be lazy in either. Do you mean creating some sort of lazy short-time-fourier-transform (STFT or spectrogram or whatever other name people like)? Or are you thinking about 1-D transforms in multi-dimensional data (arguably the same thing actually)? - slicing and scope ?? - seamless interoperability with Mir (https://github.com/libmir/mir) This would definitely be nice to have For most common use-cases I find fftw is dead simple to use with the C API though. So simple that I never even bother making bindings, I just declare what I need as I need it (which in a single application has never been more than about 10 declarations).
Re: DIP 1010--Static foreach--Formal Review
On Tuesday, 11 July 2017 at 23:50:26 UTC, Steven Schveighoffer wrote: On 7/11/17 7:21 PM, H. S. Teoh via Digitalmars-d wrote: On Tue, Jul 11, 2017 at 07:18:51PM -0400, Steven Schveighoffer via Digitalmars-d wrote: [...] 3. The only controversial part I see is that `break` doesn't break from the foreach loop. While I agree with the reasoning, and support that concept, the truth is we currently have a "poor man's" static foreach using a foreach over a tuple, and that DOES break from the loop. This is a false impression. It actually does not break from the loop, but inserts a break in the generated code, and continues to unroll the rest of the loop. It's only at codegen that the subsequent iterations are detected as dead code and elided. See: https://wiki.dlang.org/User:Quickfur/Compile-time_vs._compile-time#.22static.22_foreach_does_NOT_interpret_break_and_continue Yes, I know that it still generates all the code, but the break is still interpreted as breaking out of the loop. Timon's proposal says it "does not interact with break", so I interpret that as meaning it should break out of whatever construct is surrounding the loop, not the loop itself. Currently this: foreach(j; 0 .. 2) foreach(i; AliasSeq!(0, 1)) { writeln(i); static if(i == 0) break; } will print 0 0 Whereas with my understanding, this: foreach(j; 0 .. 2) static foreach(i; 0 .. 2) { writeln(i); static if(i == 0) break; } would print 0 This seems too confusing. -Steve break inside a case inside a static foreach inside a switch is an interesting case for this sort of reasoning
Re: Why is phobos so wack?
On Sunday, 9 July 2017 at 12:56:55 UTC, FoxyBrown wrote: import string. ... return str.join(" "); gives Error: template std.array.join cannot deduce function from argument types !()(string, string) Well there's your mistake? There is no function `join` that takes (string, string). Everything after that is more detail that may or may not be useful, but reading the error message carefully, in order, is generally good enough. That said, it would be nice if the errors were less daunting somehow.
Re: proposed @noreturn attribute
On Saturday, 8 July 2017 at 12:17:57 UTC, Andrei Alexandrescu wrote: On 7/8/17 6:15 AM, Walter Bright wrote: Has anyone a better idea? Does anyone want to write a DIP for this? An attribute is fine. A more PL-minded possibility is to return a specific type: struct None { @disable this(); @disable this(this); @disable @property None init(); } None ThisFunctionExits(); The compiler detects (without having anything hardwired about the particular type "None") that the type None is impossible to create and copy/move from a function, and therefore decrees the function will never return. Andrei I wonder if some lessons from Haskell's "bottom" type would be relevant here.
Re: Compilation times and idiomatic D code
On Wednesday, 5 July 2017 at 20:32:08 UTC, Stefan Koch wrote: On Wednesday, 5 July 2017 at 20:12:40 UTC, H. S. Teoh wrote: I vaguely remember there was talk about compressing symbols when they get too long... is there any hope of seeing this realized in the near future? Yes there is. Rainer Schuetze is quite close to a solution. Which reduces the symbol-name bloat significantly. See https://github.com/dlang/dmd/pull/5855 There is still a problem with the template system as a whole. Which I am working on in my spare time. And which will become my focus after newCTFE is done. Please give consent for the D Foundation to clone you.