Re: isCallable fails
On Friday, 22 January 2021 at 03:40:40 UTC, tsbockman wrote: Cars are mass-produced copies of a relatively small number of rather similar designs, and mechanics' customers *pay them* to understand and fix their cars so that the customers don't have to. I knew this argument comes... Nevertheless, I will use your analogy: You: My car shakes when I turn left. What do you think is wrong with it? Mechanic: Hard to say. Bring it in to the shop and I'll take a look. No. It's more that I did say: The board computer message is weird, it points to one of my tires but does not tell me the correct error. The tire seems to be wrecked. There is a scratch - but what could cause it? Someone with expierence (a mechanic) know this kind of error? I kindly ask. But mechanics do not listen and telling me I need to do an oil change and why it's important. -- If someone is interested: I think it's a bug that the compiler cannot handle this recursion correctly. By calling isCallable!S and parsing the structs "alias this" not the complete get() content need to be parsed as only the return type is relevant here - which is already known: T I have to arrange that the problematic code is not parsed when calling isCallable, so the only solution was a proxy method that switch to get() in runtime to satisfy the compiler, not very pretty, but works: struct foo(T) { alias proxy this; T delegate() p; // called from this(), this(this) void initProxy() { p = delegate() { return get; }; } T get() { // problematic code } T proxy() { return p(); } }
Re: std.algorithm.splitter on a string not always bidirectional
On Friday, 22 January 2021 at 05:51:38 UTC, Jon Degenhardt wrote: On Thursday, 21 January 2021 at 22:43:37 UTC, Steven Schveighoffer wrote: auto sp1 = "a|b|c".splitter('|'); writeln(sp1.back); // ok auto sp2 = "a.b|c".splitter!(v => !isAlphaNum(v)); writeln(sp2.back); // error, not bidirectional Why? is it an oversight, or is there a good reason for it? -Steve I believe the reason is two-fold. First, splitter is lazy. Second, the range splitting is defined in the forward direction, not the reverse direction. A bidirectional range is only supported if it is guaranteed that the splits will occur at the same points in the range when run in either direction. That's why the single element delimiter is supported. Its clearly the case for the predicate function in your example. If that's known to be always true then perhaps it would make sense to enhance splitter to generate bidirectional results in this case. --Jon Note that the predicate might use a random number generator to pick the split points. Even for same sequence of random numbers, the split points would be different if run from the front than if run from the back.
Re: std.algorithm.splitter on a string not always bidirectional
On Thursday, 21 January 2021 at 22:43:37 UTC, Steven Schveighoffer wrote: auto sp1 = "a|b|c".splitter('|'); writeln(sp1.back); // ok auto sp2 = "a.b|c".splitter!(v => !isAlphaNum(v)); writeln(sp2.back); // error, not bidirectional Why? is it an oversight, or is there a good reason for it? -Steve I believe the reason is two-fold. First, splitter is lazy. Second, the range splitting is defined in the forward direction, not the reverse direction. A bidirectional range is only supported if it is guaranteed that the splits will occur at the same points in the range when run in either direction. That's why the single element delimiter is supported. Its clearly the case for the predicate function in your example. If that's known to be always true then perhaps it would make sense to enhance splitter to generate bidirectional results in this case. --Jon
Re: std.algorithm.splitter on a string not always bidirectional
On 1/21/21 4:51 PM, H. S. Teoh wrote: > But I wouldn't be surprised if there was some > surprising corner case for which this doesn't work / would have onerous > characteristics. Likely. :) Here is one for uniq.back, which includes a link at the bottom for zip.back: https://issues.dlang.org/show_bug.cgi?id=16588 Ali
Re: isCallable fails
On Friday, 22 January 2021 at 03:08:23 UTC, frame wrote: It's like asking your mechanican if he can guess what's causing the weird sound in the car and he replies with: why didn't you disassemble your car already? Cars are mass-produced copies of a relatively small number of rather similar designs, and mechanics' customers *pay them* to understand and fix their cars so that the customers don't have to. By contrast, computer programs are tremendously more diverse than car designs, you are not paying anyone here, and we participate here to pass our skills and knowledge on to others, not just to do their work for them. Nevertheless, I will use your analogy: You: My car shakes when I turn left. What do you think is wrong with it? Mechanic: Hard to say. Bring it in to the shop and I'll take a look. You: It's a simple question! I shouldn't have to bring it in to the shop. Mechanic: Fine. If it was my car, here's how I would go about finding the problem... (Detailed explanation follows.) Do that, and if you still can't tell what's wrong, come back and talk to me again. You: That's too much work. This is ridiculous. It's a simple question: just tell me what's wrong with my car! Mechanic: Why do you think I can diagnose the problem with *even less information than you have*? If it's so simple, why do you need help? You: Rude! I'm outa here...
Re: isCallable fails
On Friday, 22 January 2021 at 02:43:44 UTC, tsbockman wrote: No, we're just used to helping each other get to the bottom of things like this. No one asked you for anything different from what we generally expect of each other in this context. This specific expectation mostly exists because, often, without a self-contained example we *truly don't know how to help you*. Please stop. I am very thankful for every hint, links to docs, tools etc. But if somebody writes "wasting his time" than it's personally (at least for me). I know it wasn't intend, somebody can have a bad day too but thats not helpful. It's like asking your mechanican if he can guess what's causing the weird sound in the car and he replies with: why didn't you disassemble your car already? But discusing about such missteps isn't helpful either and I hate it to discover such a post while searching in the web for a simple hint myself, so I will close this mentally. May someone filter out the necessary information about without wasting time.
Re: isCallable fails
On Friday, 22 January 2021 at 02:18:11 UTC, frame wrote: Anyway. It was a simple question not a prove that there is a bug in the compiler. isCallable is intended to either evaluate to a boolean, or give a clear compile-time error message. Since it did neither of those things for you, I suspect that something is wrong in the D project's code in addition to, or instead of, your code. You guys confuse a forum post question with a public examination. No, we're just used to helping each other get to the bottom of things like this. No one asked you for anything different from what we generally expect of each other in this context. This specific expectation mostly exists because, often, without a self-contained example we *truly don't know how to help you*. You are of course free to decide that our methods aren't worth your time, but please don't take it personally.
Re: isCallable fails
On Friday, 22 January 2021 at 00:59:32 UTC, tsbockman wrote: Generally, I don't need to know what causes an error in order to produce an MCVE. I have successfully done so on many occasions. It's annoying and slow, but usually very possible. I know that I have to debug it myself, but if somebody already know this kind of error I would still ask about first since the first message makes no sense. The second error indeed explains whats going on. Anyway. It was a simple question not a prove that there is a bug in the compiler. You guys confuse a forum post question with a public examination. The simple answer if any for somebody can just be: "void" can also be the data type if the compiler has problems resolving a symbol by running into a recursion while parsing.
Re: isCallable fails
On Friday, 22 January 2021 at 00:59:32 UTC, tsbockman wrote: 2) Remove, simplify, or mock up/stub out (like for unit tests) some large chunk of the remaining code in the program, from a part of the program that I *think* is unrelated to the error. 3) Re-test the program. a) If the failure goes away, goto (2) and try again by removing a different part of the program. I should clarify here that when I say "try again" I mean from a backup of the last version of the reduction-in-progress that *did* demonstrate the failure.
Re: isCallable fails
On Thursday, 21 January 2021 at 05:20:27 UTC, frame wrote: I was not asking here to re-produce my code or debug since it cannot provide a snippet if I do not know what could cause the error. Generally, I don't need to know what causes an error in order to produce an MCVE. I have successfully done so on many occasions. It's annoying and slow, but usually very possible. If it seems like it's going to be really difficult for a particular bug, it's fine to try asking others without an MCVE first. But, you should think of MCVE discovery as a valuable skill, not an impossibility. My technique works like this: 0) Make note of the symptoms/message for the specific failure that I am trying to isolate. 1) Make a separate copy of the program's source code which I can freely destroy. 2) Remove, simplify, or mock up/stub out (like for unit tests) some large chunk of the remaining code in the program, from a part of the program that I *think* is unrelated to the error. 3) Re-test the program. a) If the failure goes away, goto (2) and try again by removing a different part of the program. b) If the failure is still present and I think there is more that could be removed or simplified, goto (2). c) If the failure is still present, and I don't see anything else to remove or simplify, then I'm done. Whatever is left of the source code (hopefully something short and non-proprietary) is my MCVE. It's sort of a guess-and-check binary search for the minimum code that triggers the error. This process can be quite tedious, but it often does not require already knowing the cause of the error. (dustmite is a tool that partially automates this.) Sometimes it's worth going through, because having an MCVE is *really* useful, especially for other people who don't know the rest of your project's mostly-unrelated code base and dependencies well.
Re: std.algorithm.splitter on a string not always bidirectional
On Thu, Jan 21, 2021 at 05:43:37PM -0500, Steven Schveighoffer via Digitalmars-d-learn wrote: > auto sp1 = "a|b|c".splitter('|'); > > writeln(sp1.back); // ok > > auto sp2 = "a.b|c".splitter!(v => !isAlphaNum(v)); > > writeln(sp2.back); // error, not bidirectional > > Why? is it an oversight, or is there a good reason for it? [...] Likely an oversight. But I wouldn't be surprised if there was some surprising corner case for which this doesn't work / would have onerous characteristics. T -- MSDOS = MicroSoft's Denial Of Service
Re: opIndex negative index?
On Thursday, 21 January 2021 at 14:00:28 UTC, cerjones wrote: I'm a bit unsure if this is reasonable or not. Thoughts? Signed indexes are fine, if there is a principled reason to use them. Just make sure that you are consistent by making `length`, `opDollar`, etc. use signed types, as well. Otherwise, you're laying a trap for users of the API who may accidentally write code with mixed signed-unsigned integer operations. That's a big problem, because mixed signed-unsigned integer operations are done incorrectly by default, often with no warnings, in D and some other C-like languages. Consistently using signed types for lengths and indexes will make the API incompatible with some Phobos (D's `std`) range code, but you should get a compile-time error message. Mixing signed and unsigned, on the other hand, is likely to result in subtly wrong code that compiles without error, but sometimes does the wrong thing.
std.algorithm.splitter on a string not always bidirectional
auto sp1 = "a|b|c".splitter('|'); writeln(sp1.back); // ok auto sp2 = "a.b|c".splitter!(v => !isAlphaNum(v)); writeln(sp2.back); // error, not bidirectional Why? is it an oversight, or is there a good reason for it? -Steve
Re: opIndex negative index?
On Thursday, 21 January 2021 at 15:55:02 UTC, IGotD- wrote: On Thursday, 21 January 2021 at 15:49:02 UTC, IGotD- wrote: On Thursday, 21 January 2021 at 14:47:38 UTC, cerjones wrote: ohreally? I thought you were talking about the built in arrays. Since you create your own implementation just as you showed you are basically free to do anything. That also includes that you are free to create your own iterator as well. Tbh I was just a bit uneasy about negative indexes from a design point of view, you know when something just doesnt feel right. So anyway I coded it up and decided I didnt like it anyway, just looks weird having doSomthing(path[-1].x, path[-1].y); so im going to stick with it as it is.
Re: A variation of issue 11977?
On Thursday, 21 January 2021 at 14:11:15 UTC, kdevel wrote: Creating a scope works around the issue. Another way to work around the issue is to use «asm {jmp label;}» (replace jmp by whatever equivalent is there on the target architecture.) Yes it's ugly, but it bypasses the arbitrary limitation perfectly.
Re: opIndex negative index?
On Thursday, 21 January 2021 at 15:49:02 UTC, IGotD- wrote: On Thursday, 21 January 2021 at 14:47:38 UTC, cerjones wrote: ohreally? I thought you were talking about the built in arrays. Since you create your own implementation just as you showed you are basically free to do anything. That also includes that you are free to create your own iterator as well.
Re: opIndex negative index?
On Thursday, 21 January 2021 at 14:47:38 UTC, cerjones wrote: ohreally? I thought you were talking about the built in arrays.
Re: A variation of issue 11977?
On Thursday, 21 January 2021 at 13:55:48 UTC, kdevel wrote: [...] created https://issues.dlang.org/show_bug.cgi?id=21571
Re: opIndex negative index?
On Thursday, 21 January 2021 at 14:25:41 UTC, IGotD- wrote: On Thursday, 21 January 2021 at 14:00:28 UTC, cerjones wrote: Not possible, indexes are of type size_t which is unsigned. If you want negative indexes you need to wrap arrays in your own implementation and offset 0 so that negative indexes can be used. import std; struct Foo { int opIndex(int idx) { return idx; } } void main() { Foo foo; writeln(foo[-1]); } prints: -1 And just for weirdness... import std; struct Foo { string opIndex(string s) { return s; } } void main() { Foo foo; writeln(foo["ohrealy?"]); } prints: ohreally?
Re: opIndex negative index?
On Thursday, 21 January 2021 at 14:00:28 UTC, cerjones wrote: I have an iterator that steps along a 2D vector path command by command and uses opIndex to give access to the points for the current command. The issue is that there's a shared point between commands, so when the iterator is on a given command, it also needs to also allow access to the end point of the previous command. Currently the iterator juggles the indexes so that for a cubic you use 0,1,2,3, and 0 gives the previous end point. But it would simplify a few things if [-1] was for accessing the previous end point, so a cubic would allow indexes -1,0,1,2. I'm a bit unsure if this is reasonable or not. Thoughts? Not possible, indexes are of type size_t which is unsigned. If you want negative indexes you need to wrap arrays in your own implementation and offset 0 so that negative indexes can be used.
Re: A variation of issue 11977?
On Thursday, 21 January 2021 at 13:55:48 UTC, kdevel wrote: goto A; // line 4 aa["X"] = "Y";// line 5 A: Creating a scope { aa["X"] = "Y"; } // line 5 works around the issue.
Re: A variation of issue 11977?
On Thursday, 21 January 2021 at 13:55:48 UTC, kdevel wrote: ~~~gotoskip.d int main () { string[string] aa; goto A; // line 4 aa["X"] = "Y";// line 5 A: return 0; } ~~~ $ dmd gotoskip.d gotoskip.d(4): Error: goto skips declaration of variable gotoskip.main.__aaval2 at gotoskip.d(5) What's wrong here? Only found Issue 11977 [1] in which a declaration and initialization is jumped over. However, the statement in line 5 is neither a declaration nor an initialization. [1] https://issues.dlang.org/show_bug.cgi?id=11977 __aaval2 is a compiler-generated temporary variable. If you comment out the `goto A;` (so that the code compiles) and use the compiler flag -vcg-ast, you can see its declaration: int main() { string[string] aa = null; // goto A; (string __aaval2 = "Y";) , aa["X"] = __aaval2; A: return 0; }
opIndex negative index?
I have an iterator that steps along a 2D vector path command by command and uses opIndex to give access to the points for the current command. The issue is that there's a shared point between commands, so when the iterator is on a given command, it also needs to also allow access to the end point of the previous command. Currently the iterator juggles the indexes so that for a cubic you use 0,1,2,3, and 0 gives the previous end point. But it would simplify a few things if [-1] was for accessing the previous end point, so a cubic would allow indexes -1,0,1,2. I'm a bit unsure if this is reasonable or not. Thoughts?
A variation of issue 11977?
~~~gotoskip.d int main () { string[string] aa; goto A; // line 4 aa["X"] = "Y";// line 5 A: return 0; } ~~~ $ dmd gotoskip.d gotoskip.d(4): Error: goto skips declaration of variable gotoskip.main.__aaval2 at gotoskip.d(5) What's wrong here? Only found Issue 11977 [1] in which a declaration and initialization is jumped over. However, the statement in line 5 is neither a declaration nor an initialization. [1] https://issues.dlang.org/show_bug.cgi?id=11977