| |
 | Posted by Adam D Ruppe in reply to Mike Parker | Permalink Reply |
|
Adam D Ruppe 
Posted in reply to Mike Parker
| 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.
|