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