Re: is ==
Furthermore: https://issues.dlang.org/show_bug.cgi?id=3889 Shows real problems. You argue from the side that the bug already exists so we must work around it because we can't go back and "fix things". Who says? D has had breaking changes in the past so it is not a deal breaker. It is also a relatively easy transition because == null is very easy to find and fix. With the mentality that one must always deal with introduced logic bugs that, if fixed, will break old code is insane. The whole point of fixing bugs is to make things work *correctly*. The fact is someone decided it was a good idea to conflate null with some dynamic array BS and that is where all the problems come from. It should have never been done and this issue will persist until someone gets the balls to fix it. After all, how do you know it won't actually make a lot of "buggy" code better?
Re: Can I infer the type from this?
On Sunday, 20 May 2018 at 02:01:20 UTC, Alex wrote: On Sunday, 20 May 2018 at 01:41:03 UTC, Dr.No wrote: I'd like to pass a symbol as paramater (class static member0 and at same time get the type of this, something like this: template myTemp(alias s) { enum myTemp = templateFunction!(??)(s.stringof); } the templateFunction has this signature: int templateFunction(T)(string targetMembername) but I don't how to get the type name from the give symbol name in myTemp. Can I make this work? Something like this? ´´´ import std.stdio; void main() { size_t s; auto res = myTemp!s; } template myTemp(alias s) { enum myTemp = templateFunction!(typeof(s))(s.stringof); } int templateFunction(T)(string targetMembername) { static assert(is(T == size_t)); assert(targetMembername == "s"); return 42; } ´´´ Oh, my bad: I totally forgot a crucial thing on question: I want this to work with a static member, for example, call myTemp like this myTemp!(C.a) I don't mind if I to pass the type as parameter somehow, like myTemp!(C, C.a) or myTemp!(C)(C.a) but I do need to pass a symbol as parameter, hence I'm using alias template parameter.
Re: is ==
On Sunday, 20 May 2018 at 02:09:47 UTC, Jonathan M Davis wrote: On Sunday, May 20, 2018 01:51:50 IntegratedDimensions via Digitalmars-d- learn wrote: Simply require == null as is null and be done with it. That would be flat out wrong for dynamic arrays, because then auto result = arr == null and int[] nullArr; auto result = arr == nullArr; would have different semantics. The way that dynamic arrays are designed to work even if they're null mucks with this considerably here. Do you not see they are different? You think arr == nullArr and arr == null are suppose to necessarily be the same semantics? That is patently false! You should rethink your position on that because it is wrong. null is a keyword in D and has a very special meaning and hence that meaning MUST be taken in to account. There is no harm in making them different. Your logic thinks that that they should be the same but if you are wrong then your whole argument is wrong. for example, Object o = null; then o == null should not be true even though "null == null" in some sense. == null is a test of validity. One never checks if null == null and it is a meaningless case so allowing it as a possibility is meaningless. You are treating null as if it is on the same level as objects and arrays and it is not. By doing so you lose the power of it being singled out as a keyword. You can't police programmers minds and get them to program correctly. That's true, but making things that are highly likely to be wrong illegal prevents bugs. e.g. Not necessarily because you just create more bugs by doing that. Your son, the bubble boy, then does not develop an immune system that he should of developed by you trying to protect them from hurting himself. You should get out of the business of trying to prevent things that you don't even know are going to happen. It is a bad mindset to be in because, for all you know, those things will never happen. Time is better spent than trying to police everyone from doing anything wrong. 1. You can't do it. 2. You make things worse in the long run because who's policing you to keep you from screwing up? Do you know how many "bugs" are produced by people who are fixing "bugs"? We can surely bet more than zero. while(cond); is illegal in D precisely because it's error-prone. There are cases where doing something like that would be perfectly correct. e.g. while(++a != b); but you can do the exact same thing with empty parens while(++a != b) {} and all of those bugs with accidentally closing a loop with a semicolon go away, and you don't lose any expressiveness. The compiler just forces you to write it in a way that's far less error-prone. This is a different problem and therefor not applicable. Making it illegal to compare the null literal with == also prevents bug, and you don't lose any expressiveness doing it either. It's the same kind of logic. Making error-prone constructs illegal when there's a simple equivalent that isn't error-prone is good language design, because it prevents bugs without actually restricting the programmer. It's when the language starts disallowing things that aren't error-prone and/or don't have simple equivalents that you start running into problems with the compiler getting in your way and treating you like a kid. For simple stuff like this, it ultimately saves you time and effort without getting in your way. At most, you occasionally have to replace foo == null with foo is null or foo.length != 0, and it potentially saves you hours of effort tracking down a subtle bug. - Jonathan M Davis You certainly do lose expressiveness. You loose elegance because you cannot express logically related things in a logically related way. The problem is the WHOLE reason it is error prone is from who ever decided the dynamic array syntax of == null would not compare it the same way it does everything else. Basically someone thought they were going to be fancy and treat == null as the same as an allocated 0 length array. That was the problem from the get go. == null should have a very specific and consistent meaning and someone decided to change that in an irregular and inconsistent meaning and now we have less elegance in the language than we could. The reason why you are saying it is buggy is PRECISELY because of what was done wrong. Programmers assume that == null means the same thing it does everywhere else, but LO AND BEHOLD! Not in that one special case and if they don't know about that special case they hit the "bug". See, what you call bugs is really the programmers failing to know the special case that was created. The special case that really had no reason to be a special case. So, in fact, who ever decided on the rules here created more problems than they solved. Any time you create special cases you create complexity and that is what creates bugs of the type here. These bugs are
Re: is ==
On Sunday, May 20, 2018 01:51:50 IntegratedDimensions via Digitalmars-d- learn wrote: > Simply require == null as is null and be done with it. That would be flat out wrong for dynamic arrays, because then auto result = arr == null and int[] nullArr; auto result = arr == nullArr; would have different semantics. The way that dynamic arrays are designed to work even if they're null mucks with this considerably here. > You can't police programmers minds and get them to program correctly. That's true, but making things that are highly likely to be wrong illegal prevents bugs. e.g. while(cond); is illegal in D precisely because it's error-prone. There are cases where doing something like that would be perfectly correct. e.g. while(++a != b); but you can do the exact same thing with empty parens while(++a != b) {} and all of those bugs with accidentally closing a loop with a semicolon go away, and you don't lose any expressiveness. The compiler just forces you to write it in a way that's far less error-prone. Making it illegal to compare the null literal with == also prevents bug, and you don't lose any expressiveness doing it either. It's the same kind of logic. Making error-prone constructs illegal when there's a simple equivalent that isn't error-prone is good language design, because it prevents bugs without actually restricting the programmer. It's when the language starts disallowing things that aren't error-prone and/or don't have simple equivalents that you start running into problems with the compiler getting in your way and treating you like a kid. For simple stuff like this, it ultimately saves you time and effort without getting in your way. At most, you occasionally have to replace foo == null with foo is null or foo.length != 0, and it potentially saves you hours of effort tracking down a subtle bug. - Jonathan M Davis
Re: Can I infer the type from this?
On Sunday, 20 May 2018 at 01:41:03 UTC, Dr.No wrote: I'd like to pass a symbol as paramater (class static member0 and at same time get the type of this, something like this: template myTemp(alias s) { enum myTemp = templateFunction!(??)(s.stringof); } the templateFunction has this signature: int templateFunction(T)(string targetMembername) but I don't how to get the type name from the give symbol name in myTemp. Can I make this work? Something like this? ´´´ import std.stdio; void main() { size_t s; auto res = myTemp!s; } template myTemp(alias s) { enum myTemp = templateFunction!(typeof(s))(s.stringof); } int templateFunction(T)(string targetMembername) { static assert(is(T == size_t)); assert(targetMembername == "s"); return 42; } ´´´
Re: is ==
On Sunday, 20 May 2018 at 00:19:28 UTC, Jonathan M Davis wrote: On Saturday, May 19, 2018 17:50:50 IntegratedDimensions via Digitalmars-d- learn wrote: So, ultimately what I feels like is that you are actually arguing for == null to be interpreted as is null but you don't realize it yet. Not really, no. Having foo == null be rewritten to foo is null in the non-dynamic array cases should be fine except for the fact that it's then a terrible habit to be in when you then have to deal with dynamic arrays. Using foo == null with dyanmic arrays is an enormous code smell, because the odds are extemely high that the programmer thinks that they're checking if the dynamic array is null when that's not what they're doing at all. IMHO, it should definitely be an error to use == with null and dynamic arrays because it is such a big code smell. Either the code should be using is to check whether the array is null, or it should be checking length. It should never be using == with null. But unfortunately, the compiler is completely backwards about this and treats it as an error with pointers and references but allows it with dynamic arrays. If the compiler were improved to just replace == with is in the cases that it currently treats as illegal, then that would be fine if it then treated it as illegal with dynamic arrays. But as it stands, it is still more efficient to use is with call references, so encouraging the programmer to use is is benefical, and it encourages the programmer to get in the habit of not using == with null, since it's a terrible habit to be in with dynamic arrays. But actually making it illegal for dynamic arrays would be a much better approach. If it were up to me, it would just be illgal to use == with null in general, because that's really the way it should be with dynamic arrays, and then the language would be consistent about it. But instead, the compiler screams in the case that matters far less and allows it in the case that is clearly bad. So, it's inconsistent in a dumb way. At least if it were inconsistent by allowing it for pointers and references while disallowing it for arrays, it would be prventing it in the case that truly matters, but instead, what we have is just dumb. - Jonathan M Davis Let D be a dynamic array, O a pointer or object: | Conceptually | in D D == null Invalid Valid D is null Valid Valid O == null Valid Invalid O is null Valid Valid Right? So what you are saying is you want to create 2 more invalids in the table to satisfy some weird logic which requires the programmer to remember special cases rather than make them all valid and easy to remember even though it can be done and make sense. In fact, the 2nd invalid makes sense and should be allowed so really you want to create 3 invalids for the price of one. Simply require == null as is null and be done with it. You can't police programmers minds and get them to program correctly. If you had a kid, do you box them up in a bubble room and not let them play because they might hurt themselves? How people learn is by making mistakes. It is better to provide a logical foundation that is consistent rather than produce corner cases to handle some corner case that was created to handle another corner case because someone handled a corner case.
Can I infer the type from this?
I'd like to pass a symbol as paramater (class static member0 and at same time get the type of this, something like this: template myTemp(alias s) { enum myTemp = templateFunction!(??)(s.stringof); } the templateFunction has this signature: int templateFunction(T)(string targetMembername) but I don't how to get the type name from the give symbol name in myTemp. Can I make this work?
Re: How is == operator implemented for string type?
On Wednesday, 16 May 2018 at 18:56:26 UTC, Steven Schveighoffer wrote: On 5/16/18 2:45 PM, Dr.No wrote: where is the actual source code implementation? https://github.com/dlang/druntime/blob/7e3b4086fee8f2e2a6882942c677acc28df527ee/src/object.d#L3479 -Steve thanks
Re: is ==
On Saturday, May 19, 2018 17:13:36 Neia Neutuladh via Digitalmars-d-learn wrote: > I don't think I've ever wanted to distinguish a zero-length slice > of an array from a null array. It's safer if you don't, because it's so easy to end up with a dynamic array that is empty instead of null, and stuff like == doesn't care about the difference. But there is code that's written that cares (e.g. IIRC, std.experimental.allocator does in some cases). if(arr) is equivalent to if(cast(bool)arr) and casting a dynamic array to bool is equivalent to arr !is null which means that if(arr) means if(arr !is null) whereas it's not uncommon for folks to think that it means if(arr.length != 0) Similarly, assert(arr); is ultimately equivalent to asser(arr !is null); which suprises many folks and is rarely what folks want. So, there was a push at one point to make it illegal to use a dynamic array in an if statment or assertion directly, and it did briefly make it into the compiler. However, a few folks (Andrei and Vladimir in particular IIRC), had used arrays in if statments directly quite a bit, knowing full well what it meant. So, their code was right (albeit potentially confusing), and they pushed back. So, the change was reverted, and we're still stuck with the error-prone situation that we've had. So, most of us would argue that it's risky to treat null dynamic arrays as special and that it should be done with caution, but programmers who know what they're definitely do it. Unfortunately, when you read code that's writen that way, it's usually hard to tell whether it was written with that undertanding or not, and a stray == in the code could easily break it. > As I already said, I use "array.length == 0". "array.empty" is > part of that newfangled range business. LOL. Well, if you stay away from ranges, you're losing out on a lot of benefits - including large portions of the standard library, but checking for length works fine if you're dealing with code that's just using dynamic arrays and not ranges. The key thing is to avoid arr == null, because that's were the bugs lie. - Jonathan M Davis
Re: is ==
On Saturday, May 19, 2018 17:50:50 IntegratedDimensions via Digitalmars-d- learn wrote: > So, ultimately what I feels like is that you are actually arguing > for == null to be interpreted as is null but you don't realize it > yet. Not really, no. Having foo == null be rewritten to foo is null in the non-dynamic array cases should be fine except for the fact that it's then a terrible habit to be in when you then have to deal with dynamic arrays. Using foo == null with dyanmic arrays is an enormous code smell, because the odds are extemely high that the programmer thinks that they're checking if the dynamic array is null when that's not what they're doing at all. IMHO, it should definitely be an error to use == with null and dynamic arrays because it is such a big code smell. Either the code should be using is to check whether the array is null, or it should be checking length. It should never be using == with null. But unfortunately, the compiler is completely backwards about this and treats it as an error with pointers and references but allows it with dynamic arrays. If the compiler were improved to just replace == with is in the cases that it currently treats as illegal, then that would be fine if it then treated it as illegal with dynamic arrays. But as it stands, it is still more efficient to use is with call references, so encouraging the programmer to use is is benefical, and it encourages the programmer to get in the habit of not using == with null, since it's a terrible habit to be in with dynamic arrays. But actually making it illegal for dynamic arrays would be a much better approach. If it were up to me, it would just be illgal to use == with null in general, because that's really the way it should be with dynamic arrays, and then the language would be consistent about it. But instead, the compiler screams in the case that matters far less and allows it in the case that is clearly bad. So, it's inconsistent in a dumb way. At least if it were inconsistent by allowing it for pointers and references while disallowing it for arrays, it would be prventing it in the case that truly matters, but instead, what we have is just dumb. - Jonathan M Davis
C style callbacks fix for member callbacks
I have a member callback that I want to use as a C callback. This is impossible due to the `hidden this` passed as the "first" parameter. The callback already makes it's last value a user pointer which I use as a "this". If I make my method static extern(C) then there is no crash and everything works. The problem is that it is now a static function within the class which I want to avoid. Because there is actually a "this pointer" I can make it a member function and everything works as long as the calling convention is right. I was initially wrapping the callback in a delegate that made it all work out but I want to avoid that level of indirection since it should not be necessary. I have tried manually reversing the arguments, using various calling conventions, etc but everything crashes except when I use extern(C) static without modifying the order. extern(C) static foo(a,b,c,d) puts the parameters on the stack as d,c,b,a foo(a,b,c,d) is d,c,b,a,this (? The ABI does not make it clear what order is pushed on the stack. It uses the terminology "passes" and I assume that the calling convention is C'ish although extern(C) matters). works extern(C) static foo(a,b,c,d) does not work static foo(d,c,b,a) So something else is going on "The last parameter is passed in EAX rather than being pushed on the stack if the following conditions are met: It fits in EAX. It is not a 3 byte struct. It is not a floating point type. " Can someone clarify the exact calling convention process for C vs D along with any potential solutions to the above problem(using static is not a solution). Just to make sure we are on the same page: class { void extern(C) static foo(a,b,c,mythis); } works while class { void extern(C) foo(a,b,c); } fails. class { void foo(c,b,a); } also fails.
Re: Real Int24
On Saturday, 19 May 2018 at 18:19:35 UTC, IntegratedDimensions wrote: Is there any way to create an int24 type that behaves just like any other built in type without having to reimplement everything? In fact, what I'd like to do is create an arbitrary type: struct atype(T) { } where atype(T) is just a "view" in to N_T bits interpreted as T, an enum. If T is bit, then the N = 1 and the interpretation is 1 bit. If T is byte, then the N = 8 and the interpretation is 7 bits followed by 1 signed bit. If T is int24, then the N = 24 and the interpretation is 23 bits followed by 1 signed bit. The idea is the storage of atype is exactly N bits. If this is not possible due to boundary issues then N can always be a multiple of 8(which is for my use cause is the smallest). The main thing is that I would like to be able to use atype as if it were a built in type. If N = 24, 3 bytes, I want to be able to create arrays of atype!int24[] which work just as if they were arrays of bytes without any exception or special cases. atype!byte would be equivalent to byte and reduce to the compiler internals. I'm not looking to create a "view" of an array. I want a standalone type that can behave as all the desired types needed, which is most of the numerical types of D and some of the ones it neglected like 24-bit ints, 48-bit ints, etc. Ideally, any type could be used and the "most optimal" code is generated while being able to use the types using the standard model.
Real Int24
Is there any way to create an int24 type that behaves just like any other built in type without having to reimplement everything?
Re: is ==
On Saturday, 19 May 2018 at 01:31:38 UTC, Jonathan M Davis wrote: On Friday, May 18, 2018 23:53:12 IntegratedDimensions via Digitalmars-d- learn wrote: Why does D complain when using == to compare with null? Is there really any technical reason? if one just defines == null to is null then there should be no problem. It seems like a pedantic move by who ever implemented it and I'm hoping there is actually a good technical reason for it. Because == is pretty much never what you want to do with null. How much it matters depends on the types involved, but if you really want to check for null, is is definitely the right thing to use. In the case of pointers and references, is checks that they're pointing to the same thing. So, foo is null directly checks whether the reference or pointer is null. On the other hand, if you use ==, it's calling some form of opEquals. For pointers, that should generate identical code, but for class references, it means calling the free function opEquals. That function will check whether the references are null before calling opEquals on either of the class objects, but it does add unnecessary overhead (which, as I understand it, the compiler is unfortunately not currently able to optimize away) and provides no benefit over checking with is. Now, where is vs == _really_ matters (but unfortunately, the compiler does not complain about) is with dynamic arrays. If you do arr is null then the compiler will check whether the array's ptr is null. So, something like "" is null would be false. However, if you use ==, then it compares the length of the array and then only compares the ptrs if the length is non-zero. So, "" == null is true. So, with dynamic arrays, using == with null is a huge code smell. It _may_ be exactly what the programmer intends, but the odds are pretty high that they just don't properly understand the difference between is and ==, and they meant to be checking whether the array was actually null but just ended up checking whether its length was zero (which won't matter for some code but will cause subtle bugs in any code that treats null as special - e.g. if that is used to indicate that the array had not been given a value). Now, because of how == treats null like empty, it _is_ a bit risky to try and treat null as special with arrays, but anyone wanting to be clear in their code should either be checking null with is (in which case, they clearly care about null and not empty), or if they care about length == 0, they should either be calling empty on the array or explicitly checking the array's length, since that's what they care about. Much as having == work with null arrays avoids issues with segfaults due to an array be unitialized as well as avoids needing to give memory to an array just to have it be empty, you pretty much never actually care whether an array == null. You either care that its ptr is null (in which case, is checks that), or you care about whether its length is 0 (in which case empty or directly checking length checks that). arr == null is just unclear and likely buggy. So really, there are _zero_ advantages to comparing null with ==. Using == with null risks adding extra overhead, and it often makes the code less clear. On the other hand, using is makes it crystal clear what you mean and then does exactly what you mean - check whether the variable is actually null. So, maybe the compiler is being a bit pedantic by insisting that you use is rather than ==, but you really should be using is and not == when checking for null. - Jonathan M Davis I don't see your point. You claim that one should never use == null for whatever reason and that it is "wrong". So, why are you allowing wrong things in a language that can easily be fixed? Just reinterpret == null as is null and be done with it! This fixes the wrong and everyone can live happily ever after. Your logic is the same how people "ban" certain words like faggot. They don't like them for some reason, decide that no one should use it any more, and create a new word that essentially means the same thing... and it results in a loop where that new word then eventually gets "banned". == vs is might not be quite as extreme, maybe is will be the final "word". But if == null is banned by the compiler why the hell not just reinterpret to mean is null internally and be done with it and allow the syntax since it is so common? The only pitfalls is pasting code from other languages that might have a different interpretation, but those problems always exist since the languages are different. Your reasons for arrays is not good enough. First, not all types are arrays so you are banning a whole class of valid types for one case. That case, you say, is almost never meant anyways(that is, using == null is really meant as is null). So, ultimately what I feels like is that you are actually arguing for == null to
Re: C API / const char *text / std.string.toStringz pointer is always NULL on C side
On Saturday, 19 May 2018 at 17:33:08 UTC, Robert M. Münch wrote: On 2018-05-18 14:42:17 +, Adam D. Ruppe said: A value struct return is actually done via a hidden pointer parameter (so the function can construct it in-place for the caller, a standard optimization), so it just shifted all the other arguments to the side, causing one of those 0's to be interpreted as the string. [...] Is this somehwere documented? https://docs.microsoft.com/en-us/cpp/build/return-values-cpp: Otherwise, the caller assumes the responsibility of allocating memory and passing a pointer for the return value as the first argument. Subsequent arguments are then shifted one argument to the right.
Re: C API / const char *text / std.string.toStringz pointer is always NULL on C side
On 2018-05-18 14:42:17 +, Adam D. Ruppe said: On Friday, 18 May 2018 at 14:06:11 UTC, Robert M. Münch wrote: So, having a wrong return-type here, resulted in the const char *text parameter always being NULL. Not sure I understand the relation but looks strange to me... at least not very obvious. A value struct return is actually done via a hidden pointer parameter (so the function can construct it in-place for the caller, a standard optimization), so it just shifted all the other arguments to the side, causing one of those 0's to be interpreted as the string. Wow, thanks for the clear explanation. Without very deep internal knowhow I don't think anyone is able to ever guess this. Is this somehwere documented? -- Robert M. Münch http://www.saphirion.com smarter | better | faster
Re: is ==
On Saturday, 19 May 2018 at 04:30:24 UTC, Jonathan M Davis wrote: On Saturday, May 19, 2018 03:32:53 Neia Neutuladh via Digitalmars-d-learn wrote: > Of course, the most notable case where using == with null is > a terrible idea is dynamic arrays, and that's the case where > the compiler _doesn't_ complain. Using == with null and > arrays is always unclear about the programmer's intent and > almost certainly wasn't what the programmer intended. If the > programmer cares about null, they should use is. If they > care about lengnth, then that's what they should check. > Checking null with == is just a huge code smell. I feel like the array == null version is more explicit about not allocating memory. However, I'm paranoid about whether that's going to check the pointer instead, so I mostly use array.length == 0 instead. I'm not sure what memory allocations you're worried about. Neither "" nor [] allocates memory "" is syntax for compile-time constants and shouldn't ever allocate. [] is a specific case of [values...]; the general case allocates, but this one case does not. null is not even a compile-time constant; it's a value baked into the language and is guaranteed not to allocate. but regardless, if you're looking to check whether arr.ptr is null, then that's effectively what you get with arr is null I don't think I've ever wanted to distinguish a zero-length slice of an array from a null array. Regardless, if you're checking for null, then is does the job, and if what you care about is whether the array is empty, then that's what arr.length == 0 and arr.empty do. As I already said, I use "array.length == 0". "array.empty" is part of that newfangled range business.