On 1/14/21 1:24 PM, ddcovery wrote:
I know there is other threads about null safety and the "possible" ways
to support this in D and so on.
This is only an open question to know what code patterns you usually use
to solve this situation in D:
if(person.father.father.name == "Peter") doSomething();
if(person.father.age > 80 ) doSomething();
knowing that *person*, or its *father* property can be null
i.e.: the incremental null check solution
if(
person !is null &&
person.father !is null &&
person.father.father !is null &&
person.father.father.name == "Peter"
)
{
doSomething();
}
or the "monad" way
[person].
filter!"a !is null".map!"a.father".
filter!"a !is null".map!"a.father".
filter!"a !is null".map!"a.name".
each!( (name) {
if(name == "Peter") doSomething();
});
or, may be, you have some helper function/structs/templates
if( person.d!"father".d!"father".d!"name".get == "Peter" ){
doSomething()
}
if( person.d!"father".d!"age".get(0) > 80 ){
doSomething()
}
or an "xml path" like template
if( person.get!"father.father.name" == "Peter" )
if( person.get!"father.father.name.length"(0) == 5 )
if( person.get!"father.father.age"(0) > 80 )
If it's not a bother, I'd like to know how you usually approach it
Thanks!!!
You could kinda automate it like:
struct NullCheck(T)
{
private T* _val;
auto opDispatch(string mem)() if (__traits(hasMember, T, mem)) {
alias Ret = typeof(() { return __traits(getMember, *_val, mem);
}());
if(_val is null) return NullCheck!(Ret)(null);
else return NullCheck!(Ret)(__trats(getMember, *_val, mem));
}
bool opCast(V: bool)() { return _val !is null; }
}
auto nullCheck(T)(T *val) { return AutoNullCheck!T(val);}
// usage
if(nullCheck(person).father.father && person.father.father.name == "Peter")
Probably doesn't work for many circumstances, and I'm sure I messed
something up.
-Steve