digitalmars.D.announce - Article: Why Const Sucks
- Jonathan M Davis (5/5) Mar 05 2018 Here's something I wrote up on const:
- Atila Neves (7/12) Mar 05 2018 My biggest issues with const are, as you wrote, ranges and
- Jonathan M Davis (26/29) Mar 05 2018 Aside from the whole std.concurrency situation, I generally use immutabl...
- Atila Neves (16/50) Mar 05 2018 I prefer const over immutable because this compiles:
- Dejan Lekic (2/7) Mar 05 2018 Brilliant article, Johathan! I feel the same...
- Adam D. Ruppe (6/6) Mar 05 2018 Just a semantic note, it is "straitjacket". "straight" is like a
- Jonathan M Davis (6/12) Mar 05 2018 Thanks for the correction. I probably knew at some point, but it's not a
- Me (2/8) Mar 05 2018 You guys are a bunch of nerds . . . .
- Me (3/9) Mar 05 2018 You guys are a bunch of nerds . . . .
- Arun Chandrasekaran (5/11) Mar 05 2018 Programmers like precision, don't we! From Simon Tatham article
- SimonN (10/11) Mar 05 2018 Excellent read! I enjoyed the history of proposed solutions.
- Jonathan M Davis (30/40) Mar 05 2018 Yes, the fact that those functions are on Object is a serious problem th...
- Adam D. Ruppe (14/15) Mar 05 2018 So as to the main thrust, I generally agree. In fact, I think
- Guillaume Piolat (5/10) Mar 06 2018 +1
- bauss (2/7) Mar 05 2018 Great read for a Monday.
- joe (38/43) Mar 05 2018 Interesting read and it explains some of the incomprehensible
- ShadoLight (88/88) Mar 05 2018 Very interesting and well written! Jonathan, your experiences
- Jonathan M Davis (15/35) Mar 05 2018 Thanks. Fixed.
- aberba (17/22) Mar 06 2018 Its amazing how typed languages, in this case const, forces you
- Radu (13/18) Mar 06 2018 Spot on article, and touches some of my pain points when working
- Meta (8/29) Mar 06 2018 AFAIK this is a solved problem. Dicebot (not sure if he's still
- Dukc (21/30) Mar 06 2018 I think we have a misunderstanding here. According to that, this
- Nemanja Boric (37/72) Mar 06 2018 Meaning that if you declare your `title` member `const char[]
- joe (17/19) Mar 08 2018 May be not entirely related, but a little gotcha.
- Steven Schveighoffer (11/36) Mar 08 2018 This is a problem with the cast system, not const. D has one cast
- joe (10/50) Mar 11 2018 I figured. Sorry for off topic.
Here's something I wrote up on const: http://jmdavisprog.com/articles/why-const-sucks.html I suppose that it's not exactly the most positive article, but I feel that it's accurate. - Jonathan M Davis
Mar 05 2018
On Monday, 5 March 2018 at 10:57:35 UTC, Jonathan M Davis wrote:Here's something I wrote up on const: http://jmdavisprog.com/articles/why-const-sucks.html I suppose that it's not exactly the most positive article, but I feel that it's accurate. - Jonathan M DavisMy biggest issues with const are, as you wrote, ranges and postBlit. I still use `const` everywhere unless I can't. I used to use `immutable`, but gradually came around to only using it if I have to send data to another thread, otherwise it's too much of a hassle. Atila
Mar 05 2018
On Monday, March 05, 2018 11:38:05 Atila Neves via Digitalmars-d-announce wrote:I used to use `immutable`, but gradually came around to only using it if I have to send data to another thread, otherwise it's too much of a hassle.Aside from the whole std.concurrency situation, I generally use immutable in the places where the semantics are the same as const, so it doesn't generally cause a problem for me. I just prefer immutable in the cases where it and const are the same, because immutable clearly indicates that the value never changes, so immutable more closely fits the idea even if const happens to mean that in that particular case. I agree that using immutable where you have to do stuff like design objects in a particular way in order to make immutable work is generally too much of a pain to be worth it, but at least in those cases, the data can then be shared across threads, and it's data that doesn't need mutable backdoors, because it only makes sense to use immutable in that fashion when the object is really designed to never change state. I think that the only time that I've programmed heavily in a way that involves immutability everywhere is when I programmed in Haskell, and that combined with the fact that Haskell is lazy and completely functional such that you can't use imperative idioms anywhere made it so that each line of Haskell code took me more time to write than is the case with any other language I've used (except maybe batch, because of how insanely error-prone it is). I think that I'm a better programmer for it, but I'd hate to program that way normally, and using immutable all over the place would head too heavily in that direction - though at least D, unlike Haskell, is a multi-paradigm language and allows you to choose to use a particular idiom when you think it makes the most sense instead of forcing it everywhere. - Jonathan M Davis
Mar 05 2018
On Monday, 5 March 2018 at 13:49:43 UTC, Jonathan M Davis wrote:On Monday, March 05, 2018 11:38:05 Atila Neves via Digitalmars-d-announce wrote:I prefer const over immutable because this compiles: string[] arr; const _ = arr; While this does not: string[] arr; immutable _ = arr; Basically, const just works and immutable is a hassle unless threads are involved. There are other situations where immutable is needed / should be preferred as well, notably: struct Foo { const(ubyte)[] bytes; } Construct Foo from a mutable buffer that you're reusing to get network traffic and you're going to have a bad time. AtilaI used to use `immutable`, but gradually came around to only using it if I have to send data to another thread, otherwise it's too much of a hassle.Aside from the whole std.concurrency situation, I generally use immutable in the places where the semantics are the same as const, so it doesn't generally cause a problem for me. I just prefer immutable in the cases where it and const are the same, because immutable clearly indicates that the value never changes, so immutable more closely fits the idea even if const happens to mean that in that particular case. I agree that using immutable where you have to do stuff like design objects in a particular way in order to make immutable work is generally too much of a pain to be worth it, but at least in those cases, the data can then be shared across threads, and it's data that doesn't need mutable backdoors, because it only makes sense to use immutable in that fashion when the object is really designed to never change state. I think that the only time that I've programmed heavily in a way that involves immutability everywhere is when I programmed in Haskell, and that combined with the fact that Haskell is lazy and completely functional such that you can't use imperative idioms anywhere made it so that each line of Haskell code took me more time to write than is the case with any other language I've used (except maybe batch, because of how insanely error-prone it is). I think that I'm a better programmer for it, but I'd hate to program that way normally, and using immutable all over the place would head too heavily in that direction - though at least D, unlike Haskell, is a multi-paradigm language and allows you to choose to use a particular idiom when you think it makes the most sense instead of forcing it everywhere. - Jonathan M Davis
Mar 05 2018
On Monday, 5 March 2018 at 10:57:35 UTC, Jonathan M Davis wrote:Here's something I wrote up on const: http://jmdavisprog.com/articles/why-const-sucks.html I suppose that it's not exactly the most positive article, but I feel that it's accurate. - Jonathan M DavisBrilliant article, Johathan! I feel the same...
Mar 05 2018
Just a semantic note, it is "straitjacket". "straight" is like a non-wiggly line. "strait" means narrow or constricted. Thus, the straitjacket is a jacket that constricts your movement. Of course, using "straight" is such a common mistake it has become generally accepted... but still, I like being precise with my words.
Mar 05 2018
On Monday, March 05, 2018 13:48:23 Adam D. Ruppe via Digitalmars-d-announce wrote:Just a semantic note, it is "straitjacket". "straight" is like a non-wiggly line. "strait" means narrow or constricted. Thus, the straitjacket is a jacket that constricts your movement. Of course, using "straight" is such a common mistake it has become generally accepted... but still, I like being precise with my words.Thanks for the correction. I probably knew at some point, but it's not a word that I use often, and I didn't even think about looking it up. Now, I'm more likely to remember in the future. - Jonathan M Davis
Mar 05 2018
On Monday, 5 March 2018 at 13:48:23 UTC, Adam D. Ruppe wrote:Just a semantic note, it is "straitjacket". "straight" is like a non-wiggly line. "strait" means narrow or constricted. Thus, the straitjacket is a jacket that constricts your movement. Of course, using "straight" is such a common mistake it has become generally accepted... but still, I like being precise with my words.You guys are a bunch of nerds . . . .
Mar 05 2018
On Monday, 5 March 2018 at 13:48:23 UTC, Adam D. Ruppe wrote:Just a semantic note, it is "straitjacket". "straight" is like a non-wiggly line. "strait" means narrow or constricted. Thus, the straitjacket is a jacket that constricts your movement. Of course, using "straight" is such a common mistake it has become generally accepted... but still, I like being precise with my words.You guys are a bunch of nerds . . . . - Me
Mar 05 2018
On Monday, 5 March 2018 at 13:48:23 UTC, Adam D. Ruppe wrote:Just a semantic note, it is "straitjacket". "straight" is like a non-wiggly line. "strait" means narrow or constricted. Thus, the straitjacket is a jacket that constricts your movement. Of course, using "straight" is such a common mistake it has become generally accepted... but still, I like being precise with my words.Programmers like precision, don't we! From Simon Tatham article about how to report bugs effectively: https://www.chiark.greenend.org.uk/~sgtatham/bugs.html "Above all, *be precise*. Programmers like precision."
Mar 05 2018
On Monday, 5 March 2018 at 10:57:35 UTC, Jonathan M Davis wrote:Here's something I wrote up on const:Excellent read! I enjoyed the history of proposed solutions. I've run into the trouble with annotated opEquals in classes several times. I believe an empty/nonexistant Object class is the correct solution, together with templates. If it breaks tricky opEquals-overriding usercode, then so be it. The const trouble is merely a symptom here, the real problem is Object. In structs, all const members feel alien, they preventing all copying. This seems far harder to solve. -- Simon
Mar 05 2018
On Monday, March 05, 2018 13:53:21 SimonN via Digitalmars-d-announce wrote:On Monday, 5 March 2018 at 10:57:35 UTC, Jonathan M Davis wrote:Yes, the fact that those functions are on Object is a serious problem that affects more than const, but part of the reason for explaining that particular issue was to show how the use of const - or the lack thereof - on a member function can have serious consequences for a class hierarchy. It's by far the worst in the case of Object, because it affects _all_ classes in D, but any time that someone designs a class in D that is intendend to then have other classes derived from it, the same choices pop up; the consequences are just then on a smaller scale.Here's something I wrote up on const:Excellent read! I enjoyed the history of proposed solutions. I've run into the trouble with annotated opEquals in classes several times. I believe an empty/nonexistant Object class is the correct solution, together with templates. If it breaks tricky opEquals-overriding usercode, then so be it. The const trouble is merely a symptom here, the real problem is Object.In structs, all const members feel alien, they preventing all copying. This seems far harder to solve.Yeah. I don't know what we do about that. In general, I think that it makes by far the most sense for value types to not be inherently const (even in part), so I'm not all that worried about the problems that stem from making a particular member variable const. But the fact that you then can't use a postblit constructor with a const object - even if nothing in the object is const unless the entire object is const - is definitely a problem. IIRC, Walter's take on it was that it was bad design for objects to deep-copy like that and that it was just better to use stuff like COW, in which case, postblit constructors aren't generally needed. And as such, he's a lot less worried about the problem than otherwise might be the case. I agree that it's frequently problematic for copying to be expensive in that manner, but it's also sometimes very useful. I expect that a good, solid DIP on the subject would be accepted in spite of the fact that Walter isn't big on postblit constructors, but first, someone has to come up with such a DIP, and that's not even vaguely easy - especially if the answer doesn't involve adding a copy constructor to the language (which I would guess would be rejected due the extra complexity that it would add to the language, but I don't know). Either way, right now, it's just one more thing on the list of things that makes it difficult enough to use const in D that many of us use it fairly minimally. - Jonathan M Davis
Mar 05 2018
On Monday, 5 March 2018 at 10:57:35 UTC, Jonathan M Davis wrote:Here's something I wrote up on const:So as to the main thrust, I generally agree. In fact, I think const is almost useless even if you want to use it fully: you said immutable is better in many places, and yes, but in addition to that, inout is better than const in most the remaining cases. Constructing a const variable? Almost completely useless - immutable is better in almost all (if not actually all) cases. Referencing function parameters? inout is better in all cases except just plain input. If there's any part of it being returned - as is the case on most member methods to me at least - inout is flat-out better. And then, of course, like you said "don't use it" is the solution to most of the const system's flaws anyway.... which seems to be the case with a lot of D's add-on qualifiers.
Mar 05 2018
On Monday, 5 March 2018 at 13:59:02 UTC, Adam D. Ruppe wrote:On Monday, 5 March 2018 at 10:57:35 UTC, Jonathan M Davis wrote:+1 The worst part of those add-on qualifiers is that the official gospel is that they are useful when in reality you HAVE to avoid them to be productive.Here's something I wrote up on const:And then, of course, like you said "don't use it" is the solution to most of the const system's flaws anyway.... which seems to be the case with a lot of D's add-on qualifiers.
Mar 06 2018
On Monday, 5 March 2018 at 10:57:35 UTC, Jonathan M Davis wrote:Here's something I wrote up on const: http://jmdavisprog.com/articles/why-const-sucks.html I suppose that it's not exactly the most positive article, but I feel that it's accurate. - Jonathan M DavisGreat read for a Monday.
Mar 05 2018
On Monday, 5 March 2018 at 10:57:35 UTC, Jonathan M Davis wrote:Here's something I wrote up on const: http://jmdavisprog.com/articles/why-const-sucks.html I suppose that it's not exactly the most positive article, but I feel that it's accurate. - Jonathan M DavisInteresting read and it explains some of the incomprehensible error messages. Basically you're saying we've got a strong const in D but essentially the situation is much like in Java because the general approach is don't use it ? Kind of ironic. I made a Logger module a couple years back and I used const very generously. Then came the moment where the LogWriters actually had to do the writing. One would assume that a function called 'stdio.write' mutates some state, but it sure as hell doesn't affect the state of my logger. DMD said: So soooowy! writeln not const-y, no can do, soooowy! So I remove const. One function at a time and end up with a module where basically no const remains. But it doesn't stop there. Since logger isn't const anymore, it now can't be used in any const functions. So more de-const-ification happened... Also, it's frustrating to have to get rid of const because Object.toString uses some Outputwriter thing which is not const and therefore transitively you can't have const anywhere else. Kind of a disappointing experience. As far as I'm concerned, it's not so much "don't use const; or, it's not worth it" but more like "I would if I could but I can't so I shan't". I bother with const as much as possible but it's incredible frustrating and I would argue the time lost to de-const-ify APIs is easily equivalent to a code breaking change that would make const more applicable. Something possimpible. Like a compiler that doesn't purely make decisions upon a const keyword, but one that can understand that interacting with some random function with only "in" parameters or objects, which aren't even interacting with,or are part of, the object's internal state and are just passed through, can't violate the const-ness of the object. But there's likely much more to consider than that and I couldn't ever dream of implementing such a thing..unfortunately
Mar 05 2018
Very interesting and well written! Jonathan, your experiences with const in C++/Java just about matches my experiences with it. I also feel that the situation in D is less than ideal in this regard. First, a small (for sure copy-pasta) typo in your article: const(int[]) arr1 = getArray(); const(int)[] arr2 = p1; //Sure you meant arr2 = arr1; Regarding the proposed solution to the issues with Object namely "the solution to this problem which was agreed to a few years ago was to remove opEquals, opCmp, toHash, and toString from Object so that derived classes can define them with whatever attributes are desired" which, you say, will never happen because of too much code breakage... What about the following? Currently the compiler is smart enough, so you can define class Foo and explicitly inherit from Object if you prefer: class Foo : Object {..} //OK, no recursive Object inherits Object ad-infinitum. Would it not be easier to exploit this and go the "opposite" way i.e. rather than remove it, just extend the hierarchy by adding a base class to Object itself (in object.d no less), something like this: class ObjectBase { interface Monitor{..} static ObjectBase factory(string classname){..} } class Object : ObjectBase { string toString(){..} size_t toHash() trusted nothrow{..} int opCmp(Object o){..} bool opEquals(Object o){..} static Object factory(string classname){..} } Now, if you do: class Foo{..} //OK. Still inherits from Object i.e. identical to 'class Foo : Object {..} class Foo : Object {..} //The same, just explicit //On the other hand: class Bar : ObjectBase //Deliberately bypass inheritance from Object. Inheritance from ObjectBase will have to be explicit (the price to pay for non-breakage!), but now class Bar is free to implement opEquals, opCmp, toHash, etc as it sees fit. This still guarantees back-wards compatibility since all classes currently inherited from Object have exactly the same semantics as they do today. No upgrades to any current projects/code required! Why was something like this not considered (you don't give a link, so I cannot investigate), rather than simply removing them from Object? Can this be exploited to, in effect, create the same opportunity but minus the breakage? Or am I missing something? Actually, in a more general sense I have begun to wonder if the common point of departure in D-land, that the concept of tail-const is actually a "part of" the concept of const, is not maybe wrong. We typically describe the concepts of tail/head-const "in terms of" const i.e. const in D 'equals' head-const 'plus' tail-const [1]. Since the concepts of tail-const and head-const are not that well known (outside of mostly C++-land), these 2 concepts are often utilized to differentiate D's concept of const, and explain it relative to the const (or final/sealed/readonly/etc) found in other languages. Maybe that muddles the water, and the 3 concepts, even though related, can semantically exist separately as well! I am of the opinion that we really need something like tail-const in D - particularly to semantically mark that the "payload" in a range is constant, but that the range itself can mutate. But it invariably falls apart when you try to shoehorn it into the general concept of const-ness in D with its transitivity properties, etc. The 2 concepts just don't gel, and I think the only way this can be accomplished is to have a separate semantic construct and syntax for tail-const. I think the 2 use cases are mostly orthogonal, and only overlapping in a narrow sense - but it this narrow sense that is used to explain it!. And, yes, the tail-const version will have less guarantees and none of the optimization opportunities that the current const version can promise. Of course I realize the changes of this being added to D is practically zero; So, yes, i have to concur with your conclusions as well! PS. BTW, your blog's title "The Long-Winded D Guy" is quite brilliant. You are indeed a bit long-winded, but you also take the time to explain things very thoroughly. It is a trade-off and I think in your case the cost-benefit ratio is positive. Thank you for that! Also, if you ever write a book (it might have to come in multiple volumes ;-), you can already count on having 1 buyer! [1] https://dlang.org/articles/const-faq.html#const
Mar 05 2018
On Monday, March 05, 2018 17:35:28 ShadoLight via Digitalmars-d-announce wrote:Very interesting and well written! Jonathan, your experiences with const in C++/Java just about matches my experiences with it. I also feel that the situation in D is less than ideal in this regard. First, a small (for sure copy-pasta) typo in your article: const(int[]) arr1 = getArray(); const(int)[] arr2 = p1; //Sure you meant arr2 = arr1;Thanks. Fixed.Regarding the proposed solution to the issues with Object namely "the solution to this problem which was agreed to a few years ago was to remove opEquals, opCmp, toHash, and toString from Object so that derived classes can define them with whatever attributes are desired" which, you say, will never happen because of too much code breakage... What about the following? Currently the compiler is smart enough, so you can define class Foo and explicitly inherit from Object if you prefer:...Why was something like this not considered (you don't give a link, so I cannot investigate), rather than simply removing them from Object? Can this be exploited to, in effect, create the same opportunity but minus the breakage? Or am I missing something?As I mentioned, there was recently some talk about creating a DIP to add a new root object below Object. If that's done, presumably, Object will still be the default to avoid code breakage, but it would be provide essentially what you're talking about. However, such a DIP still has to be written, so anything at this point is speculation as to what it's going to look like. At the time that it was decided to remove the functions from Object, it was more reasonable than it would be now (since D is definitely older now with a larger user base), and the details of how it would be done were never fully decided, which is part of why it's never come to fruition in spite of it being clear that we needed a root object without those functions. - Jonathan M Davis
Mar 05 2018
On Monday, 5 March 2018 at 10:57:35 UTC, Jonathan M Davis wrote:Here's something I wrote up on const: http://jmdavisprog.com/articles/why-const-sucks.html I suppose that it's not exactly the most positive article, but I feel that it's accurate. - Jonathan M DavisIts amazing how typed languages, in this case const, forces you to think in mutation but with an exception. I wonder the real world SOLE benefit of using const compared to mutable-immutable style. Its either mutable or immutable. Exception could only available by casting immutable to mutable. I feels this const thing is a theoretical problem. One can overcome practically with code style discipline. At a point, const becomes just a decoration; something people use prematurely (YAGNI). It must feel like sleeping on your bed with sharp knives hanging at the top such that they can fall on you anything: when comparing code in a typed language to an untyped one. That's a potential cause of premature use of certain type attributes. By the way, Jonathan, you should really consider writing a book with such deep insights your have. Especially the way you explain things.
Mar 06 2018
On Monday, 5 March 2018 at 10:57:35 UTC, Jonathan M Davis wrote:Here's something I wrote up on const: http://jmdavisprog.com/articles/why-const-sucks.html I suppose that it's not exactly the most positive article, but I feel that it's accurate. - Jonathan M DavisSpot on article, and touches some of my pain points when working with const/immutable structs. Recently I tried to create a ref-counted immutable struct, oh boi... This later use case is of tremendous value for safe concurrent code that's nogc. Unfortunately I couldn't find a way to make it work efficiently and in the same time not look like a disgusting hack. I suspect a possible solution is to allow immutable(const) postblit overloads as well as immutable dtors that will act as an escape hatch for unsafe work and in the same time provide hints that you are operating on an immutable(const) this.
Mar 06 2018
On Tuesday, 6 March 2018 at 10:02:10 UTC, Radu wrote:On Monday, 5 March 2018 at 10:57:35 UTC, Jonathan M Davis wrote:AFAIK this is a solved problem. Dicebot (not sure if he's still around) had initially proposed it: store the reference count just before the immutable piece of memory. | ref count | object/struct | In fact, Andrei added a new allocator to std.experimental.allocator to support this: https://dlang.org/library/std/experimental/allocator/building_blocks/affix_allocator/affix_allocator.prefix.htmlHere's something I wrote up on const: http://jmdavisprog.com/articles/why-const-sucks.html I suppose that it's not exactly the most positive article, but I feel that it's accurate. - Jonathan M DavisSpot on article, and touches some of my pain points when working with const/immutable structs. Recently I tried to create a ref-counted immutable struct, oh boi... This later use case is of tremendous value for safe concurrent code that's nogc. Unfortunately I couldn't find a way to make it work efficiently and in the same time not look like a disgusting hack. I suspect a possible solution is to allow immutable(const) postblit overloads as well as immutable dtors that will act as an escape hatch for unsafe work and in the same time provide hints that you are operating on an immutable(const) this.
Mar 06 2018
On Monday, 5 March 2018 at 10:57:35 UTC, Jonathan M Davis wrote (in the article):The problem is that the entire object must be fully initialized before the body of the postblit constructor is run. That means that any member variables which are const or immutable are stuck at whatever they were in the original object, because it would violate the type system to mutate them. And if an object is const or immutable, then that's all of the members.I think we have a misunderstanding here. According to that, this would not compile (imports left out): struct placeAtWorldMap { char[] title; int[2] coordsMicroDeg; this(this) { title = title.dup; } } void main() { char[] title = "London bridge".dup; const place = placeAtWorldMap(title, [51_508_038, -87_693]); const samePlace = place; "falling down ".copy(title); place.title.writeln; // falling down samePlace.title.writeln; // London bridge readln; } ...but it compiles and correctly runs, and I'm happy about that.
Mar 06 2018
On Tuesday, 6 March 2018 at 10:49:48 UTC, Dukc wrote:On Monday, 5 March 2018 at 10:57:35 UTC, Jonathan M Davis wrote (in the article):Quote from the article:The problem is that the entire object must be fully initialized before the body of the postblit constructor is run. That means that any member variables which are const or immutable are stuck at whatever they were in the original object, because it would violate the type system to mutate them. And if an object is const or immutable, then that's all of the members.I think we have a misunderstanding here. According to that, this would not compile (imports left out): struct placeAtWorldMap { char[] title; int[2] coordsMicroDeg; this(this) { title = title.dup; } } void main() { char[] title = "London bridge".dup; const place = placeAtWorldMap(title, [51_508_038, -87_693]); const samePlace = place; "falling down ".copy(title); place.title.writeln; // falling down samePlace.title.writeln; // London bridge readln; } ...but it compiles and correctly runs, and I'm happy about that.. That means that any member variables which are const or immutable are stuck at whatever they were in the original object, because it would violate the type system to mutate themMeaning that if you declare your `title` member `const char[] title`, you can't change it in the postblit, but you could set it in the constructor. ``` import std.array; import std.stdio; import std.algorithm; struct placeAtWorldMap { const char[] title; int[2] coordsMicroDeg; this(char[] name) { this.title = name.idup; // you can assign const members here } this(char[] name, int[2] coords) { this.title = name; this.coordsMicroDeg = coords; } this(this) {// title = title.dup; // doesn't work anymore } } void main() { char[] title = "London bridge".dup; const place = placeAtWorldMap(title, [51_508_038, -87_693]); const newPlace = placeAtWorldMap("Big Ben".dup); const samePlace = place; "falling down ".copy(title); place.title.writeln; // falling down samePlace.title.writeln; // London bridge newPlace.title.writeln; // Big Ben } ```
Mar 06 2018
On Tuesday, 6 March 2018 at 11:03:24 UTC, Nemanja Boric wrote:title = title.dup; // doesn't work anymoreStrange! You're right it does not when the type declares a member as const, yet:...does not prevent the postblit from working whenthe object is declared const by user. I think we have a bug here. I believe postblits should behave like constructors in both events.On Monday, 5 March 2018 at 10:57:35 UTC, Jonathan M Davis wrote (in the article):And if an object is const or immutable, then that's all of the members.
Mar 06 2018
On Tuesday, 6 March 2018 at 12:05:26 UTC, Dukc wrote:I think we have a bug here. I believe postblits should behave like constructors in both events.https://issues.dlang.org/show_bug.cgi?id=18561
Mar 06 2018
On Monday, 5 March 2018 at 10:57:35 UTC, Jonathan M Davis wrote:Here's something I wrote up on const: /snipMay be not entirely related, but a little gotcha. given: interface XY {} class Foo: XY {} class Bar: XY {} void doSomething(in XY sth) { auto foo = cast(Foo)sth; // error in safe code } But the compiler doesn't emit a warning that const got cast away in system code. Since system is the default setting and casting const away is by definition undefined behavior, there should be some feedback. If you cast away const in C++ you need to be explicit about it by using const_cast, documents the intention rather than D's swiss-army-cast.
Mar 08 2018
On 3/8/18 9:58 AM, joe wrote:On Monday, 5 March 2018 at 10:57:35 UTC, Jonathan M Davis wrote:This is a problem with the cast system, not const. D has one cast mechanism, and it's used to: a) dynamic type cast b) hook user-supplied opCast c) enter undefined behavior by casting away const/immutable. I really think we should have a separate mechanism for a and b, as they are far less dangerous than c. std.conv.to does this as well, but the language should have some safeguards against using "safe casting" incorrectly. -SteveHere's something I wrote up on const: /snipMay be not entirely related, but a little gotcha. given: interface XY {} class Foo: XY {} class Bar: XY {} void doSomething(in XY sth) { auto foo = cast(Foo)sth; // error in safe code } But the compiler doesn't emit a warning that const got cast away in system code. Since system is the default setting and casting const away is by definition undefined behavior, there should be some feedback. If you cast away const in C++ you need to be explicit about it by using const_cast, documents the intention rather than D's swiss-army-cast.
Mar 08 2018
On Thursday, 8 March 2018 at 15:13:09 UTC, Steven Schveighoffer wrote:On 3/8/18 9:58 AM, joe wrote:I figured. Sorry for off topic.On Monday, 5 March 2018 at 10:57:35 UTC, Jonathan M Davis wrote:This is a problem with the cast system, not const. ...Here's something I wrote up on const: /snipMay be not entirely related, but a little gotcha. given: interface XY {} class Foo: XY {} class Bar: XY {} void doSomething(in XY sth) { auto foo = cast(Foo)sth; // error in safe code } But the compiler doesn't emit a warning that const got cast away in system code. Since system is the default setting and casting const away is by definition undefined behavior, there should be some feedback. If you cast away const in C++ you need to be explicit about it by using const_cast, documents the intention rather than D's swiss-army-cast.... D has one cast mechanism, and it's used to: a) dynamic type cast b) hook user-supplied opCast c) enter undefined behavior by casting away const/immutable. I really think we should have a separate mechanism for a and b, as they are far less dangerous than c. std.conv.to does this as well, ...Thanks for pointing this out....but the language should have some safeguards against using "safe casting" incorrectly. -Steveyes, that's what I was aiming for :) This one got me because I assumed, with all the improved security in place, D would never silently do such a thing... Assumptions, right? ...the root of all evil. I should know better. haha. Anyways, thanks for the insight and have a nice Sunday.
Mar 11 2018