Open question: what code pattern you use usually for null safety problem

Steven Schveighoffer schveiguy at gmail.com
Thu Jan 14 20:23:08 UTC 2021


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


More information about the Digitalmars-d-learn mailing list