Discussion Thread: DIP 1042--ProtoObject--Community Review Round 1
Adam D Ruppe
destructionator at gmail.com
Thu Jan 13 18:10:21 UTC 2022
So let's think about stringify a little.
First, just like with the other things, this isn't a real world
problem. You can always tighten constraints in subclasses right
now. You can also add overloads to take a sink, like Throwable
does, right now. This DIP is worse than nothing.
But let's think about how to do it with virtual functions. Among
the options:
1) string toString(); You can override this today with @nogc
etc., but it is tricky to actually implement since it returns a
string, which is assumed to have no owner. You potentially could
return a buffer inside the object, or a malloc'd thing or
whatever too, just this goes against the expected conventions and
users are liable to misuse it anyway.
I think realistically this signature must either return static
data or GC'd data. Of course, it can be `pure nothrow @safe` etc.
today with zero trouble, again subclasses are free to add that
*today*.
But let's look at the others for nogc options.
2) Throwable adds an overload `void toString(void delegate(in
char[]) sink)`
The tricky bit is that sink. Since it isn't labeled @nogc at top
level, the implementation has to assume it can be passed a gc
func which means the toString itself also can't be @nogc.
This is very similar to opApply right now - you have to add a
combination of overloads, and then overriding the right virtual
slot in subclasses is tricky. Which one do you override? Which
one do you call on the outside?
Of course, this doesn't need to be known by the implementation!
Just like `inout`, the implementation could be treated as the
most restrictive set, and the actual application at the call site
depends on what is actually passed to you.
DIP 1041 discussed exactly this (at significant length):
https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1041.md
It is postponed.... waiting for an answer from our glorious
emperor.
Note that any stringify interface is going to face these same
questions BECAUSE THERE IS NO LIMITATION FROM OBJECT TODAY. DIP
1042, again, *misidentifies the problem* meaning it cannot fix
anything, even if its solutions were sound (and they aren't).
Without something like dip 1041 - not necessarily that exact
text, but something along those lines, since it identifies a
*real* problem - we're in trouble regardless of if it is on
Object, Throwable, ProtoObject Stringify, or anything else.
3) Maybe we could do some kind of return of a builder
interface.... something like returning a stringify range that the
user must iterate over. If it is turned inside out, it can pass a
temporary as `front` and then the user is able to copy it out as
needed.
```d
struct StringBuilderRange {
int delegate (int position, scope char[] buffer) @nogc pure
nothrow @safe fillBuffer;
int position;
@nogc pure nothrow @safe:
this(typeof(fillBuffer) fb) {
fillBuffer = fb;
popFront();
}
void popFront() {
auto got = fillBuffer(position, buffer[]);
position += got;
bufferUsed = got;
}
char[] front() return {
return buffer[0 .. bufferUsed];
}
bool empty() const {
return bufferUsed == 0;
}
char[16] buffer;
int bufferUsed;
}
interface Stringify {
StringBuilderRange stringify();
}
class Foo : Stringify {
StringBuilderRange stringify() @nogc nothrow pure @safe return {
return StringBuilderRange(&this.fillBuffer);
}
int fillBuffer(int position, scope char[] buffer) @nogc nothrow
pure @safe {
if(position == 0 && buffer.length >= 5) {
buffer[0 .. 5] = "hello";
return 5;
}
return 0;
}
}
void main() @nogc @safe nothrow pure {
import std.stdio;
scope foo = new Foo();
foreach(item; foo.stringify())
debug writeln(item); // debug just to allow it past nogc pure
on main in writeln
}
```
But you can see it is a bit of a pain to implement in the class
and this doesn't actually compile with the dip1000. But I don't
know how to use that at all so I'm probably just doing it wrong.
Just this kind of turn inside out lets you be very restrictive on
the inside without necessarily forcing things to be restrictive
on the outside.
This kind of thing MIGHT work with a bit more fleshing out
without limiting end users too much. But eeek.
I prefer option #2 here. But that'd dip 1041, not dip 1042.
More information about the Digitalmars-d
mailing list