Trying to use Mir ion, its a perfect example of the failure of D's attribute system
A moo person
moo_mail at fake.com
Thu Jan 19 04:06:27 UTC 2023
On Thursday, 19 January 2023 at 02:10:14 UTC, Walter Bright wrote:
> You can pretty much not use any attributes if you use none
> (including not using @safe).
>
> We can help if you can present specific cases.
In this case you can't leave them unannotated as all the Mir
functions are annotated and they try to call stuff in the type
you are trying to serialize.
@safe and const are the one that is the most problematic in my
case. (I mentioned @nogc before but I listed it by mistake but I
have ran into similar issues with @nogc libs)
I am not really looking for help with Mir Ion specifically as its
just some library, honestly at this point I'm probably not going
to use it because it's too unwieldy and over engineered.
But here is what I have had to do so far to even try to get
things compiling. I feel that Mir trying to be @safe is forcing
me to write even less safe code than I would normally just to try
and get it through the type system. At a certain point you just
start casting and annotating randomly just to get it to compile.
These sorts of workarounds seem to be what always happens when I
encounter these annotations. In my own code I avoid them like the
plague if I can't get by without them.
struct PageSerial {
// this is just some GUI element
// the contents of this gui element is what I am trying to
ser/deser
private Grid g;
@serdeKeys("blocks")
@serdeIgnoreIn
//@serdeLikeList
auto blocks_out() @property @trusted const {
// Had to put @trusted because the mir function to ser/deser is
@safe
// Had to put const because the mir function decides to cast my
type to const when working with it?? no idea why
import std.algorithm : filter, map;
import std.range : ElementType;
// have to cast away the const
auto t = cast(PageSerial*)(&this);
auto r =
(t.g).contents.children()[]
.filter!(c => (cast(GridBlock)c !is null))()
.map!(c => GridBlockSerial(cast(GridBlock)c))();
static assert(is(ElementType!(typeof(r)) == GridBlockSerial));
// trustRange wraps all the range functions with @trusted
// had to do this because somehow the map type's empty
evaluated to @system
// but the range is iterated in the @safe serializeValue so i
have to force it
return trustRange(r);
}
// this one doesnt even work so not even sure if its set up
right for Mir
// at least it compiles but trying to read the data back in
causes exceptions
@serdeKeys("blocks")
@serdeIgnoreOut
@serdeLikeList
@serdeProxy!GridBlockSerial
auto blocks_in() @property @trusted const {
struct R{
private Grid x;
void put(GridBlockSerial b){ x.addElement(b.makeElement()); }
}
return R(cast(Grid)g);
}
}
GridBlockSerial is another serialized type but not as complex.
The PageSerial type gets passed into Mir's serializeJson and
deserializeJson. Each of which pass them down into some lower
level templates (eg Mir's serializeValue) which is annotated
@safe.
I try to go in and read Mir's code but its just a spaghetti mess
of templates, its very hard to reason about and understand what
is going on. It's like a ton of engineering effort was spent in
an attempt to make the library "safer" in some type system sense,
but the net result is a library that is borderline unusably
cumbersome and actually incentivizes me to write less safe code.
If the argument is that the library should have been designed to
infer the annotations, then why even have the annotations in the
language at all if the best practice is to infer them.
More information about the Digitalmars-d
mailing list