Thread overview
simple definition of "in" function parameters, and default "ref"
Oct 27, 2018
John Nixon
Oct 27, 2018
Stanislav Blinov
Oct 27, 2018
Jonathan M Davis
Oct 27, 2018
John Nixon
Oct 27, 2018
12345swordy
Oct 27, 2018
Jonathan M Davis
Oct 28, 2018
Adam D. Ruppe
October 27, 2018
I have just read that the storage class "in" for function parameters has not yet been properly implemented. From its simple meaning as a one-way flow of information into a function from the calling function, surely it should be implemented by copying the argument, as is now done by default for all function arguments. Note this has a distinct meaning from the far more restrictive "const" that enforces the variable to remain constant throughout its lifetime while the called function is running. It would then naturally complement "out" and provide a simple semantics in the function signature to aid program design.
It would also make it simpler if there was no difference between the behaviour of reference and value types in function parameters with default passing by reference. This would make the storage class "none" correspond to "in" and "out". At present if this is wanted, sometimes the keyword "ref" has to be used, and sometimes it is not necessary (depending on whether the type is value or reference).
A simplified language would make it easier to develop programs to check programmer's code.

October 27, 2018
On Saturday, 27 October 2018 at 11:48:55 UTC, John Nixon wrote:
> I have just read that the storage class "in" for function parameters has not yet been properly implemented. From its simple meaning as a one-way flow of information into a function from the calling function, surely it should be implemented by copying the argument, as is now done by default for all function arguments.

```
void foo(T)(in T value) { /* ... */ }

int i;
Object o;

// 1
foo(&i);
// 2
foo(o);
```

Are you suggesting that for (1), typeof(value) in foo should be `int*`? And that for (2) typeof (value) in foo should be `Object`? This can't work. You can't implicitly "copy" a pointee or a referree, you can only copy the respective bits of the pointer/reference. If you do that and strip `const` from the argument, you're left with a non-const pointer or reference, respectively, which would make `in` pointless.

From the spec (https://dlang.org/spec/function.html#param-storage):
"[in] defined as scope const. However in has not yet been properly implemented so it's current implementation is equivalent to const. It is recommended to avoid using in until it is properly defined and implemented. Use scope const or const explicitly instead."

Translation: a long time ago, `in` was supposed to be a shorthand for `const scope`. Later on Walter in his patches started treating `in` as just `const`, as doing otherwise would "break too much [third-party user] code". Current wording indicates that that could've been a mistake.

> It would also make it simpler if there was no difference between the behaviour of reference and value types in function parameters with default passing by reference.

Now that is a catastrophe-breaking-change suggestion if I've ever seen one.
October 27, 2018
On Saturday, October 27, 2018 5:48:55 AM MDT John Nixon via Digitalmars-d wrote:
> I have just read that the storage class "in" for function
> parameters has not yet been properly implemented. From its simple
> meaning as a one-way flow of information into a function from the
> calling function, surely it should be implemented by copying the
> argument, as is now done by default for all function arguments.
> Note this has a distinct meaning from the far more restrictive
> "const" that enforces the variable to remain constant throughout
> its lifetime while the called function is running. It would then
> naturally complement "out" and provide a simple semantics in the
> function signature to aid program design.
> It would also make it simpler if there was no difference between
> the behaviour of reference and value types in function parameters
> with default passing by reference. This would make the storage
> class "none" correspond to "in" and "out". At present if this is
> wanted, sometimes the keyword "ref" has to be used, and sometimes
> it is not necessary (depending on whether the type is value or
> reference).
> A simplified language would make it easier to develop programs to
> check programmer's code.

in was supposed to be identical to const scope. However, scope has never really done much aside for delegates and was not very well defined, so it's pretty much just been the same as const. Lots of people have used it either because they liked the idea that it was the counterpart to out or because they thought that they understood what how it was supposed to work and wanted whatever behavior that was, but it wasn't actually properly defined and has always just been the same as const for everything other than delegates. So, arguably, no one should have been using it, but lots of people have been.

However, DIP 1000 actually defines what scope means and makes it work for more than just delegates, and the result would be that making in actually mean const scope as originally intended would then break a _lot_ of code. _Some_ of that code should be broken, because the author used scope in a way that's close enough to what scope is actually going to mean that the fact that the code doesn't compile would mean that a bug will have been caught, but in the vast majority of cases, in was used without a proper understanding of what it would mean - especially since scope was not properly defined, and as it is, now that scope _does_ have a proper definition with DIP 1000, most people don't understand it very well outside of simple examples, meaning that it's hard to correctly write code that uses scope with -dip1000 even now. So, it's _highly_ unlikely that existing code using in is using it in a way that's going to be compatible with scope. So, the current plan is for in to remain as const rather than to become const scope, because it would mean far less code breakage. Some people are not very happy about that, and the plan may yet change, but either way, there's pretty much no way that in is going to be changed to mean something else entirely at this point. Doing so would break even more code than actually making it mean const scope as originally intended would.

- Jonathan M Davis



October 27, 2018
Thank you for both the detailed explanations in reply to my post. They are in places a little over my head. My motivation was to make D semantically as simple as possible. John Nixon

October 27, 2018
On Saturday, 27 October 2018 at 13:28:20 UTC, Jonathan M Davis wrote:
> On Saturday, October 27, 2018 5:48:55 AM MDT John Nixon via Digitalmars-d wrote:
>> I have just read that the storage class "in" for function
>> parameters has not yet been properly implemented. From its simple
>> meaning as a one-way flow of information into a function from the
>> calling function, surely it should be implemented by copying the
>> argument, as is now done by default for all function arguments.
>> Note this has a distinct meaning from the far more restrictive
>> "const" that enforces the variable to remain constant throughout
>> its lifetime while the called function is running. It would then
>> naturally complement "out" and provide a simple semantics in the
>> function signature to aid program design.
>> It would also make it simpler if there was no difference between
>> the behaviour of reference and value types in function parameters
>> with default passing by reference. This would make the storage
>> class "none" correspond to "in" and "out". At present if this is
>> wanted, sometimes the keyword "ref" has to be used, and sometimes
>> it is not necessary (depending on whether the type is value or
>> reference).
>> A simplified language would make it easier to develop programs to
>> check programmer's code.
>
> in was supposed to be identical to const scope. However, scope has never really done much aside for delegates and was not very well defined, so it's pretty much just been the same as const. Lots of people have used it either because they liked the idea that it was the counterpart to out or because they thought that they understood what how it was supposed to work and wanted whatever behavior that was, but it wasn't actually properly defined and has always just been the same as const for everything other than delegates. So, arguably, no one should have been using it, but lots of people have been.
>
> However, DIP 1000 actually defines what scope means and makes it work for more than just delegates, and the result would be that making in actually mean const scope as originally intended would then break a _lot_ of code. _Some_ of that code should be broken, because the author used scope in a way that's close enough to what scope is actually going to mean that the fact that the code doesn't compile would mean that a bug will have been caught, but in the vast majority of cases, in was used without a proper understanding of what it would mean - especially since scope was not properly defined, and as it is, now that scope _does_ have a proper definition with DIP 1000, most people don't understand it very well outside of simple examples, meaning that it's hard to correctly write code that uses scope with -dip1000 even now. So, it's _highly_ unlikely that existing code using in is using it in a way that's going to be compatible with scope. So, the current plan is for in to remain as const rather than to become const scope, because it would mean far less code breakage. Some people are not very happy about that, and the plan may yet change, but either way, there's pretty much no way that in is going to be changed to mean something else entirely at this point. Doing so would break even more code than actually making it mean const scope as originally intended would.
>
> - Jonathan M Davis

The "in" feature perplex me here, I never understand why we couldn't simply write "const scope" instead of "in". Seems it better off to mean "(foreach var a in x)" for readability sake instead of using as a parameter that no-one seems to be hardly using.
October 27, 2018
On Saturday, October 27, 2018 4:32:48 PM MDT 12345swordy via Digitalmars-d wrote:
> The "in" feature perplex me here, I never understand why we couldn't simply write "const scope" instead of "in". Seems it better off to mean "(foreach var a in x)" for readability sake instead of using as a parameter that no-one seems to be hardly using.

As I understand it, the in keyword was used on parameters in D1 to mean something something similar to const, but whatever it meant, it wasn't something that was going to match up with D2. And for D2, it was decided to make it mean const scope in an attempt to make porting code from D1 to D2 easier. However, with everything going on early in D2 development (and in the years since), scope was not exactly a priority, and so it wasn't really fully sorted out and was never focused on until Walter worked on DIP 1000, meaning that while in was supposed to mean const scope, it never really properly did. It did for delegates, so it wasn't identical to const but was effectively identical to const everywhere else making it just plain weird in general. Personally, I think that having a keyword mean two other keywords is a terrible idea in the first place, but there are definitely folks who like the idea.

If in were added to D2 without its history in D1, I expect that the situation would have been quite different. Regardless, none of that would have had any effect on foreach, because in is already used as a keyword elsewhere in the language and in places similar to foreach - e.g. it's an operator.

if(auto value = key in aa)

and that usage arguably clashes far more with the idea of using in with foreach than having used it with function parameters. Also, whether using in with foreach would have been easier to read is highly debatable. Personally, I find in harder to read, not easier. If anything, I would have expected the debate to have been over whether it should have been a colon instead of a semicolon, since IIRC most other major C-derived languages have gone with the colon, whereas D went with the semicolon. But in the end, it's mostly a matter of personal preference. ;, :, and in all _can_ work, and the differences are primarily cosmetic.

- Jonathan M Davis



October 28, 2018
On Saturday, 27 October 2018 at 22:32:48 UTC, 12345swordy wrote:
> The "in" feature perplex me here, I never understand why we couldn't simply write "const scope" instead of "in".

`in` is a counterpoint to `out`.

`out` means the function is going to write a value to that variable as output.

`in` means the function is going to look at the value, but otherwise not touch it.

> better off to mean "(foreach var a in x)" for readability sake instead of using as a parameter that no-one seems to be hardly using.

there's no reason it couldn't be both.