First Draft: ref For Variable Declarations
Quirin Schroll
qs.il.paperinik at gmail.com
Fri Apr 26 09:36:17 UTC 2024
On Sunday, 14 April 2024 at 23:28:07 UTC, Walter Bright wrote:
> I appreciate your thoughts.
>
> I agree that `ref` parameters make it slightly less clear what
> is happening at the call site. But we don't really put
> documentation at the call site, we put the documentation at the
> callee. A `ref` parameter self-documents restrictions on how
> the pointer is used. `out` goes even further, it says that a
> value is not being passed in, only out. Pointers come with
> other behaviors - they can be incremented, and they can be
> free'd.
>
> In my years of experience, I see a lot of operating system APIs
> that use a pointer. It's often unclear what is going to happen
> with that pointer. Most of the time, they stick to `ref`
> semantics, but not always. Like a `char*` being actually a
> string in C, rather than a reference to a `char`.
Zig tries to be explicit about how an argument is passed: It only
allows pass-by-value. If you want to pass by reference, pass the
address by value.
While this looks like the same mess as in C, Zig has a whole zoo
of pointer types that indicate the various intentions behind a
pointer. Zig distinguishes a single-element pointer and a pointer
into an array; only the latter allows pointer arithmetic. Zig
also distinguishes pointers into arrays that are
sentinel-terminated.
A C `char*` that’s intended to be a string would be typed as
pointer into 0-terminated array of `char`. A C `int*` that’s
supposed to be `ref` or `out` would be a single-element pointer
to `int`. Zig also has `null` indicators, i.e. it distinguishes
pointers and slices that can be null and those that can’t be.
It’s a complete 180° from what D’s philosophy is. D style is
passing a `ref` or a slice when you can. This means when you see
a pointer, it means something more complicated is going on. One
thing that I’d never do because it would confuse my future self:
Passing `*null` via ref. It’s legal in D (not in C++), but I have
never seen that being meaningfully used, i.e. I have yet to see
an API that takes some `ref` parameter and the docs say that
passing `*null` does X and Y.
I can see the value in both philosophies. While they seem
incompatible, they’re not. D can take a concept or two from Zig.
Notably, in C#, to pass by reference, you have to put `ref` also
before the argument in the function call. This ship has sailed
for D. Also in C#, `ref` variables can be reassigned:
```cs
int i = 0, j = 1;
ref int r = ref i;
r = 2; // as if i = 2
r = ref j; // r points to j now
r = 3; // as if j = 3
```
I’m not saying D should allow reassigning `ref`, just pointing
out that C#’s `ref` is quite different to D’s `ref` in that
regard.
More information about the dip.development
mailing list