Added copy constructors to "Programming in D"

Ali Çehreli acehreli at yahoo.com
Thu Feb 10 02:39:11 UTC 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)
 >
 > ...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



More information about the Digitalmars-d-announce mailing list