digitalmars.D.announce - Added copy constructors to "Programming in D"
- =?UTF-8?Q?Ali_=c3=87ehreli?= (19/19) Jan 07 2022 1) After about three years, I finally added copy constructors:
- Tejas (3/6) Jan 07 2022 Thank you very much for creating and maintaining such an amazing
- Imperatorn (4/7) Jan 08 2022 Splendid!
- Andrea Fontana (3/13) Jan 13 2022 I don't think it is possible. You have to buy a new copy when
- Martin Tschierschke (4/12) Jan 14 2022 [...]
- =?UTF-8?Q?Ali_=c3=87ehreli?= (18/23) Jan 27 2022 Yes, now all copies are updated:
- Imperatorn (2/10) Jan 27 2022 Wonderful, thanks for your highly valuable contributions
- Stanislav Blinov (3/6) Jan 08 2022 Bit early, methinks. Copy ctors aren't even fully supported by
- =?UTF-8?Q?Ali_=c3=87ehreli?= (5/8) Jan 08 2022 Thanks. The spec discourages postblit as well. What's the best of saying...
- Stanislav Blinov (9/20) Jan 08 2022 They are all, most certainly, bugs. But they're there ever since
- vit (10/21) Jan 08 2022 Bugs, for example:
- Ferhat =?UTF-8?B?S3VydHVsbXXFnw==?= (2/5) Jan 08 2022 Good to see you keep it up to date.
- Anonymouse (3/6) Feb 09 2022 I'm curious, could you elaborate a bit on this? I skimmed through
- =?UTF-8?Q?Ali_=c3=87ehreli?= (66/72) Feb 09 2022 To make sure we are looking at the same version, the new content has the...
- H. S. Teoh (85/88) Feb 09 2022 [...]
- Meta (10/10) Feb 09 2022 Why do we even bother with `in` when we can do:
- =?UTF-8?Q?Ali_=c3=87ehreli?= (52/62) Feb 09 2022 I didn't know that but 'in' is underrated. There is heavy mental load on...
- Mathias LANG (33/35) Feb 10 2022 I think an *immediate* improvement we could make to ease people's
- Walter Bright (2/17) Feb 10 2022 It sounds sensible to me.
- Walter Bright (3/21) Feb 10 2022 By the way, `cast()ptr` will peal off the outermost const/immutable/etc ...
- Meta (4/23) Feb 10 2022 Didn't Scott Meyers cover exactly this in his "the last thing D
- Elronnd (2/3) Feb 10 2022 Shouldn't do that for class references. Otherwise seems fine.
1) After about three years, I finally added copy constructors: http://ddili.org/ders/d.en/special_functions.html#ix_special_functions.copy%20constructor Of course, now I stress that postblit is discouraged. 2) The other noteworthy change in the book is my now-different stance on variables: Now I recommend 'const' over 'immutable' for variables. And I favor 'in' for parameters over 'const'. (Unfortunately, not all code in the book follow those guidelines.) And I recommend the -preview=in command line switch: http://ddili.org/ders/d.en/function_parameters.html#ix_function_parameters.in,%20parameter 3) I've updated all electronic formats: PDF, EPUB, AZW3, and MOBI: http://ddili.org/ders/d.en/ I had some trouble with ebooks in the past: The fonts would not work and table of contents would not be generated. Please let me know if you see something wrong. WARNING: The paper book publishers are not updated yet. If you order a paper book now, you will get the old book. (I think from December 2020.) Ali
Jan 07 2022
On Saturday, 8 January 2022 at 02:07:10 UTC, Ali Çehreli wrote:1) After about three years, I finally added copy constructors: http://ddili.org/ders/d.en/special_functions.html#ix_special_functions.copy%20constructor [...]Thank you very much for creating and maintaining such an amazing resource for newcomers to D and programming in general :D
Jan 07 2022
On Saturday, 8 January 2022 at 02:07:10 UTC, Ali Çehreli wrote:1) After about three years, I finally added copy constructors: http://ddili.org/ders/d.en/special_functions.html#ix_special_functions.copy%20constructor [...]Splendid! Will the physical book also be updated? Thanks!
Jan 08 2022
On Saturday, 8 January 2022 at 13:23:52 UTC, Imperatorn wrote:On Saturday, 8 January 2022 at 02:07:10 UTC, Ali Çehreli wrote:I don't think it is possible. You have to buy a new copy when published. /s1) After about three years, I finally added copy constructors: http://ddili.org/ders/d.en/special_functions.html#ix_special_functions.copy%20constructor [...]Splendid! Will the physical book also be updated? Thanks!
Jan 13 2022
On Thursday, 13 January 2022 at 09:21:46 UTC, Andrea Fontana wrote:On Saturday, 8 January 2022 at 13:23:52 UTC, Imperatorn wrote:[...]On Saturday, 8 January 2022 at 02:07:10 UTC, Ali Çehreli wrote:1) After about three years, I finally added copy constructors:🤣🤣🤣Will the physical book also be updated? Thanks!I don't think it is possible. You have to buy a new copy when published. /s
Jan 14 2022
On 1/8/22 05:23, Imperatorn wrote:On Saturday, 8 January 2022 at 02:07:10 UTC, Ali Çehreli wrote:http://ddili.org/ders/d.en/special_functions.html#ix_special_function .copy%20constructor1) After about three years, I finally added copy constructors:Will the physical book also be updated?Yes, now all copies are updated: - Hardcopy by IngramSpark - Paperback by IngramSpark and KDP (I checked on Amazon, the "Look Inside" feature shows the new content (at least the COpyright page)) - Ebooks on KDP, GumRoad, and Draft2Digital There are three years' worth of corrections and edits as well. I've also removed the "First Edition" misnomer from the book; it is obviously continuosly updated. An of course, everything is free here: http://ddili.org/ders/d.en I have a minor update to that page as well, which should be live soon. Aside: The D Language Foundation has an Amazon Associate link to the book: https://www.amazon.com/dp/1515074609?&tag=dlang-20 And many other ways to take donations: https://dlang.org/foundation/donate.html Ali
Jan 27 2022
On Thursday, 27 January 2022 at 15:30:02 UTC, Ali Çehreli wrote:On 1/8/22 05:23, Imperatorn wrote:Wonderful, thanks for your highly valuable contributions[...]wrote:constructors:[...]http://ddili.org/ders/d.en/special_functions.html#ix_special_functions.copy%20constructor [...][...]
Jan 27 2022
On Saturday, 8 January 2022 at 02:07:10 UTC, Ali Çehreli wrote:1) After about three years, I finally added copy constructors: http://ddili.org/ders/d.en/special_functions.html#ix_special_functions.copy%20constructor Of course, now I stress that postblit is discouraged.Bit early, methinks. Copy ctors aren't even fully supported by the runtime yet.
Jan 08 2022
On 1/8/22 5:49 AM, Stanislav Blinov wrote:Thanks. The spec discourages postblit as well. What's the best of saying it then? Something like "There are still limitations of copy constructors as of this writing." Or there are just bugs? AliOf course, now I stress that postblit is discouraged.Bit early, methinks. Copy ctors aren't even fully supported by the runtime yet.
Jan 08 2022
On Saturday, 8 January 2022 at 16:24:03 UTC, Ali Çehreli wrote:On 1/8/22 5:49 AM, Stanislav Blinov wrote:They are all, most certainly, bugs. But they're there ever since copy ctors have been introduced, and with no clear perspective on when they're going to be fixed. Some are pretty nasty - https://issues.dlang.org/show_bug.cgi?id=22614 . Spec recommending to switch to copy ctors is... dubious - what's the point if you can't even dup an array correctly?.. Maybe something like "Support for copy constructors hasn't been fully integrated into the D runtime library yet"?by theOf course, now I stress that postblit is discouraged.Bit early, methinks. Copy ctors aren't even fully supportedruntime yet.Thanks. The spec discourages postblit as well. What's the best of saying it then? Something like "There are still limitations of copy constructors as of this writing." Or there are just bugs? Ali
Jan 08 2022
On Saturday, 8 January 2022 at 16:24:03 UTC, Ali Çehreli wrote:On 1/8/22 5:49 AM, Stanislav Blinov wrote:Bugs, for example: When appending to dynamic array reallocate memory, then copy ctors are ignored. Assignment of static arrays doesn't call copy constructor for elements. dup/idup doesn't call copy constructors... This is necessary to fix it: [SAoC 2021] Replace druntime Hooks with Templates https://forum.dlang.org/thread/flwjoxilxfpvdjheehdg forum.dlang.orgby theOf course, now I stress that postblit is discouraged.Bit early, methinks. Copy ctors aren't even fully supportedruntime yet.Thanks. The spec discourages postblit as well. What's the best of saying it then? Something like "There are still limitations of copy constructors as of this writing." Or there are just bugs? Ali
Jan 08 2022
On Saturday, 8 January 2022 at 02:07:10 UTC, Ali Çehreli wrote:1) After about three years, I finally added copy constructors: http://ddili.org/ders/d.en/special_functions.html#ix_special_functions.copy%20constructor [...]Good to see you keep it up to date.
Jan 08 2022
On Saturday, 8 January 2022 at 02:07:10 UTC, Ali Çehreli wrote:2) The other noteworthy change in the book is my now-different stance on variables: Now I recommend 'const' over 'immutable' for variables.I'm curious, could you elaborate a bit on this? I skimmed through the page on Immutability but I didn't find anything explaining it.
Feb 09 2022
On 2/9/22 02:15, Anonymouse wrote:On Saturday, 8 January 2022 at 02:07:10 UTC, Ali Çehreli wrote:To make sure we are looking at the same version, the new content has the following section: <quote> in parameters As we will see in the next chapter, in implies const and is more useful with the ‑preview=in command line switch. For that reason, I recommend in parameters over const parameters. </quote> http://ddili.org/ders/d.en/const_and_immutable.html In short, in the past, under the influence of "stronger guarantee" clearly sounding better, I was recommending immutable for variables: immutable i = 42; Realizing that I don't do that in my own code, now I recommend const: const i = 42; Further, now that we have -preview=in (thanks to Mathias Lang), I recommend 'in' over const for parameters. (Actually, I had always recommended 'in' and did use it in some of the examples in the book (inconsistently) but I wasn't using it in my own code.) But the whole thing is complicated. :) So, I asked for and received opinions on this thread: https://forum.dlang.org/thread/sig2d4$657$1 digitalmars.com I don't find the common description helpful: "immutable provides stronger guarantee." That's true and sounds better than mere "strong" but it does not help a programmer with deciding on which one to use. Rather, I like the following distinction: - const is a promise - immutable is a requirement Now, that helps me decide which one to use when. Let's start with a function: void foo(in A a, immutable B b) { // ... } There, foo "promises" to not mutate 'a' ('in' implies 'const') and "requires" that 'b' is not mutated by any other code. With that understanding, it is silly to "require" that no other code mutates a local variable: void x() { immutable b = B(); // Really? Who can mutate it? // ... } So, the following is logical (and shorter :) ): void x() { const b = B(); // ... } Now, if I need to pass it to a function that "requires" immutable, of course I will have to define it as immutable to satisfy that requirement: void x() { immutable b = B(); foo(A(), b); // ... } Aside: One of the confusions is that 'const' would work there as well *if* B did not have any indirection. But if it's defined as e.g. struct B { int[] arr; } then, x() will not compile with 'const b'. In summary: Variables: 'const' by default, 'immutable' as needed (because somebody requires it) Parameters: 'in' by default, 'immutable' if required That's my view. I think there are others who disagree with parts of it and that's why this issue is surprisingly complicated. Ali2) The other noteworthy change in the book is my now-different stance on variables: Now I recommend 'const' over 'immutable' for variables.I'm curious, could you elaborate a bit on this? I skimmed through the page on Immutability but I didn't find anything explaining it.
Feb 09 2022
On Wed, Feb 09, 2022 at 10:28:15AM -0800, Ali Çehreli via Digitalmars-d-announce wrote: [...]- const is a promise - immutable is a requirement[...] Strictly speaking, that's not really an accurate description. :-P A more accurate description would be: - const: I cannot modify the data (but someone else might). - immutable: I cannot modify the data, AND nobody else can either. The best way I've found to understand the relationship between const, immutable, and mutable in D is the following "type inheritance" diagram (analogous to a class inheritance diagram): const / \ (mutable) immutable Const behaves like the "base class" (well, base type, sortof) that either mutable or immutable can implicitly convert to. Mutable and immutable, however, are mutually incompatible "derived classes" that will not implicitly convert to each other. (Of course, the reality is somewhat more complex than this, but this is a good, simple conceptual starting point to understanding D's type system.) Const means whoever holds the reference to the data cannot modify it. So it's safe to hand them both mutable and immutable data. Mutable means you are allowed to modify it, so obviously it's illegal to pass in const or immutable. Passing mutable to const is OK because the recipient cannot modify it, even though the caller himself may (since he holds a mutable reference to it). Immutable means NOBODY can modify it, not even the caller. I.e., *nobody* holds a mutable reference to the data. So you cannot pass mutable to immutable. Obviously, it's safe to pass immutable to const (the callee cannot modify it anyway, so we're OK). But you cannot pass const to immutable, because, as stated above, a const reference might be pointing to mutable data: even though the holder of the reference cannot himself modify it, it may have come from a mutable reference somewhere else. Allowing it would break the rule that immutable means *nobody* has a mutable reference to the data. So that's not allowed. IOW, "downcasting" in the above "type hierarchy" is not allowed, in general. However, there's a special case where mutable does implicitly convert to mutable: this is if the mutable reference is unique, meaning that it's the only reference that exists to that data. In such a case, it's OK to convert that mutable reference to an immutable one, provided the mutable reference immediately goes out of scope. After that point, nobody holds a mutable reference to it anymore, so it fits into the definition of immutable. This happens when a mutable reference is returned from a pure function: MyData createData() pure { MyData result; // N.B.: mutable return result; // mutable reference goes out of scope } // OK: function is pure and reference to data is unique immutable MyData data = createData(); The `pure` ensures that createData didn't cheat and store a mutable reference to the data in some global variable, so the reference to MyData that it returns is truly unique. So in this case we allow mutable to implicitly convert to immutable. There's also another situation where immutable is allowed to implicitly convert to mutable: this is when the data is a by-value type containing no indirections. Essentially, we're making a copy of the immutable data, so it doesn't matter if we modify the copy, since we're not actually modifying the original data. // Now, w.r.t. the original question of when we should use const vs. immutable: - For local variables, there's no practical difference between const and immutable, because by definition the current function holds the only reference to it, so there can't be any mutable reference to it. I would just use immutable in this case -- the compiler may be able to optimize the code better knowing that there can't be any mutable reference anywhere else (though in theory the compiler should have already figured this out, since it's a local variable). - For function parameters, I would always use const over immutable, unless there was a reason I want to guarantee that nobody else holds a mutable reference to that argument (e.g., I'm storing the reference in a data structure that requires the data not to be mutated afterwards). Using const makes the function usable with both mutable and immutable arguments, which is more flexible when you don't need to guarantee that the data will never be changed by anybody. Some people may prefer `in` instead of const for function parameters: it's more self-documenting, and if you use -preview=in, it means `const scope`, which adds an additional check that you don't accidentally leak reference to parameters past the scope of the function. T -- Windows 95 was a joke, and Windows 98 was the punchline.
Feb 09 2022
Why do we even bother with `in` when we can do: alias In(T) = const scope T; void test(In!int n) { pragma(msg, typeof(n)); } ? onlineapp.d(3): Deprecation: storage class `scope` has no effect in type aliases const(int) ...oh
Feb 09 2022
On 2/9/22 18:11, Meta wrote:Why do we even bother with `in` when we can do: alias In(T) = const scope T; void test(In!int n) { pragma(msg, typeof(n)); } ? onlineapp.d(3): Deprecation: storage class `scope` has no effect in type aliases const(int) ...ohI didn't know that but 'in' is underrated. There is heavy mental load on deciding parameter types: // Silly const: void foo(const(int)); // Too much information to the user (why // do they need to know that I will mutate the parameter): void foo(int); // When I know that copying is expensive // (which excludes rvalues; oops): void foo(ref const(ExpensiveToCopy)); // When I know that the type is non-copyable, // I have to use 'ref': void foo(ref const(NonCopyable)); What if foo is a template? ref or const or by-value? Or inout? Always or sometimes? Enough already! :) All I want to say is "I want to use this parameter as input." I don't care if its rvalue or expensive to copy or impossible to copy. I will define it as 'ref' if that's what I want but I shouldn't be thinking about any of the above for function inputs. I am happy to raise awareness of the new 'in': https://dlang.org/spec/function.html#in-params 'in' allows passing rvalues by ref! 'in' eliminates unwanted side-effects just because a function wants to use an object. 'in' passes non-copyable types by reference. Wow! That's engineering to my ears. :) Having said that, there is one thing that bothers me with 'in' or 'const'. Let's assume I want to mutate a copy of the parameter: void foo(in int i) { ++i; // ERROR } So I must make a copy: auto j = i; ++j; // ERROR Because 'auto' is too safe and takes 'const'. One more try: int j = i; ++j; Or perhaps in some generic code: import std.traits : Unqual; Unqual!(typeof(i)) j = i; ++j; Ok, fine. One more thing remains: Although 'i' may be the most logical name for the parameter, I cannot name 'j' as 'i' so I can mangle the parameter name just to prevent using 'i' in the function by accident: void foo(in int i_); That's not good because it changes what my callers see of my function. I can use 'i_' in the body (instead of 'j') but then I am open to the same mistake of using 'i' instead of 'i_' in the body. (Obviously not when mutating but when actually using.) Yeah, that issue bugs me a little. Ali
Feb 09 2022
On Thursday, 10 February 2022 at 02:39:11 UTC, Ali Çehreli wrote:Yeah, that issue bugs me a little. AliI think an *immediate* improvement we could make to ease people's life is to make `auto` peel the outermost qualifier level inside functions. So that: ```D const int* ptr; auto p2 = ptr; static assert(is(typeof(p2) == const(int)*)); ``` I really can't think of any downside to it, only upsides: - It is still predictable / consistent; - It *might* reduce the number of template instantiations in some cases; - It just flows more naturally... If you want full constness, there's still `const`; Likewise, I've been tinkering with having `const* p2 = ptr` to allow `p2` to be mutated. But it has far more implications and the benefits aren't as clear. For `auto`, I think the case is pretty straightforward. Fun fact: C++ mangling actually does that. ```D extern(C++) void foo (const int a); extern(C++) void bar (int a); pragma(msg, foo.mangleof); // _Z3fooi not _Z3fooKi pragma(msg, bar.mangleof); // _Z3bari ``` P.S: Thanks for spreading the love about `-preview=in`. I haven't moved forward with enabling it by default yet, because it just does exactly what we want it to do and has never bothered us, so we tend to forget it's not the default. I shall however start to move ahead now that the switch has been available for a few releases.
Feb 10 2022
On 2/10/2022 12:06 AM, Mathias LANG wrote:I think an *immediate* improvement we could make to ease people's life is to make `auto` peel the outermost qualifier level inside functions. So that: ```D const int* ptr; auto p2 = ptr; static assert(is(typeof(p2) == const(int)*)); ``` I really can't think of any downside to it, only upsides: - It is still predictable / consistent; - It *might* reduce the number of template instantiations in some cases; - It just flows more naturally... If you want full constness, there's still `const`;It sounds sensible to me.
Feb 10 2022
On 2/10/2022 12:34 PM, Walter Bright wrote:On 2/10/2022 12:06 AM, Mathias LANG wrote:By the way, `cast()ptr` will peal off the outermost const/immutable/etc from the type.I think an *immediate* improvement we could make to ease people's life is to make `auto` peel the outermost qualifier level inside functions. So that: ```D const int* ptr; auto p2 = ptr; static assert(is(typeof(p2) == const(int)*)); ``` I really can't think of any downside to it, only upsides: - It is still predictable / consistent; - It *might* reduce the number of template instantiations in some cases; - It just flows more naturally... If you want full constness, there's still `const`;It sounds sensible to me.
Feb 10 2022
On Thursday, 10 February 2022 at 20:34:29 UTC, Walter Bright wrote:On 2/10/2022 12:06 AM, Mathias LANG wrote:Didn't Scott Meyers cover exactly this in his "the last thing D needs" talk? It seems like a really bad idea.I think an *immediate* improvement we could make to ease people's life is to make `auto` peel the outermost qualifier level inside functions. So that: ```D const int* ptr; auto p2 = ptr; static assert(is(typeof(p2) == const(int)*)); ``` I really can't think of any downside to it, only upsides: - It is still predictable / consistent; - It *might* reduce the number of template instantiations in some cases; - It just flows more naturally... If you want full constness, there's still `const`;It sounds sensible to me.
Feb 10 2022
On Thursday, 10 February 2022 at 23:21:50 UTC, Meta wrote:On Thursday, 10 February 2022 at 20:34:29 UTC, Walter Bright wrote:Well D has already taken the piss on that talk a long time ago. No offense to D overall, and I still love it.On 2/10/2022 12:06 AM, Mathias LANG wrote:Didn't Scott Meyers cover exactly this in his "the last thing D needs" talk? It seems like a really bad idea.I think an *immediate* improvement we could make to ease people's life is to make `auto` peel the outermost qualifier level inside functions. So that: ```D const int* ptr; auto p2 = ptr; static assert(is(typeof(p2) == const(int)*)); ``` I really can't think of any downside to it, only upsides: - It is still predictable / consistent; - It *might* reduce the number of template instantiations in some cases; - It just flows more naturally... If you want full constness, there's still `const`;It sounds sensible to me.
Feb 11 2022
On Friday, 11 February 2022 at 10:06:32 UTC, bauss wrote:Rumours that Ali's next book will be called "Effective D++" are..... true ;-)Didn't Scott Meyers cover exactly this in his "the last thing D needs" talk? It seems like a really bad idea.Well D has already taken the piss on that talk a long time ago. No offense to D overall, and I still love it.
Feb 11 2022
On Thursday, 10 February 2022 at 08:06:23 UTC, Mathias LANG wrote:make `auto` peel the outermost qualifier level inside functions.Shouldn't do that for class references. Otherwise seems fine.
Feb 10 2022