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

Reply via email to