www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.announce - Added copy constructors to "Programming in D"

reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
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
next sibling parent Tejas <notrealemail gmail.com> writes:
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
prev sibling next sibling parent reply Imperatorn <johan_forsberg_86 hotmail.com> writes:
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
next sibling parent reply Andrea Fontana <nospam example.org> writes:
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:


 http://ddili.org/ders/d.en/special_functions.html#ix_special_functions.copy%20constructor

 [...]
Splendid! 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 13
parent Martin Tschierschke <mt smartdolphin.de> writes:
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
prev sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 1/8/22 05:23, 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:

 
http://ddili.org/ders/d.en/special_functions.html#ix_special_function .copy%20constructor
 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
parent Imperatorn <johan_forsberg_86 hotmail.com> writes:
On Thursday, 27 January 2022 at 15:30:02 UTC, Ali Çehreli wrote:
 On 1/8/22 05:23, Imperatorn wrote:
 [...]
wrote:
 [...]
constructors:
 [...]
http://ddili.org/ders/d.en/special_functions.html#ix_special_functions.copy%20constructor [...]
Wonderful, thanks for your highly valuable contributions
Jan 27
prev sibling next sibling parent reply Stanislav Blinov <stanislav.blinov gmail.com> writes:
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
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 1/8/22 5:49 AM, Stanislav Blinov wrote:

 Of course, now I stress that postblit is discouraged.
Bit early, methinks. Copy ctors aren't even fully supported by the runtime 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
next sibling parent Stanislav Blinov <stanislav.blinov gmail.com> writes:
On Saturday, 8 January 2022 at 16:24:03 UTC, Ali Çehreli wrote:
 On 1/8/22 5:49 AM, Stanislav Blinov wrote:

 Of course, now I stress that postblit is discouraged.
Bit early, methinks. Copy ctors aren't even fully supported
by the
 runtime 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
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"?
Jan 08
prev sibling parent vit <vit vit.vit> writes:
On Saturday, 8 January 2022 at 16:24:03 UTC, Ali Çehreli wrote:
 On 1/8/22 5:49 AM, Stanislav Blinov wrote:

 Of course, now I stress that postblit is discouraged.
Bit early, methinks. Copy ctors aren't even fully supported
by the
 runtime 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
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.org
Jan 08
prev sibling next sibling parent Ferhat =?UTF-8?B?S3VydHVsbXXFnw==?= <aferust gmail.com> writes:
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
prev sibling parent reply Anonymouse <zorael gmail.com> writes:
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
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 2/9/22 02:15, Anonymouse wrote:
 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.
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. Ali
Feb 09
next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
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
prev sibling parent reply Meta <jared771 gmail.com> writes:
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
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
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)

 ...oh
I 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
parent reply Mathias LANG <geod24 gmail.com> writes:
On Thursday, 10 February 2022 at 02:39:11 UTC, Ali Çehreli wrote:
 Yeah, that issue bugs me a little.

 Ali
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`; 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
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
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
next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 2/10/2022 12:34 PM, Walter Bright wrote:
 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.
By the way, `cast()ptr` will peal off the outermost const/immutable/etc from the type.
Feb 10
prev sibling parent reply Meta <jared771 gmail.com> writes:
On Thursday, 10 February 2022 at 20:34:29 UTC, Walter Bright 
wrote:
 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.
Didn't Scott Meyers cover exactly this in his "the last thing D needs" talk? It seems like a really bad idea.
Feb 10
parent reply bauss <jj_1337 live.dk> writes:
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:
 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.
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
parent Abdulhaq <alynch4047 gmail.com> writes:
On Friday, 11 February 2022 at 10:06:32 UTC, bauss wrote:

 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.
Rumours that Ali's next book will be called "Effective D++" are..... true ;-)
Feb 11
prev sibling parent Elronnd <elronnd elronnd.net> writes:
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