Re: Quality of errors in DMD
On 9/3/2016 7:35 PM, John Colvin wrote: In my experience getting a clue as to what is was the compiler didn't like is very useful. Often the only way I can find a workaround is by locating the assert in the compiler source and working out what it might possibly be to do with, then making informed guesses about what semi-equivalent code I can write that will avoid the bug. If the assert just had a little more info, it might save me a fair amount of time. If you're willing to look at the file/line of where the assert tripped, I don't see how a message would save any time at all.
Re: CompileTime performance measurement
On Sunday, 4 September 2016 at 04:31:09 UTC, Jonathan M Davis wrote: He didn't say that it _couldn't_ be done. He said that it _shouldn't_ be done. - Jonathan M Davis Yes exactly.
Re: CompileTime performance measurement
On Sunday, 4 September 2016 at 04:35:15 UTC, rikki cattermole wrote: void writeln(T...)(T args) { if (__ctfe){ debug { __ctfeWriteln(args); } } else { // ... current implementation } } That will not work. The signature is void __ctfeWriteln(const string s)
Re: CompileTime performance measurement
On 04/09/2016 4:31 PM, Jonathan M Davis via Digitalmars-d wrote: On Sunday, September 04, 2016 16:24:34 rikki cattermole via Digitalmars-d wrote: On 04/09/2016 4:14 PM, Stefan Koch wrote: On Sunday, 4 September 2016 at 04:10:29 UTC, rikki cattermole wrote: On 04/09/2016 2:08 PM, Stefan Koch wrote: On Sunday, 4 September 2016 at 02:06:55 UTC, Stefan Koch wrote: This works already. Anything placed in a debug {} block will be considered pure regardless. Opps your comment was about the debate. I would say that __ctfeWriteln and __ctfeTicksMs should not work outside of debug. Can we have writeln and writefln call into it if __ctfe is true? Just so that we have got some consistency between runtime and CTFE usage. No! writeln and __ctfeWriteln are to be regarded as completely different things. __ctfeWriteln is a debugging tool only! It should not be used in any production code. void writeln(T...)(T args) { if (__ctfe){ debug { __ctfeWriteln(args); } } else { // ... current implementation } } Are you sure? He didn't say that it _couldn't_ be done. He said that it _shouldn't_ be done. - Jonathan M Davis I wrote that code to prove that it could be used only for debugging purposes, which is Stefan's argument.
Re: CompileTime performance measurement
On Sunday, September 04, 2016 16:24:34 rikki cattermole via Digitalmars-d wrote: > On 04/09/2016 4:14 PM, Stefan Koch wrote: > > On Sunday, 4 September 2016 at 04:10:29 UTC, rikki cattermole wrote: > >> On 04/09/2016 2:08 PM, Stefan Koch wrote: > >>> On Sunday, 4 September 2016 at 02:06:55 UTC, Stefan Koch wrote: > This works already. > Anything placed in a debug {} block will be considered pure regardless. > >>> > >>> Opps your comment was about the debate. > >>> I would say that __ctfeWriteln and __ctfeTicksMs should not work outside > >>> of debug. > >> > >> Can we have writeln and writefln call into it if __ctfe is true? > >> Just so that we have got some consistency between runtime and CTFE usage. > > > > No! > > writeln and __ctfeWriteln are to be regarded as completely different > > things. > > __ctfeWriteln is a debugging tool only! > > It should not be used in any production code. > > void writeln(T...)(T args) { > if (__ctfe){ > debug { > __ctfeWriteln(args); > } > } else { > // ... current implementation > } > } > > Are you sure? He didn't say that it _couldn't_ be done. He said that it _shouldn't_ be done. - Jonathan M Davis
Re: CompileTime performance measurement
On 04/09/2016 4:14 PM, Stefan Koch wrote: On Sunday, 4 September 2016 at 04:10:29 UTC, rikki cattermole wrote: On 04/09/2016 2:08 PM, Stefan Koch wrote: On Sunday, 4 September 2016 at 02:06:55 UTC, Stefan Koch wrote: This works already. Anything placed in a debug {} block will be considered pure regardless. Opps your comment was about the debate. I would say that __ctfeWriteln and __ctfeTicksMs should not work outside of debug. Can we have writeln and writefln call into it if __ctfe is true? Just so that we have got some consistency between runtime and CTFE usage. No! writeln and __ctfeWriteln are to be regarded as completely different things. __ctfeWriteln is a debugging tool only! It should not be used in any production code. void writeln(T...)(T args) { if (__ctfe){ debug { __ctfeWriteln(args); } } else { // ... current implementation } } Are you sure?
Re: CompileTime performance measurement
On Sunday, 4 September 2016 at 04:10:29 UTC, rikki cattermole wrote: On 04/09/2016 2:08 PM, Stefan Koch wrote: On Sunday, 4 September 2016 at 02:06:55 UTC, Stefan Koch wrote: This works already. Anything placed in a debug {} block will be considered pure regardless. Opps your comment was about the debate. I would say that __ctfeWriteln and __ctfeTicksMs should not work outside of debug. Can we have writeln and writefln call into it if __ctfe is true? Just so that we have got some consistency between runtime and CTFE usage. No! writeln and __ctfeWriteln are to be regarded as completely different things. __ctfeWriteln is a debugging tool only! It should not be used in any production code.
Re: CompileTime performance measurement
On 04/09/2016 2:08 PM, Stefan Koch wrote: On Sunday, 4 September 2016 at 02:06:55 UTC, Stefan Koch wrote: This works already. Anything placed in a debug {} block will be considered pure regardless. Opps your comment was about the debate. I would say that __ctfeWriteln and __ctfeTicksMs should not work outside of debug. Can we have writeln and writefln call into it if __ctfe is true? Just so that we have got some consistency between runtime and CTFE usage.
Re: colour lib
On 04/09/2016 5:44 AM, Marco Leise wrote: Am Sat, 3 Sep 2016 16:01:26 +1200 schrieb rikki cattermole: Something[0] along this line perhaps? Overview of the choices and scope along with reasoning. [0] https://github.com/rikkimax/alphaPhobos/blob/master/source/std/experimental/graphic/image/specification.dd I have not found text about color spaces there, but it is an interesting collection of API design rationales. "If it mutates it may throw. If it doesn't mutate it shouldnt." I never thought about it that way. I was using my image specification as an example for something Manu could do for color (I use Manu's color implementation as my image library is a "test" of it).
Re: Usability of "allMembers and derivedMembers traits now only return visible symbols"
On Saturday, 3 September 2016 at 19:31:12 UTC, Jacob Carlborg wrote: That can usually be solved using .tupleof[i], but I agree. Well, .tupleof gives you a typed representation of the memory layout, to me it's something different than qualified access of fields, just a safer mean to access memory. And sure you can always memcpy data. Also introspection works on .tupleof, so it's not affected by the allMembers change and it's awkward to mix them b/c names and layout don't have a simple 1-to-1 relation.
Re: Usability of "allMembers and derivedMembers traits now only return visible symbols"
On Saturday, 3 September 2016 at 18:56:33 UTC, Dicebot wrote: Obviously serialization libraries come to mind, especially important for binary serialization because private members still affect the layout of the struct. Let me repeat that another time, private members have never been accessible by traits. That's the main reasoning this change was based upon.
Re: Usability of "allMembers and derivedMembers traits now only return visible symbols"
On Saturday, 3 September 2016 at 17:23:53 UTC, Basile B. wrote: On Saturday, 3 September 2016 at 16:52:50 UTC, Martin Nowak wrote: On Tuesday, 30 August 2016 at 22:24:12 UTC, Ali Çehreli wrote: I don't agree with the current solution: Well let's come up with a better solution then. Let's start by finding some proper use-cases that require introspection on private members w/o having access to them. In my user library, the serialization is based on the @Set and @Get UDAs. Typically there would be a setter (a public method) and no getter (i.e the data is read directly either from a protected or private variable). A public setter for private members is weird, but well. As a library template can't read private fields, you don't need the @Get attribute. The introspection is used to create a property descriptor. What does that mean? You're creating a property in the serialised data? Defining de-/serialize methods in the class/struct, e.g. with a mixin template would be the cleaner and more obvious approach IMO.
Re: Usability of "allMembers and derivedMembers traits now only return visible symbols"
On Sunday, 4 September 2016 at 03:21:05 UTC, Stefan Koch wrote: While I do understand, that there could be a potential performance when private members could be changed around because they are not visible form outside. I fail to see how we would take advantage of that without breaking our object-model. It's mostly about linkage of private methods.
Re: Usability of "allMembers and derivedMembers traits now only return visible symbols"
On Saturday, 3 September 2016 at 17:57:08 UTC, Jonathan M Davis wrote: I do get the feeling that too much of what we do with features like this is ad-hoc without really designing things up front, and then we keep having to tweak stuff as we go along in ways that aren't always particularly nice. That's not true, there was DIP22, and it explicitly mentions how traits should work. The problem that was new and very hard to see, is that allowing traits to bypass visibility checks means we either can't replace access checks, must allow access of private members (w/ the cost tradeoffs mentioned in the announce thread), or come up with a different solution. While it's fairly straightforward to skip visibility checks during traits lookups, I couldn't come up with a useful use-case while writing tests for that implementation, and after some more thought came up with the allMembers change.
Re: Usability of "allMembers and derivedMembers traits now only return visible symbols"
On Sunday, 4 September 2016 at 03:14:18 UTC, Martin Nowak wrote: It didn't slip, but I wish Walter had at least stated his opinion on the PR before merging. My thinking is that the plebes should be able to access things via the object.member syntax by obeying the usual visibility rules. But __traits(allMembers, T) should be the reflection backdoor that gives the savvy users total access, at the obvious cost of an awkward syntax. As explained several times here and in the announce thread, private members have never been accessible, other than introspecting attributes, and making them accessible comes with a performance cost and a fairly big language change. So the real question is, why do we need introspection without access, and can we handle that few cases with mixin templates. If we really need introspection of private members than we might need to go back to the drawing board and modify the visibility concept introduced with DIP22. While I do understand, that there could be a potential performance when private members could be changed around because they are not visible form outside. I fail to see how we would take advantage of that without breaking our object-model.
Re: Usability of "allMembers and derivedMembers traits now only return visible symbols"
On Saturday, 3 September 2016 at 20:40:57 UTC, Andrei Alexandrescu wrote: On 9/3/16 7:57 PM, Jonathan M Davis via Digitalmars-d wrote: Previously __traits(allMembers, T) listed _all_ members, whereas now it wil only list the ones that are accessible. The same for __traits(derivedMembers, T). So, they'll still give you the private members if you use them inside the module in question but not elsewhere. That... doesn't sound good. I wonder how such important changes slip by Walter and myself unnoticed. It didn't slip, but I wish Walter had at least stated his opinion on the PR before merging. My thinking is that the plebes should be able to access things via the object.member syntax by obeying the usual visibility rules. But __traits(allMembers, T) should be the reflection backdoor that gives the savvy users total access, at the obvious cost of an awkward syntax. As explained several times here and in the announce thread, private members have never been accessible, other than introspecting attributes, and making them accessible comes with a performance cost and a fairly big language change. So the real question is, why do we need introspection without access, and can we handle that few cases with mixin templates. If we really need introspection of private members than we might need to go back to the drawing board and modify the visibility concept introduced with DIP22.
Re: Quality of errors in DMD
On Saturday, 3 September 2016 at 22:48:27 UTC, Walter Bright wrote: On 9/3/2016 6:20 AM, Adam D. Ruppe wrote: On Saturday, 3 September 2016 at 12:12:34 UTC, Walter Bright wrote: Except that asserts are checking for compiler bugs, not diagnostics on user code. Except that in the real world, it is an irrelevant distinction because you have stuff to do and can't afford to wait on the compiler team to actually fix the bug. If nothing else, you'd like to know where it is so you can hack around the bug by changing your implementation. Users are not equipped to do that, and we shouldn't raise false expectations that they can. Developers who are equipped to that are able and willing to build the compiler from source with debugging turned on. Really, what possible use is there to an end user for an assert that unhelpfully printed out a message that the register allocator failed? There's nothing "user friendly" about a such a message. I understand if you want to say producing better error messages in the compiler is a pain and you have other priorities, but surely you accept that they are valuable for this reason if nothing else. No, I do not accept that, and I've had no trouble working around asserts I've gotten from other vendors' compilers, despite there being no message other than the compiler failed. Most of the time it's the last change made that triggered it. Back up one change and do something different. In my experience getting a clue as to what is was the compiler didn't like is very useful. Often the only way I can find a workaround is by locating the assert in the compiler source and working out what it might possibly be to do with, then making informed guesses about what semi-equivalent code I can write that will avoid the bug. If the assert just had a little more info, it might save me a fair amount of time.
Re: CompileTime performance measurement
On Sunday, 4 September 2016 at 02:06:55 UTC, Stefan Koch wrote: This works already. Anything placed in a debug {} block will be considered pure regardless. Opps your comment was about the debate. I would say that __ctfeWriteln and __ctfeTicksMs should not work outside of debug.
Re: CompileTime performance measurement
On Sunday, 4 September 2016 at 02:03:49 UTC, sarn wrote: On Sunday, 4 September 2016 at 01:53:21 UTC, Stefan Koch wrote: Pragma msg can only print compiletime constants. While __ctfeWriteln can print state while doing CTFE. Thanks, that makes a lot of sense. Just to check, it prints to standard error, right? Also, the issue of non-deterministic compilation reminds me of the debate about allowing logging statements in pure functions. Maybe there's a similar answer (i.e., making it only work in some kind of debug mode). This works already. Anything placed in a debug {} block will be considered pure regardless.
Re: CompileTime performance measurement
On Sunday, 4 September 2016 at 01:53:21 UTC, Stefan Koch wrote: Pragma msg can only print compiletime constants. While __ctfeWriteln can print state while doing CTFE. Thanks, that makes a lot of sense. Just to check, it prints to standard error, right? Also, the issue of non-deterministic compilation reminds me of the debate about allowing logging statements in pure functions. Maybe there's a similar answer (i.e., making it only work in some kind of debug mode).
Re: CompileTime performance measurement
On Sunday, 4 September 2016 at 01:44:40 UTC, sarn wrote: On Sunday, 4 September 2016 at 00:04:16 UTC, Stefan Koch wrote: I recently implemented __ctfeWriteln. Sounds like pragma msg. How does it compare? https://dlang.org/spec/pragma.html#msg Pragma msg can only print compiletime constants. While __ctfeWriteln can print state while doing CTFE. Example int fn(int n) { import std.conv; __ctfeWriteln((n-10).to!string); return n; } static assert(fn(22)); will print 12; whereas int fn(int n) { import std.conv; pragma(msg, n.to!string); return n; } will tell you that the symbol n is not avilable at compiletime
Re: CompileTime performance measurement
On Sunday, 4 September 2016 at 00:04:16 UTC, Stefan Koch wrote: I recently implemented __ctfeWriteln. Sounds like pragma msg. How does it compare? https://dlang.org/spec/pragma.html#msg
Re: Quality of errors in DMD
On 9/3/2016 5:09 PM, Stefan Koch wrote: Perhaps the best error message would be "Please post this as a bug to bugzilla." That's fine with me, and Dicebot made a PR to do it.
Re: ADL
On 9/3/2016 5:36 PM, Timon Gehr wrote: Does not work. Local overloads are not supported. Yeah, you're right, should have tested that: void abc(int); void def(uint); void foo() { alias func = abc; alias func = def; // error func(1); } fails. Pushing it out a level works: void abc(int); void def(uint); template foo() { alias func = abc; alias func = def; void foo() { func(1); } } void main() { foo(); }
Re: ADL
On 9/3/2016 4:46 PM, Andrei Alexandrescu wrote: On 9/4/16 12:28 AM, Walter Bright wrote: On 9/3/2016 1:43 PM, Andrei Alexandrescu wrote: On 9/3/16 10:43 PM, Walter Bright wrote: On 9/3/2016 8:34 AM, Manu via Digitalmars-d wrote: And if either module doesn't have an instance of func? static if (traits(compiles, ModuleOf!T.func)) alias func = ModuleOf!T.func; What's an elegant way to encapsulate this as a stutter-free one-liner? -- Andrei using a template and mixing it in "Show me the mo^H^Hcode." template foo(T) { static if (traits(compiles, ModuleOf!T.func)) foo = "alias func = " ~ ModuleOf!T.func ~ ";"; else foo = ""; } mixin(foo!T);
Re: ADL
On 03.09.2016 13:24, Walter Bright wrote: Something like: void foo(T,U)(T t, U u) { alias func = ModuleOf!T.func; alias func = ModuleOf!U.func; func(t, u); } Does not work. Local overloads are not supported.
Re: DIP1001: DoExpression
On 03.09.2016 17:28, Andrei Alexandrescu wrote: What's wrong with: auto seq(T...)(auto ref T vals) { return vals[$ - 1]; } - The name (I'd expect that function to return vals). - Does not work if one or more arguments is of type 'void'. (Arguably that's just a language misdesign.)
Re: CompileTime performance measurement
On Sunday, 4 September 2016 at 00:08:14 UTC, David Nadlinger wrote: Please don't. This makes CTFE indeterministic. Please elaborate on why this would have a negative impact ? if someone chooses to use a symbol called __ctfeTicksMs they shoud know what they are doing. To write performance tests, just measure compilation of a whole program (possibly with -o-). The variance due to the startup/shutdown overhead can trivially be controlled by just executing the CTFE code in question often enough. That will only allow you to tell how much overall ctfe-time you spent. It will not allow you to pinpoint and optimize the offenders.
Re: Quality of errors in DMD
On Saturday, 3 September 2016 at 22:53:25 UTC, Walter Bright wrote: On 9/3/2016 3:05 PM, Ethan Watson wrote: In the cases I've been bringing up here, it's all been user code that's been the problem *anyway*. Regardless of if the compiler author was expecting code to get to that point or not, erroring out with zero information is a bad user experience. Nobody is suggesting that asserts are a good user experience. I've asserted (!) over and over that this is why asserts have a high priority to get fixed. Adding more text to the assert message is not helpful to end users. Perhaps the best error message would be "Please post this as a bug to bugzilla."
Re: CompileTime performance measurement
On Sunday, 4 September 2016 at 00:04:16 UTC, Stefan Koch wrote: Based on that experience I have now implemented another pseudo function called __ctfeTicksMs. […] Please tell me what you think. Please don't. This makes CTFE indeterministic. To write performance tests, just measure compilation of a whole program (possibly with -o-). The variance due to the startup/shutdown overhead can trivially be controlled by just executing the CTFE code in question often enough. — David
CompileTime performance measurement
Hi Guys. I recently implemented __ctfeWriteln. Based on that experience I have now implemented another pseudo function called __ctfeTicksMs. That evaluates to a uint representing the number of milliseconds elapsed between the start of dmd and the time of semantic evaluation of this expression. This does allow meaningful compiletime performance tests to be written. spanning both CTFE and template-incitations timeings. Please tell me what you think.
Re: ADL
On 9/4/16 12:28 AM, Walter Bright wrote: On 9/3/2016 1:43 PM, Andrei Alexandrescu wrote: On 9/3/16 10:43 PM, Walter Bright wrote: On 9/3/2016 8:34 AM, Manu via Digitalmars-d wrote: And if either module doesn't have an instance of func? static if (traits(compiles, ModuleOf!T.func)) alias func = ModuleOf!T.func; What's an elegant way to encapsulate this as a stutter-free one-liner? -- Andrei using a template and mixing it in "Show me the mo^H^Hcode."
Re: Usability of "allMembers and derivedMembers traits now only return visible symbols"
On 9/3/16 11:54 PM, Jacob Carlborg wrote: On 2016-09-03 22:40, Andrei Alexandrescu wrote: That... doesn't sound good. I wonder how such important changes slip by Walter and myself unnoticed. Here's the PR that introduced the change: https://github.com/dlang/dmd/pull/6078 Thanks. -- Andrei
Re: Quality of errors in DMD
On 9/3/2016 3:05 PM, Ethan Watson wrote: In the cases I've been bringing up here, it's all been user code that's been the problem *anyway*. Regardless of if the compiler author was expecting code to get to that point or not, erroring out with zero information is a bad user experience. Nobody is suggesting that asserts are a good user experience. I've asserted (!) over and over that this is why asserts have a high priority to get fixed. Adding more text to the assert message is not helpful to end users.
Re: Quality of errors in DMD
On 9/3/2016 6:20 AM, Adam D. Ruppe wrote: On Saturday, 3 September 2016 at 12:12:34 UTC, Walter Bright wrote: Except that asserts are checking for compiler bugs, not diagnostics on user code. Except that in the real world, it is an irrelevant distinction because you have stuff to do and can't afford to wait on the compiler team to actually fix the bug. If nothing else, you'd like to know where it is so you can hack around the bug by changing your implementation. Users are not equipped to do that, and we shouldn't raise false expectations that they can. Developers who are equipped to that are able and willing to build the compiler from source with debugging turned on. Really, what possible use is there to an end user for an assert that unhelpfully printed out a message that the register allocator failed? There's nothing "user friendly" about a such a message. I understand if you want to say producing better error messages in the compiler is a pain and you have other priorities, but surely you accept that they are valuable for this reason if nothing else. No, I do not accept that, and I've had no trouble working around asserts I've gotten from other vendors' compilers, despite there being no message other than the compiler failed. Most of the time it's the last change made that triggered it. Back up one change and do something different.
Re: Quality of errors in DMD
On 9/3/2016 6:14 AM, Jacob Carlborg wrote: What kind of issue due you see with trying to print some form of information when an assertion fails? Because it's useless to anyone but the compiler devs, and it adds cruft to the compiler. And even worse than useless, it confuses the user into thinking it is a meaningful message. It is not. It is a compiler bug. It has meaning only to the compiler developer, and hence does not belong in the *user* interface. Let's not pretend the user can debug the compiler. I would have certainty help me the times I've hacked on the compiler and triggered an assertion. Why shouldn't the developers working on the compiler getting as much help as possible? The compiler code is littered with helpful debugging printf's that are commented out. I use them all the time. There is no purpose to them if one is not actively working on the compiler.
Re: ADL
On 9/3/2016 3:35 AM, Walter Bright wrote: That isn't how it works in C++. It's done right up front in finding the candidates for overloading, not as a fallback. That statement is incorrect. It's used as a fallback in C++. I had forgotten.
Re: ADL
On 9/3/2016 1:43 PM, Andrei Alexandrescu wrote: On 9/3/16 10:43 PM, Walter Bright wrote: On 9/3/2016 8:34 AM, Manu via Digitalmars-d wrote: And if either module doesn't have an instance of func? static if (traits(compiles, ModuleOf!T.func)) alias func = ModuleOf!T.func; What's an elegant way to encapsulate this as a stutter-free one-liner? -- Andrei using a template and mixing it in
Re: Usability of "allMembers and derivedMembers traits now only return visible symbols"
On Saturday, 3 September 2016 at 21:54:24 UTC, Jacob Carlborg wrote: Here's the PR that introduced the change: https://github.com/dlang/dmd/pull/6078 I'm certainly not going to upgrade to the next DMD if this change is retained. allMembers not returning all members makes introspection entirely useless when it comes to Binderoo. The wrong conclusions were made from that bug to begin with it seems. allMembers should return all members. getProtection should report on the protection of a symbol *regardless* of whether getMember will succeed or not (this is currently why I have my PrivacyOf workaround - to stop the compiler crashing when using a template instead of a mixin template to do introspection). getMember itself, well, I'd honestly prefer if there was a way to get to members without having to correlate with .tupleof as it will simplify Binderoo code. The .tupleof method doesn't help me when it comes to introspecting private/protected functions for C++ binding.
Re: Quality of errors in DMD
On Saturday, 3 September 2016 at 13:20:37 UTC, Adam D. Ruppe wrote: Except that in the real world, it is an irrelevant distinction because you have stuff to do and can't afford to wait on the compiler team to actually fix the bug. If nothing else, you'd like to know where it is so you can hack around the bug by changing your implementation. I'm sure every long time D programmer (and likely C++ if you've been in a long time, I have hit many bugs in g++ too) has hit a compiler bug and "fixed" it by using some different approach in their user code. Exactly this. If a compiler bug stops someone from working in a production environment because there's no information about why the bug occured, the semantic difference between a compiler bug and a user code bug means precisely nothing to the end user. It does mean that they're losing hours of work while the problem is clumsily attempted to be diagnosed. In the cases I've been bringing up here, it's all been user code that's been the problem *anyway*. Regardless of if the compiler author was expecting code to get to that point or not, erroring out with zero information is a bad user experience. This also gets compounded in environments where you can't just grab the hottest DMD with a compiler bug fix. Before too long, our level builders will be using D as their scripting language. They need a stable base. We can't do something like upgrade a compiler during a milestone week, so upgrades will be scheduled (I'm planning on going with even-numbered releases). A fix for the compiler bug is no good if I can't ship it out for months. The only way to go there is to implement workarounds until such time an upgrade is feasible. (Side note: There's zero chance of me upgrading to the next DMD if it retains the altered allMembers functionality) These kinds of problems are likely to be compounded when D reaches critical mass. It's all well and good to tell people in the enthusiast community "Run to get a repro case and make a bug". If a problem can't be easily googlable or understandable from the error reporting, then that's a turn off for a wider audience.
dependency analysis for makefile construction
Are there any FOSS tools for doing dependency analysis of (e.g.) all the d files in a directory, to let you know when a .o file needs to be regenerated? This presumably would depend mostly on the import statements (including import of any file to be used in string construction, as in 'auto my_string = import("my_file");'). My guess is there must be, because one of the big deals about d is the more regular syntax it offers to make compiler building more reliable. (I'm using gdc, and building with gnumake.) TIA for any info! dan
Re: Usability of "allMembers and derivedMembers traits now only return visible symbols"
On 2016-09-03 22:40, Andrei Alexandrescu wrote: That... doesn't sound good. I wonder how such important changes slip by Walter and myself unnoticed. Here's the PR that introduced the change: https://github.com/dlang/dmd/pull/6078 -- /Jacob Carlborg
Re: Usability of "allMembers and derivedMembers traits now only return visible symbols"
On Saturday, 3 September 2016 at 20:54:19 UTC, Andrei Alexandrescu wrote: On 9/3/16 10:50 PM, Basile B. wrote: On Saturday, 3 September 2016 at 20:40:57 UTC, Andrei Alexandrescu wrote: Martin, any chance we can undo this change to the language? The problem is deeper. If he undoes the change then what will happen again is that the results of allMembers won't be usable by the other traits, e.g getMember, because them are still limited by the protection attributes. Where are the past discussions on this matter? -- Andrei The change in 2.071.2-beta3 to allMembers is designed to fix https://issues.dlang.org/show_bug.cgi?id=15907 which happens because of a __traits(getMember,...) on the results of a __traits(allMembers,...).
[Issue 15442] Eponymous template restrictions should be documented
https://issues.dlang.org/show_bug.cgi?id=15442 github-bugzi...@puremagic.com changed: What|Removed |Added Status|NEW |RESOLVED Resolution|--- |FIXED --
[Issue 15442] Eponymous template restrictions should be documented
https://issues.dlang.org/show_bug.cgi?id=15442 --- Comment #1 from github-bugzi...@puremagic.com --- Commits pushed to master at https://github.com/dlang/dlang.org https://github.com/dlang/dlang.org/commit/190da42b6d6fe0abc205fda66a1d0e4086c5cf5c fix issue 15442 - Eponymous template restrictions should be documented https://github.com/dlang/dlang.org/commit/9e638f110b96b02253f239c99288e93a71bb6bbf Merge pull request #1456 from BBasile/issue-15442 fix issue 15442 - Eponymous template restrictions should be documented --
Re: ADL
On 9/3/16 11:31 AM, Manu via Digitalmars-d wrote: > In any case, these difficulties are the consequence of trying to write C++ > code in D. You've told me this before, and I find it kind of offensive every time you do, since I've been programming D for like 7 years now, and I definitely don't code D like C++. If anything, I have a strong tendency to code C++ like D, and that has lead to a lot of interesting changes in my C++ style. I'm tired of these sorts of dismissals. You insist that I'm not a 'real' D programmer, or something to that effect. There's really no need to take offense here. We have a bit of a mimosa culture of easily bruised egos it seems. As the joke goes: "You take offense too easily." "I can't believe you just said that!" It's hard to not see your view as coming straight from the "I want to speak Italian by replacing English words with Italian words" box. * It hypothesizes that one entire style of design is completely impossible because it lacks one obscure feature from C++. * Vast evidence to the contrary is ignored. * The fact that the feature is problematic and controversial even within C++ circles is also neglected. * The lack of said feature is regarded as an utter disaster and no workaround is even close to cutting the mustard. * A language change is a must; no library solution would ever be acceptable. For the most part this is a Pop a level up and figure what the needed accomplishment is, so other routes than the ADL bottleneck are possible. Let's approach this together like a problem that has a solution within D, and let's make that solution accessible comfortably. Two apocryphal anecdotes: Koenig invented the eponymous lookup as a consequence to the fact that namespaces broke the "Hello, world" program (something to do with cout and endl being migrated to namespace std), which surprised the inner circles of C++ the way putting mentos in coke surprises the unwary. Namespaces are an unusually poorly designed feature of C++, not second even to exceptions. By that time significant work had been invested in defining and implementing namespaces, so going back wasn't quite an option. ADL was hailed as a horrible hack but a lifesaving one. Compilers have been slow to implement ADL, partly because essentially it meant breaking a lookup algorithm that was relatively orderly and DWIM, and replace it with a patchwork of special cases. The community has since learned to live with the odd idioms that make code work with the new rules. Second anecdote: Scott Meyers had an infamous talk on C++ in which the leitmotif was "What does f(x) mean?" Scott asks the question in the beginning to which the obvious response is "Call function f passing it argument x". By the time his talk is done, the horrified audience realizes they have no idea what f(x) means and where it goes. Andrei
Re: ADL
On 9/3/2016 9:24 AM, Andrei Alexandrescu wrote: On 9/3/16 5:57 PM, Manu via Digitalmars-d wrote: It's not a problem I've ever had. A problem you didn't know you have. It's a classic C++ conundrum combining theory and practice. One thing I've noticed in my years of programming and helping others with their code is that one can use a feature for decades, over and over, but are only using it in a certain specific way. One is lulled into thinking that it works in the general case because one is not aware that one's usage is constrained. Someone else comes along, uses it slightly differently, and oops. "But I always took the left fork!" :-) It bites me all the time.
Re: ADL
On 9/3/2016 6:22 AM, ZombineDev wrote: I agree that it's not a template issue. It's more of a modules vs namespaces issue. I think the lack of ADL is not a problem in C# because everyone can (and everyone does) extend an existing namespace, so most user's of LINQ algorithms just slap a `using System.Linq` on top of the file without caring in exactly which file the functionality they're using is coming from. Hmm, that explanation could be it. I'm not very familiar with LINQ.
Re: ADL
On 9/3/2016 8:51 AM, Manu via Digitalmars-d wrote: This is exactly the difference between std.algorithm, and what I was trying to express as an algorithm that 'does work'. It's not the business of the API for the user to supply the work to do (ie, via lambda); the function is meant to do the work, which means it needs to call other functions. There are no lambdas to be seen in this situation. This is purely a stylistic issue. I, on the other hand, think lambdas are a superior design, as ADL lookups never sat well with me because it can be quite difficult for the user to figure out where 'func' is coming from. (Besides, I showed how other scopes can be imported based on a type, and then things can be looked up in those scopes, and UFCS applied.) I still think that's unnecessarily complicated, and multiple arguments leads to static if-ing and __traits(compiles,...). The fact the user needs to intervene at all is already too much. I already showed how your previous objection to this could be folded away inside a nice template. Apparently I need to stress again, this is a *core value proposition of D*... It's presented as "this is modern D code", and yet it's awkward and requires careful handling or you get hard to understand name-resolution issues. As mentioned, I don't see anything hard to understand about it - it makes it clear to the reader where names are coming from. ADL pulls names in from who knows where. UFCS *is* modern D. Algorithms and ranges *is* modern D. Seriously, this is the style that modern D aspires to, and it doesn't 'just work'. There should be ear-piercing alarms and flashing red everywhere. This comes up for me frequently, yet ADL has never caused me a single moments trouble, in 15+ years. I didn't even know ADL existed until I started running into this problem in D and then wondered to myself why I never encountered the same issue in C++. It worked so seamlessly and intuitively, I didn't even know it was there. I don't care if the solution is ADL like C++, or something else that works, just that this problem is real; it's a massive fly in the ointment of modern D style, and I don't think it's acceptable. It needs a seamless solution, not manual intervention at every case. D depends on this so much more than C++ does. You've used ADL for 15 years. You're obviously very comfortable with it. I suggest trying out using lambdas enough to feel comfortable with it before deciding that ADL is better. New coding styles are rarely comfortable right off the bat.
Re: Fallback 'catch-all' template functions
Am Sat, 3 Sep 2016 02:56:16 -0700 schrieb Walter Bright: > On 9/3/2016 2:43 AM, Manu via Digitalmars-d wrote: > > This is interesting. Can you explain how that works? > > > Specializations are preferred over non-specializations, and T:T is the > identity > specialization. Pretty cool, I'll try that next time I write templated overload sets! -- Marco
Re: Usability of "allMembers and derivedMembers traits now only return visible symbols"
On 9/3/16 10:50 PM, Basile B. wrote: On Saturday, 3 September 2016 at 20:40:57 UTC, Andrei Alexandrescu wrote: Martin, any chance we can undo this change to the language? The problem is deeper. If he undoes the change then what will happen again is that the results of allMembers won't be usable by the other traits, e.g getMember, because them are still limited by the protection attributes. Where are the past discussions on this matter? -- Andrei
Re: Fallback 'catch-all' template functions
Am Sat, 3 Sep 2016 14:24:13 +0200 schrieb Andrei Alexandrescu: > On 9/3/16 7:29 AM, Manu via Digitalmars-d wrote: > > On 3 September 2016 at 11:38, Andrei Alexandrescu via Digitalmars-d > > wrote: > >> On 9/3/16 2:41 AM, Manu via Digitalmars-d wrote: > >>> > >>> On 3 September 2016 at 00:18, Xinok via Digitalmars-d > >>> wrote: > > > In the past, I have suggested using the "default" keyword to specify a > fallback function of this kind. I think it's a useful pattern for generic > algorithms that have optimized variants on specific types for > performance. > > void f(T)(T t) if(isSomething!T) {} > void f(T)(T t) if(isSomethingElse!T) {} > void f(T)(T t) default {} > >>> > >>> > >>> It's an interesting idea... flesh out a DIP? > >> > >> > >> We're better off without that. -- Andrei > > > > Then we need a decent way to do this. > > Use static if inside the function. The entire notion of "call this > function if you can't find something somewhere that works" is > questionable. -- Andrei This notion is what drives template specializations in D: char foo(T)(T t) { return '?'; } // Call this if nothing else matches char foo(T : int)(T t) { return 'i'; } // Call this for ints char foo(T : string)(T t) { return 's'; } // Call this for strings Granted it's a bit more fuzzy and talks about "more specialized", but it is ultimately the same as a hard fallback when foo(3.4) is called. UFCS functions are also only invoked if there is no method with that name on the type, or any type reachable through "alias this" or opDot and there is no opDispatch on said types accepting that name. However questionable the notion is, it is common in D today. Static if also wont work in cases where the signature needs to be different, like overloads of opCast, where one returns bool and is const and another returns a different view on the same thing by ref and is inout. opCast(T:bool) would be unclean, as it also matches types T with a boolean 'alias this'. One can also imagine that some overloads want to take their arguments by value while others take it by ref. -- Marco
Re: Usability of "allMembers and derivedMembers traits now only return visible symbols"
On Saturday, 3 September 2016 at 20:40:57 UTC, Andrei Alexandrescu wrote: Martin, any chance we can undo this change to the language? The problem is deeper. If he undoes the change then what will happen again is that the results of allMembers won't be usable by the other traits, e.g getMember, because them are still limited by the protection attributes.
Re: ADL
On 9/3/16 10:43 PM, Walter Bright wrote: On 9/3/2016 8:34 AM, Manu via Digitalmars-d wrote: And if either module doesn't have an instance of func? static if (traits(compiles, ModuleOf!T.func)) alias func = ModuleOf!T.func; What's an elegant way to encapsulate this as a stutter-free one-liner? -- Andrei
Re: ADL
On 9/3/2016 8:34 AM, Manu via Digitalmars-d wrote: And if either module doesn't have an instance of func? static if (traits(compiles, ModuleOf!T.func)) alias func = ModuleOf!T.func;
Re: ADL
On 9/3/16 10:29 PM, Walter Bright wrote: On 9/3/2016 6:04 AM, Andrei Alexandrescu wrote: This only works with the respective modules do define `func`. We need something that conditionally plants the symbol depending on whether the module defines it or not. -- Andrei That's where __traits(compiles, ...) comes in. It can be encapsulated in another template. Yah. That we need to plant in the standard library. -- Andrei
Re: Usability of "allMembers and derivedMembers traits now only return visible symbols"
On 9/3/16 7:57 PM, Jonathan M Davis via Digitalmars-d wrote: Previously __traits(allMembers, T) listed _all_ members, whereas now it wil only list the ones that are accessible. The same for __traits(derivedMembers, T). So, they'll still give you the private members if you use them inside the module in question but not elsewhere. That... doesn't sound good. I wonder how such important changes slip by Walter and myself unnoticed. My thinking is that the plebes should be able to access things via the object.member syntax by obeying the usual visibility rules. But __traits(allMembers, T) should be the reflection backdoor that gives the savvy users total access, at the obvious cost of an awkward syntax. The fact that __traits(allMembers, T) compiles in all cases and has DIFFERENT semantics depending on whether T is in the same vs. a different module is the deadly sign of poor language design. Martin, any chance we can undo this change to the language? Andrei
Re: ADL
On 9/3/2016 9:01 AM, Manu via Digitalmars-d wrote: Right, and it also has to not conflict with possible local definitions, or instances supplied by imports in the local namespace. Ie, the module where T came from is *an additional* place to look, not *the* place to look. I expect that local definitions may exist for things like generic fallbacks, or primitive/builtin type implementations. 1. 'alias func = ...;' also works to bring in local definitions to an even footing with the other alias func statements. 2. Due to recent changes to import lookup rules, imports are searched if locals do not satisfy the lookup. 3. You can use traits(compiles, ...) to not insert the names in the local scope if it already can be looked up. So I believe you're good to go.
Re: ADL
On 9/3/16 7:38 PM, Tobias Müller wrote: Andrei Alexandrescuwrote: On 9/3/16 7:08 PM, Tobias M wrote: On Saturday, 3 September 2016 at 16:33:07 UTC, Andrei Alexandrescu wrote: I see. This is a matter orthogonal to DbI - introspection should be able to figure out whether a member can be found, or a nonmember if the design asks for it. I wouldn't like "tricking" DbI into thinking a member is there when there isn't. -- Andrei The problem I see with DbI is rather that the user of a function thinks that an optional constraint is satisfied, while in reality it isn't, due to a non-obvious lookup/visibility problem. At some point there's a need to RTFM. -- Andrei Is there one for DbI? (Sincere question) Not yet. We have the allocators body of work, but that's too niche to serve as a general example. I think std.experimental.checkedint will be the canonical example on how to do DbI. I'll propose a blog post to Mike. -- Andrei
Re: ADL
On 9/3/2016 6:04 AM, Andrei Alexandrescu wrote: This only works with the respective modules do define `func`. We need something that conditionally plants the symbol depending on whether the module defines it or not. -- Andrei That's where __traits(compiles, ...) comes in. It can be encapsulated in another template.
Poodinis (DI framework) 7.0.0 released
Poodinis is a dependency injection framework for the D programming language. It is heavily inspired by the Spring Framework. New in this release is constructor injection. Whenever the dependency container resolves a class it creates an instance of that class. During creation it attempts to resolve dependencies defined in that class' constructor and passes them when created. This is done fully automated without the need of UDAs. Of course member-based injection is still available too. Besides constructor injection, all previously deprecated code has been removed in this version. For more info, see the changelog. You can find the project at: Github: https://github.com/mbierlee/poodinis D package registry: http://code.dlang.org/packages/poodinis
[Issue 16457] std.regex postprocesses ctRegex every time at runtime
https://issues.dlang.org/show_bug.cgi?id=16457 --- Comment #2 from greenify--- thanks a lot for looking at this so quickly :) > The problem is enum re = ... line. Enum means ctRegex!`((c)(s)?)?ti` is > copy-pasted at the place of usage, basically reconstructing regex on each > loop iteration b/c compile-time version can't cache compiled patterns. Okay that makes partially sense, but to give some background I found this problem because the D changelog generation crashed on my machine (16G) while parsing a 300kB log file. The dummy file is a dustmited & reduced version of the changelog generator: https://github.com/dlang/tools/blob/master/changed.d#L77 And using `enum ... = ctRegex!...` seems to be a very common pattern: https://github.com/search?q=enum+ctRegex=Code=%E2%9C%93 > Replace enum with static and all should be good. Unfortunately I can still observe the same behavior, I also tried to move ctRegex to the matchAll. Funnily with regex I don't get this allocation / out of memory -problem. FYI static immutable doens't work: foo.d(10): Error: template std.regex.matchAll cannot deduce function from argument types !()(string, immutable(StaticRegex!char)), candidates are: /usr/include/dlang/dmd/std/regex/package.d(860):std.regex.matchAll(R, RegEx)(R input, RegEx re) if (isSomeString!R && is(RegEx == Regex!(BasicElementOf!R))) /usr/include/dlang/dmd/std/regex/package.d(868):std.regex.matchAll(R, String)(R input, String re) if (isSomeString!R && isSomeString!String) /usr/include/dlang/dmd/std/regex/package.d(875):std.regex.matchAll(R, RegEx)(R input, RegEx re) if (isSomeString!R && is(RegEx == StaticRegex!(BasicElementOf!R))) --
[Issue 16457] std.regex postprocesses ctRegex every time at runtime
https://issues.dlang.org/show_bug.cgi?id=16457 Dmitry Olshanskychanged: What|Removed |Added CC||dmitry.o...@gmail.com --- Comment #1 from Dmitry Olshansky --- (In reply to greensunny12 from comment #0) > Consider the following program, it will crash as it allocates _a lot_ of > memory before the garbage can be collected. > > void main() > { > import std.regex; > enum re = ctRegex!(`((c)(s)?)?ti`); > import core.memory : GC; > string text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit"; > > foreach (i; 0..500_000_000) > { > if (auto m = matchAll(text, re)) {} > //if (i % 1_000_000) > //GC.collect(); > } > } > > On my machine (16G) it crashes at about 5M iterations. > The GC profile finds two hotspots (here 2M iterations): > > 204800 200 uint[] D main > std/regex/internal/parser.d:1607 > 18400 200 std.regex.internal.ir.Bytecode[] D main > std/array.d:852 > > (the latter is insertInPlace) > > After looking at the code it seems pretty weird, because "postprocess" > should be called while constructing the RegEx and once only. The problem is enum re = ... line. Enum means ctRegex!`((c)(s)?)?ti` is copy-pasted at the place of usage, basically reconstructing regex on each loop iteration b/c compile-time version can't cache compiled patterns. Replace enum with static and all should be good. --
Re: Usability of "allMembers and derivedMembers traits now only return visible symbols"
On 2016-09-03 20:56, Dicebot wrote: Obviously serialization libraries come to mind, especially important for binary serialization because private members still affect the layout of the struct. That can usually be solved using .tupleof[i], but I agree. -- /Jacob Carlborg
Re: Usability of "allMembers and derivedMembers traits now only return visible symbols"
On 2016-09-03 17:50, Martin Nowak wrote: It will, e.g. having getMember bypass protection means vibe.d would now serialize private members https://github.com/rejectedsoftware/vibe.d/blob/c1180791de61d0f8c9bfb584c2551a5b64627e32/source/vibe/internal/meta/traits.d#L146. Until now getMember was just a DotIdExp (i.e. `T.indent`/`var.ident`), so it was used to test whether sth. can be accessed. Without looking at the how the rest of the code works, it already checks if a member is public or not [1]. Or are you saying that "isPublicMember" would return a different value? [1] https://github.com/rejectedsoftware/vibe.d/blob/c1180791de61d0f8c9bfb584c2551a5b64627e32/source/vibe/internal/meta/traits.d#L159 -- /Jacob Carlborg
Re: Beta D 2.071.2-b3
On 2016-09-03 18:02, Martin Nowak wrote: Why not just use `__traits(getAttributes, var.tupleof[0])`? I've already updated my code to use the above. When I first implemented it, it was not possible to use a "tupleof expression" as argument to __traits(getAttributes). -- /Jacob Carlborg
Re: Usability of "allMembers and derivedMembers traits now only return visible symbols"
On 09/03/2016 07:52 PM, Martin Nowak wrote: > On Tuesday, 30 August 2016 at 22:24:12 UTC, Ali Çehreli wrote: >> I don't agree with the current solution: > > Well let's come up with a better solution then. > Let's start by finding some proper use-cases that require introspection > on private members w/o having access to them. Obviously serialization libraries come to mind, especially important for binary serialization because private members still affect the layout of the struct. signature.asc Description: OpenPGP digital signature
[Issue 15625] Internal error: backend/elfobj.c 1014
https://issues.dlang.org/show_bug.cgi?id=15625 --- Comment #5 from Mark Isaacson--- I'll work on getting one at the next hackathon. --
Re: Usability of "allMembers and derivedMembers traits now only return visible symbols"
On Saturday, September 03, 2016 19:30:54 Andrei Alexandrescu via Digitalmars-d wrote: > On 9/3/16 6:39 PM, Andrej Mitrovic via Digitalmars-d wrote: > > On 9/3/16, Martin Nowak via Digitalmars-dwrote: > >> On Wednesday, 31 August 2016 at 13:12:30 UTC, Adam D. Ruppe wrote: > >>> Ugh, it really should just give everything and have getMember > >>> bypass it. That won't even break any code! > >> > >> It will, e.g. having getMember bypass protection means vibe.d > >> would now serialize private members > > > > Then just add a check in vibe.d itself to avoid serializing private > > members. You can still call getProtection on the symbol and skip > > serializing it. > > > > Alternatively you can use UDAs so you can mark which fields should or > > shouldn't be serializible. For example > > https://github.com/msgpack/msgpack-d/blob/6046808c2e678e27cb2e2d9314241c36 > > 1a6fd0ae/src/msgpack/attribute.d#L21 > > > > The bottom line is with restricting access to private symbols you have > > no choice on the matter, while allowing access lets you specialize > > whether to ignore the symbols or not. > > I didn't follow this closely, but clearly we need some means to access > private members for introspection purposes. I hope we don't paint > ourselves out of that corner. -- Andrei Well, that certainly seems to be exactly what we're doing with the changes that Ali is complaining about. Previously __traits(allMembers, T) listed _all_ members, whereas now it wil only list the ones that are accessible. The same for __traits(derivedMembers, T). So, they'll still give you the private members if you use them inside the module in question but not elsewhere. I would have thought that the way to handle this would be to have them list all members regardless of access level and then to have code check for the access level if it cares. I would have thought that doing stuff like looking at private symbols would be perfectly okay with no errors or deprecation warnings and that it would just be _accessing_ the symbol that would be disallowed and would require you to check for in code that used introspection. But clearly, there must be something that I misunderstand here, because that's not at all where this seems to be going. I do get the feeling that too much of what we do with features like this is ad-hoc without really designing things up front, and then we keep having to tweak stuff as we go along in ways that aren't always particularly nice. And this particular change seems to just be a reaction to problems that we ran into with changing how imports work. And maybe it's the right choice, but it sure doesn't seem like it. - Jonathan M Davis
Re: ADL
ZombineDevwrote: > So what? C#'s generics are less flexible than C++ and D templates. > The point is that C#'s lookup does not consider only the > implemented interfaces, but also falls back to extensions > methods. If C# had ADL, > the compiler would also look for extension methods in the > namespace > of the type (in non-generic methods, when the type is "known"), > although the user of the type may not have imported the namespace. ADL wouldn't change anything if you don't cast to a specific type, and if you do, that part of the code is not generic anymore. >>> Sum is implemented in that stupid way, because unlike C++, in >>> C# operators need to be implemented as static methods, so you >>> can't abstract them with an interface. If they were instance >>> methods, you could implement them outside of the class as >>> extension methods and there would be no need to write a >>> distinct method for each type. Here's an example: >>> http://rextester.com/PQFPC46087 >>> The only thing missing is syntax sugar to forward the '+' >>> operator to 'Add' in my example. >> >> With runtime reflection you can do almost anything... That's >> circumventing the type system and doesn't disprove anything. > > There's no circumventing the type system. `typeof(obj)` is barely > even reflection. You can do this with regular cast or using the > `is` expression (http://rextester.com/CXGNK69048). I used > `typeof` just because it could yield better performance. Typecasting *is* circumventing the type system.
Re: colour lib
Am Sat, 3 Sep 2016 16:01:26 +1200 schrieb rikki cattermole: > On 03/09/2016 12:17 PM, Manu via Digitalmars-d wrote: > ...snip... > > > I think the presence of all this colour space information as type > > arguments should nudge users in the right direction. They'll be all > > "I've never seen this parameter before..." and google it... maybe. > > I don't think it's the std lib doco's job to give users a lesson in > > colour theory...? :/ :D Just a short paragraph. "Note: The common sRGB color space used in computer screens or JPEGs from digicams does not evenly distribute brightness along the pixel values. Multiplying an sRGB pixel by two, wont double its intensity! To perform accurate image manipulations, you are advised to always convert to a high precision linear color-space like [insert name] first. More information on the history of sRGB and the formulas used can be found here: https://www.w3.org/Graphics/Color/sRGB; I believe sRGB is the only color-space that you "feel" you are already familiar with as a computer person, because you see and use it all the time. If I really wanted to make you pull your hair I'd say: "Man this NormalizedInt stuff would so benefit from MMX. Imagine we don't use float but ushort as linear RGB value and then use a single PADDUSW to add two colors." > Something[0] along this line perhaps? > > Overview of the choices and scope along with reasoning. > > [0] > https://github.com/rikkimax/alphaPhobos/blob/master/source/std/experimental/graphic/image/specification.dd I have not found text about color spaces there, but it is an interesting collection of API design rationales. "If it mutates it may throw. If it doesn't mutate it shouldnt." I never thought about it that way. -- Marco
Re: ADL
On Saturday, 3 September 2016 at 17:05:35 UTC, Tobias M wrote: On Saturday, 3 September 2016 at 16:32:16 UTC, ZombineDev wrote: No you're wrong. There's no need for interfaces or for generic constraints. It's not static vs duck typing. It's just a method lookup issue. See for yourself: http://rextester.com/GFKNSK99121 Ok, Interfaces and other generic methods with compatible constraints. But in the end you cannot do much without any interface constraints except writing out to the console as you do in the example. But the main point still holds, name lookup is only done at definition time, not at instantiation time. That's why you can only call generic methods. Overloads don't work. So what? C#'s generics are less flexible than C++ and D templates. The point is that C#'s lookup does not consider only the implemented interfaces, but also falls back to extensions methods. If C# had ADL, the compiler would also look for extension methods in the namespace of the type (in non-generic methods, when the type is "known"), although the user of the type may not have imported the namespace. Sum is implemented in that stupid way, because unlike C++, in C# operators need to be implemented as static methods, so you can't abstract them with an interface. If they were instance methods, you could implement them outside of the class as extension methods and there would be no need to write a distinct method for each type. Here's an example: http://rextester.com/PQFPC46087 The only thing missing is syntax sugar to forward the '+' operator to 'Add' in my example. With runtime reflection you can do almost anything... That's circumventing the type system and doesn't disprove anything. There's no circumventing the type system. `typeof(obj)` is barely even reflection. You can do this with regular cast or using the `is` expression (http://rextester.com/CXGNK69048). I used `typeof` just because it could yield better performance. I mean, it even "works" for types that cannot be added at all, by just returning a default value... ? Sorry, I don't understand, what's the problem?
Re: ADL
Andrei Alexandrescuwrote: > On 9/3/16 7:08 PM, Tobias M wrote: >> On Saturday, 3 September 2016 at 16:33:07 UTC, Andrei Alexandrescu wrote: >>> I see. This is a matter orthogonal to DbI - introspection should be >>> able to figure out whether a member can be found, or a nonmember if >>> the design asks for it. I wouldn't like "tricking" DbI into thinking a >>> member is there when there isn't. -- Andrei >> >> The problem I see with DbI is rather that the user of a function thinks >> that an optional constraint is satisfied, while in reality it isn't, due >> to a non-obvious lookup/visibility problem. > > At some point there's a need to RTFM. -- Andrei Is there one for DbI? (Sincere question)
Re: ADL
On 9/3/16 7:08 PM, Tobias M wrote: On Saturday, 3 September 2016 at 16:33:07 UTC, Andrei Alexandrescu wrote: I see. This is a matter orthogonal to DbI - introspection should be able to figure out whether a member can be found, or a nonmember if the design asks for it. I wouldn't like "tricking" DbI into thinking a member is there when there isn't. -- Andrei The problem I see with DbI is rather that the user of a function thinks that an optional constraint is satisfied, while in reality it isn't, due to a non-obvious lookup/visibility problem. At some point there's a need to RTFM. -- Andrei
Re: ADL
On 9/3/16 7:00 PM, vit wrote: On Saturday, 3 September 2016 at 13:04:30 UTC, Andrei Alexandrescu wrote: On 9/3/16 1:24 PM, Walter Bright wrote: On 9/3/2016 3:12 AM, Walter Bright wrote: If you are still determined to use it, you can use: __traits(compiles, ...) like you would SFINAE in C++ to select which of the modules from the argument types selects a function that compiles. Eh, I realized it's simpler than that. Based on the code I already presented, each argument can be used to generate an import for its corresponding version of the function. Then, overloading rules apply and it works. Something like: Something like: void foo(T,U)(T t, U u) { alias func = ModuleOf!T.func; alias func = ModuleOf!U.func; func(t, u); } This only works with the respective modules do define `func`. We need something that conditionally plants the symbol depending on whether the module defines it or not. -- Andrei perhaps this: auto adl(string fn, T, Args...)(auto ref T x, auto ref Args args) Perhaps too surgical (although nice to have as an option). We need something that pulls the symbol for all purposes. -- Andrei
Re: Usability of "allMembers and derivedMembers traits now only return visible symbols"
On 9/3/16 6:39 PM, Andrej Mitrovic via Digitalmars-d wrote: On 9/3/16, Martin Nowak via Digitalmars-dwrote: On Wednesday, 31 August 2016 at 13:12:30 UTC, Adam D. Ruppe wrote: Ugh, it really should just give everything and have getMember bypass it. That won't even break any code! It will, e.g. having getMember bypass protection means vibe.d would now serialize private members Then just add a check in vibe.d itself to avoid serializing private members. You can still call getProtection on the symbol and skip serializing it. Alternatively you can use UDAs so you can mark which fields should or shouldn't be serializible. For example https://github.com/msgpack/msgpack-d/blob/6046808c2e678e27cb2e2d9314241c361a6fd0ae/src/msgpack/attribute.d#L21 The bottom line is with restricting access to private symbols you have no choice on the matter, while allowing access lets you specialize whether to ignore the symbols or not. I didn't follow this closely, but clearly we need some means to access private members for introspection purposes. I hope we don't paint ourselves out of that corner. -- Andrei
Re: DIP1001: DoExpression
On 9/3/16 6:39 PM, Cauterite wrote: On Saturday, 3 September 2016 at 16:28:15 UTC, Andrei Alexandrescu wrote: This is a terrible argument. It has "why not" all over it. -- Andrei Sorry, it's my first time proposing a language feature. My DConf 2016 talk has a few considerations on what makes a good proposal. We consider it an antipattern to list reasons for why not adding a feature. It's like on a date - if nothing went wrong, that doesn't mean anything went right :o). -- Andrei
Re: ADL
Tobias Mwrote: > On Saturday, 3 September 2016 at 16:32:16 UTC, ZombineDev wrote: >> Sum is implemented in that stupid way, because unlike C++, in >> C# operators need to be implemented as static methods, so you >> can't abstract them with an interface. If they were instance >> methods, you could implement them outside of the class as >> extension methods and there would be no need to write a >> distinct method for each type. Here's an example: >> http://rextester.com/PQFPC46087 >> The only thing missing is syntax sugar to forward the '+' >> operator to 'Add' in my example. > > With runtime reflection you can do almost anything... That's > circumventing the type system and doesn't disprove anything. > I mean, it even "works" for types that cannot be added at all, by > just returning a default value... It's not runtime reflection, sorry about that. But Add claims to be generic but it's actually just a list of special cases. It compiles for all types but only works for some. And even worse, for types that actually do support addition but are not in the list it silently does the wrong thing. You cannot do the same in a truly generic way.
Re: Usability of "allMembers and derivedMembers traits now only return visible symbols"
On Saturday, 3 September 2016 at 16:52:50 UTC, Martin Nowak wrote: On Tuesday, 30 August 2016 at 22:24:12 UTC, Ali Çehreli wrote: I don't agree with the current solution: Well let's come up with a better solution then. Let's start by finding some proper use-cases that require introspection on private members w/o having access to them. In my user library, the serialization is based on the @Set and @Get UDAs. Typically there would be a setter (a public method) and no getter (i.e the data is read directly either from a protected or private variable). The introspection is used to create a property descriptor. But because of the protection attributes I have to mix the introspection features (== a template) in each aggregate that declares properties and in each descendant class that declare new properties. Class Foo { mixin features f; // so that the private stuff are visible private: @Get int _field; public @Set void field(int value){} this() {f.analyze!Foo;} } class Bar: Foo { mixin features f; // so that the private stuff are visible private: @Get int _otherfield; public @Set void otherfield(int value){} this() {f.analyze!Bar;} } while I could do, with the omniscient traits: Class Foo { private: @Get int _field; public @Set void field(int value){} this(this T)() { features.analyze!T; } } Class Bar: Foo { private: @Get int _otherfield; public @Set void otherfield(int value){} } no need to re-mix the features for each derived class...
Re: phobos unit tests
On Saturday, September 03, 2016 16:56:08 ZombineDev via Digitalmars-d wrote: > You can just enable the unittests for a single instance that you > know for sure that it will be used. For example: > 1) > https://github.com/dlang/phobos/blob/v2.071.2-b3/std/experimental/ndslice/sl > ice.d#L808 > > 2) > https://github.com/dlang/phobos/blob/v2.071.2-b3/std/experimental/ndslice/sl > ice.d#L947 So, in order to avoid having the unit tests compiled into the code of anyone who uses your template, you have to create a special version identifier that you use with your unit test build and your documentation build, and then you version the tests within the template with that version. And in order to avoid having the unit test compiled into every instantiation of that template during your test, you have to also put it in a static if for a specific instantiation? Sure, that's feasible, but that's getting _ugly_. - Jonathan M Davis
Re: Using OpenGL
On Saturday, 3 September 2016 at 16:07:52 UTC, Mike Parker wrote: On Saturday, 3 September 2016 at 16:01:34 UTC, Mike Parker wrote: The following compiles, runs, and shows the triangle. It's the code you posted above with the corrected call to glBufferData along with more D style (as I would write it anyway) and less C. The dynamic array! Thank you so much, I changed that on another file and it finally drew the triangle. And I ran your code and it works brilliantly. I should now be in a comfortable position to digest all this information now. Can't thank you enough. One thing I overlooked. In lines where a variable is both declared and initialized, like this one: GLFWwindow* window = glfwCreateWindow(...); I normally let the compiler use type inference as I did in the manifest constant declarations: auto window = glfwCreateWindow(...); IMO, when you're dealing with long or ugly type names, it makes the code look cleaner. Yeah, it is nicer to read. Now I wonder if I can load shaders from separate files (à la http://www.opengl-tutorial.org/beginners-tutorials/tutorial-2-the-first-triangle/).
Re: ADL
On Saturday, 3 September 2016 at 16:32:16 UTC, ZombineDev wrote: No you're wrong. There's no need for interfaces or for generic constraints. It's not static vs duck typing. It's just a method lookup issue. See for yourself: http://rextester.com/GFKNSK99121 Ok, Interfaces and other generic methods with compatible constraints. But in the end you cannot do much without any interface constraints except writing out to the console as you do in the example. But the main point still holds, name lookup is only done at definition time, not at instantiation time. That's why you can only call generic methods. Overloads don't work. Sum is implemented in that stupid way, because unlike C++, in C# operators need to be implemented as static methods, so you can't abstract them with an interface. If they were instance methods, you could implement them outside of the class as extension methods and there would be no need to write a distinct method for each type. Here's an example: http://rextester.com/PQFPC46087 The only thing missing is syntax sugar to forward the '+' operator to 'Add' in my example. With runtime reflection you can do almost anything... That's circumventing the type system and doesn't disprove anything. I mean, it even "works" for types that cannot be added at all, by just returning a default value...
Re: ADL
On Saturday, 3 September 2016 at 16:33:07 UTC, Andrei Alexandrescu wrote: I see. This is a matter orthogonal to DbI - introspection should be able to figure out whether a member can be found, or a nonmember if the design asks for it. I wouldn't like "tricking" DbI into thinking a member is there when there isn't. -- Andrei The problem I see with DbI is rather that the user of a function thinks that an optional constraint is satisfied, while in reality it isn't, due to a non-obvious lookup/visibility problem.
Re: ADL
On Saturday, 3 September 2016 at 13:04:30 UTC, Andrei Alexandrescu wrote: On 9/3/16 1:24 PM, Walter Bright wrote: On 9/3/2016 3:12 AM, Walter Bright wrote: If you are still determined to use it, you can use: __traits(compiles, ...) like you would SFINAE in C++ to select which of the modules from the argument types selects a function that compiles. Eh, I realized it's simpler than that. Based on the code I already presented, each argument can be used to generate an import for its corresponding version of the function. Then, overloading rules apply and it works. Something like: Something like: void foo(T,U)(T t, U u) { alias func = ModuleOf!T.func; alias func = ModuleOf!U.func; func(t, u); } This only works with the respective modules do define `func`. We need something that conditionally plants the symbol depending on whether the module defines it or not. -- Andrei perhaps this: auto adl(string fn, T, Args...)(auto ref T x, auto ref Args args){ import std.traits : moduleName, hasMember; import std.meta : Filter, NoDuplicates, staticMap; import std.array : join; static if(hasMember!(T, fn)){ mixin("return x." ~ fn ~ "(args);"); } else{ enum toImportString(T) = "import " ~ moduleName!(T) ~ " : " ~ fn ~ ";"; enum hasModuleFN(T) = __traits(compiles, mixin("(){" ~ toImportString!T ~ "}")); alias Types = Filter!(hasModuleFN, NoDuplicates!(T, Args)); static assert(Types.length, "no property '" ~ fn ~ "' for type '" ~ __traits(identifier, T)~ "'"); mixin([staticMap!(toImportString, Types),"return " ~ fn ~ "(x, args);"].join("\n")); } }
Re: phobos unit tests
On Saturday, 3 September 2016 at 15:58:51 UTC, Jonathan M Davis wrote: On Saturday, September 03, 2016 07:48:14 H. S. Teoh via Digitalmars-d wrote: > In any case, for now, I never put non-generic unit tests in > templates, and I reject PRs that have them. Sure, having to > copy-paste your examples sucks, but it doesn't affect the > code of everyone who uses the template, whereas ddoc-ed unit > tests do. [...] Actually you don't need to copy-paste your examples, which IMO is a bad idea to begin with. Just version out the non-generic unittests when compiling user code, and you can have the best of both worlds. And you still have the problem that all of those unit tests will be compiled into every instantiation of the template that's part of your unittest build. So, you end up with longer build times and longer run times for your unit tests. I agree that copy-pasting sucks, but it's what we had to do before with had ddoc-ed unit tests, and I still think that it's better than resulting in all of the additional copies of the tests being compiled in and run - especially if the project isn't small. - Jonathan M Davis No need for that - see my other post: http://forum.dlang.org/post/psrgjdlvsiukkuhre...@forum.dlang.org
Re: phobos unit tests
On Saturday, 3 September 2016 at 15:54:31 UTC, Jonathan M Davis wrote: On Saturday, September 03, 2016 15:06:33 Andrei Alexandrescu via Digitalmars-d wrote: On 9/3/16 5:36 AM, Manu via Digitalmars-d wrote: > This document: https://wiki.dlang.org/Contributing_to_Phobos > > States: "Avoid unittest in templates (it will generate a new > unittest for each instance) - put your tests outside" Actually that's a good thing, sometimes you do want to run a unittest for each instantiation. Sometimes, sure. But usually not. > Sounds reasonable, but then I realised that most of my unit > tests are documenting unittests... this recommendation is in > conflict with the documentation standards... who wins? Just version it only for the documentation. Then the tests won't be run unless your documentation build is also your unittest build, and they frequently can't be the same - e.g. when something differs between operating systems, and you have a separate D_Ddoc or StdDdoc block so that you can have proper documentation without requiring that the documentation be built on all systems and potentially being able to document what exists on each system. For instance, the supported clock types vary quite a bit across operating systems, so the core.time.ClockType enum has different values on different systems and version(CoreDdoc) is used so that the documentation can list them all and list the consistently across systems. You could add some sort of version identifier that's specific to your build that you use for your unittest builds (similar to how Phobos has StdDdoc separate from D_Ddoc), but even if you do that, you still have the problem of the non-generic unit tests within a template being compiled into every instantiation of the template that's part of your unittest build, and all of those tests will get run, increasing both the build times and the time it takes to run the unit tests. - Jonathan M Davis You can just enable the unittests for a single instance that you know for sure that it will be used. For example: 1) https://github.com/dlang/phobos/blob/v2.071.2-b3/std/experimental/ndslice/slice.d#L808 2) https://github.com/dlang/phobos/blob/v2.071.2-b3/std/experimental/ndslice/slice.d#L947
Re: Usability of "allMembers and derivedMembers traits now only return visible symbols"
On Tuesday, 30 August 2016 at 22:24:12 UTC, Ali Çehreli wrote: I don't agree with the current solution: Well let's come up with a better solution then. Let's start by finding some proper use-cases that require introspection on private members w/o having access to them.
Re: DIP1001: DoExpression
On Saturday, 3 September 2016 at 16:03:39 UTC, Jonathan M Davis wrote: So, instead of having the return statement which everyone knows to look for and is easy to grep for, you want to add a way to return _without_ a return statement? I think you've misunderstood. Even with DoExpressions, the only way to return from a function without a return statement is in a lambda '=>' function.
Re: Usability of "allMembers and derivedMembers traits now only return visible symbols"
On 9/3/16, Martin Nowak via Digitalmars-dwrote: > On Wednesday, 31 August 2016 at 13:12:30 UTC, Adam D. Ruppe wrote: >> Ugh, it really should just give everything and have getMember >> bypass it. That won't even break any code! > > It will, e.g. having getMember bypass protection means vibe.d > would now serialize private members Then just add a check in vibe.d itself to avoid serializing private members. You can still call getProtection on the symbol and skip serializing it. Alternatively you can use UDAs so you can mark which fields should or shouldn't be serializible. For example https://github.com/msgpack/msgpack-d/blob/6046808c2e678e27cb2e2d9314241c361a6fd0ae/src/msgpack/attribute.d#L21 The bottom line is with restricting access to private symbols you have no choice on the matter, while allowing access lets you specialize whether to ignore the symbols or not.
Re: DIP1001: DoExpression
On Saturday, 3 September 2016 at 16:28:15 UTC, Andrei Alexandrescu wrote: This is a terrible argument. It has "why not" all over it. -- Andrei Sorry, it's my first time proposing a language feature.
Re: DIP1001: DoExpression
On Saturday, 3 September 2016 at 16:10:16 UTC, Jonathan M Davis wrote: .. and from what I've seen, it seems to be the case that just about only the only folks who read it correctly are the ones who use it frequently .. You know what else is easy to misread? { x; y; return z; }(); Because until you reach the () at the end you have no idea whether this is supposed to be an anonymous function to be called elsewhere or a series of statements to be executed right now. Sure, the comma expression isn't used very often, but when I do need to use it I don't want to have to put garbage syntax like that in my code. When you're reading code and you see `do(` you know straight away what's going on.
Re: Usability of "allMembers and derivedMembers traits now only return visible symbols"
On Wednesday, 31 August 2016 at 21:12:54 UTC, Ali Çehreli wrote: On 08/30/2016 03:24 PM, Ali Çehreli wrote: > v2.071.2-b3 is bringing a change for this bug: > > https://issues.dlang.org/show_bug.cgi?id=15907 > > I don't agree with the current solution: > > http://dlang.org/changelog/2.071.2.html#traits-members-visibility > > Modules should be able to use library templates without needing to mix > them in first. > > Do you think the solution in the change log usable? I don't think so > because silently skipping my private members is an unexpected behavior > that will cause bugs. Here is a regression caused by the above change: interface I { void foo(); package: void foo(int); } string how(alias Base, alias func)() { return ""; } import std.typecons; class C : AutoImplement!(I, how) { } What this derives a class in std.typecons that implements the interface, and yes such a derived class can't override/implement package protected methods. AutoImplement would also work better as mixin in order to instantiate the passed in how template in the original instantiation scope. void main() { auto c = new C(); c.foo(); c.foo(42);// COMPILATION ERROR: // deneme.o: In function `_Dmain': // deneme.d:(.text._Dmain+0x39): undefined reference to `_D6deneme1I3fooMFiZv' The missing interface method implementation should've give a compile error, please file a bug. The recommended solution of mixing in every template instance is not a viable solution because that would effectively remove IFTI from D. What a huge loss that would be. We can't afford that. Exaggeration won't help us to find good solutions. Remember that private fields never were accessible, so only some edge cases will be affected. The need for mixin templates will remain rare.
Re: ADL
On 9/3/16 4:09 PM, Tobias M wrote: On Saturday, 3 September 2016 at 12:25:11 UTC, Andrei Alexandrescu wrote: What problems are you referring to? -- Andrei The problems discussed here in the thread related to name lookup at template instantiation time. And also similar problems related to visibility (public/private) that were discussed in a different thread recently. I see. This is a matter orthogonal to DbI - introspection should be able to figure out whether a member can be found, or a nonmember if the design asks for it. I wouldn't like "tricking" DbI into thinking a member is there when there isn't. -- Andrei
Re: ADL
On Saturday, 3 September 2016 at 14:05:11 UTC, Tobias M wrote: On Saturday, 3 September 2016 at 12:40:26 UTC, ZombineDev wrote: No, LINQ doesn't work because of interfaces, but because of extension methods (C#'s variant of UFCS). The IEnumerable interface defines only a single method. All the useful functionality is implemented as extension methods which are only available if the user specifically imports the namespace in which where they're defined (just like D's ranges and range primitive implementations for arrays). Those extension methods are used as a fallback, similarly to UFCS in D: every type can override the extension methods by implementing the method itself. Also more inner namespaces (more closer to the method invocation) override more outer namespaces. I know extension methods, that's not the point. The point is, that you cannot have a generic method like this in C#, it won't compile: class Bar { void GenericMethod(T arg) { arg.Foo(); } } Instead you need a constraint like this: interface IFoo { void Foo(); } class Bar { void GenericMethod(T arg) where T: IFoo { arg.Foo(); } } No you're wrong. There's no need for interfaces or for generic constraints. It's not static vs duck typing. It's just a method lookup issue. See for yourself: http://rextester.com/GFKNSK99121 Similarly for LINQ, you cannot just implement a generic "Sum" extension method for IEnumerable that works for all T, because you cannot just use the + operator in that method. It is not defined on T if there are no respective constraints. Look at how it is implemented separately for every type T that supports +: https://msdn.microsoft.com/de-de/library/system.linq.enumerable.sum(v=vs.110).aspx Sum is implemented in that stupid way, because unlike C++, in C# operators need to be implemented as static methods, so you can't abstract them with an interface. If they were instance methods, you could implement them outside of the class as extension methods and there would be no need to write a distinct method for each type. Here's an example: http://rextester.com/PQFPC46087 The only thing missing is syntax sugar to forward the '+' operator to 'Add' in my example. I'm guessing that operator overloading was designed that way because: 1) they're worried about boxing and virtual call overhead 2) operator overloading was designed before generics (IIRC).
Re: DIP1001: DoExpression
On 9/3/16 6:19 PM, Cauterite wrote: On Saturday, 3 September 2016 at 15:28:36 UTC, Andrei Alexandrescu wrote: What's wrong with: auto seq(T...)(auto ref T vals) { return vals[$ - 1]; } Well there's nothing *wrong* with that, but I really think that 'do' is the perfect word for this purpose, and the fact that it's already a keyword is real convenient. For just 10 lines in parse.d we get this great syntax, no code breakage, no need to copy-paste a little template around. This is a terrible argument. It has "why not" all over it. -- Andrei
Re: Fallback 'catch-all' template functions
On 9/3/16 6:10 PM, Manu via Digitalmars-d wrote: We do this sort of things a lot. Consider std.conv.to? std.conv.to is not a frequently done thing. -- Andrei
Re: DIP1001: DoExpression
On 9/3/16 6:10 PM, Jonathan M Davis via Digitalmars-d wrote: I think that we're much better off just killing it off. We're better off with what we have right now: you can use comma, just don't take the last value. Absent a smoking gun (and one very smokey and stinky at that), I don't see the purpose of DIP1001. I suggest we just retire it. Andrei
Re: Beta D 2.071.2-b3
On Saturday, 3 September 2016 at 14:40:37 UTC, Martin Nowak wrote: Yes, it does help. As private prevents usage outside of a module it allows to do some optimizations that required whole program analysis otherwise, e.g. variables and functions can get internal linkage, thus reducing loads/stores and indirect calls. This doesn't really work that easily due to templates that depend on private data, and private data being referenced from alias parameters. Of course, all such cases can still be statically detected when compiling the module in question, but this is quite a bit less trivial than just looking at the protection level. — David
Re: ADL
On 9/3/16 5:57 PM, Manu via Digitalmars-d wrote: On 3 September 2016 at 22:42, Andrei Alexandrescu via Digitalmars-dwrote: On 9/3/16 1:51 AM, Manu via Digitalmars-d wrote: I've never thought about this problem in C++, or had any problems with ADL. How do you swap two objects of a generic type that may or may not define its own swap? -- Andrei It's not a problem I've ever had. A problem you didn't know you have. It's a classic C++ conundrum combining theory and practice. I'm not actually quite sure I understand your question... The task is to swap two objects of generic type T. If T's namespace defines an overload of swap with the appropriate signature, use it. Otherwise, fall back to std::swap. For bonus points: if T defines swap as a _member_ function, use that. I guess this is sort of like the issue I was alluding to in my other thread though; there exists a generic implementation, but some type requires to specialise for itself, which then needs to trump the otherwise ambiguous conflict with the catch-all? I think that's an interesting problem, but it's quite easy to solve with an (ugly) forwarding template; but that forwawrding template leads right back here, where the worker `doThingImpl()` as implemented for each type that supports 'doThing' depends on ADL to be callable from the master `doThing()` function. Post the code. Andrei
Re: DIP1001: DoExpression
On Saturday, 3 September 2016 at 15:28:36 UTC, Andrei Alexandrescu wrote: What's wrong with: auto seq(T...)(auto ref T vals) { return vals[$ - 1]; } Well there's nothing *wrong* with that, but I really think that 'do' is the perfect word for this purpose, and the fact that it's already a keyword is real convenient. For just 10 lines in parse.d we get this great syntax, no code breakage, no need to copy-paste a little template around.