January 15, 2021 Re: Open question: what code pattern you use usually for null safety problem | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 1/15/21 9:19 AM, Steven Schveighoffer wrote: > Something similar to BlackHole or WhiteHole. Essentially there's a default action for null for all types/fields/methods, and everything else is passed through. And now reading the other thread about this above, it looks like this type is already written: https://code.dlang.org/packages/optional I'd say use that. -Steve |
January 15, 2021 Re: Open question: what code pattern you use usually for null safety problem | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Friday, 15 January 2021 at 14:25:09 UTC, Steven Schveighoffer wrote:
> On 1/15/21 9:19 AM, Steven Schveighoffer wrote:
>
>> Something similar to BlackHole or WhiteHole. Essentially there's a default action for null for all types/fields/methods, and everything else is passed through.
>
> And now reading the other thread about this above, it looks like this type is already written:
>
> https://code.dlang.org/packages/optional
>
> I'd say use that.
>
> -Steve
That could be useful actually
|
January 15, 2021 Re: Open question: what code pattern you use usually for null safety problem | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Friday, 15 January 2021 at 14:19:35 UTC, Steven Schveighoffer wrote: > On 1/14/21 7:27 PM, ddcovery wrote: >> On Thursday, 14 January 2021 at 20:23:08 UTC, Steven Schveighoffer wrote: >>> >>> 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 >> >> I'm seeing "opDispatch" everywhere last days :-). It's really powerful!!! >> >> If we define an special T _(){ return _val; } method, then you can write >> >> if( nullCheck(person).father.father.name._ == "Peter") >> >> And renaming >> >> if( ns(person).father.father.name._ == "Peter" ) > > This doesn't work, if person, person.father, or person.father.father is null, because now you are dereferencing null again. > > But something like this might work: > > NullCheck(T) > { > ... // opdispatch and stuff > bool opEquals(auto ref T other) { > return _val is null ? false : *_val == other; > } > } > > Something similar to BlackHole or WhiteHole. Essentially there's a default action for null for all types/fields/methods, and everything else is passed through. > > Swift has stuff like this built-in. But D might look better because you wouldn't need a chain of question marks. > > -Steve I don't know if I can add this to Dlang IDE and then share a link... links that I generate doesn't work... * I have adapted the "onDispatch" and the factory method to manage nullable and not nullable values * The unwrapper "T _()" method returns Nullable!T for nullable value types instead T (similar to c#) * I removed the T* when testing changes (I discovered after 1000 changes that template errors are not well informed by the compiler... I losted a lot to discover a missing import)... I will try to restore. import std.typecons; import std.traits; void main() { Person person = new Person("Andres", 10, new Person("Peter", 40, null)); // null reference assert(ns(person).father.father._ is null); // null reference assert(ns(person).father.father.name._ is null); // reference value assert(ns(person).father.name._ == "Peter"); // Nullable!int assert(ns(person).father.father.age._.isNull); assert(ns(person).father.father.age._.get(0) == 0); assert(ns(11)._.get == 11); } struct NullSafety(T) { private T _val; private bool _isEmpty; auto opDispatch(string name)() if (__traits(hasMember, T, name)) { alias Ret = typeof((() => __traits(getMember, _val, name))()); if (_val is null) { static if (isAssignable!(Ret, typeof(null))) return NullSafety!(Ret)(null, true); else return NullSafety!(Ret)(Ret.init, true); } else { return NullSafety!(Ret)(__traits(getMember, _val, name), false); } } static if (isAssignable!(T, typeof(null))) // Reference types unwrapper T _() { return _val; } else // value types unwrapper Nullable!T _() { return _isEmpty ? Nullable!T() : Nullable!T(_val); } } auto ns(T)(T val) { static if (isAssignable!(T, typeof(null))) return NullSafety!T(val, val is null); else return NullSafety!T(val, false); } class Person { public string name; public Person father; public int age; this(string name, int age, Person father) { this.name = name; this.father = father; this.age = age; } } |
January 15, 2021 Re: Open question: what code pattern you use usually for null safety problem | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Friday, 15 January 2021 at 14:25:09 UTC, Steven Schveighoffer wrote:
> On 1/15/21 9:19 AM, Steven Schveighoffer wrote:
>
>> Something similar to BlackHole or WhiteHole. Essentially there's a default action for null for all types/fields/methods, and everything else is passed through.
>
> And now reading the other thread about this above, it looks like this type is already written:
>
> https://code.dlang.org/packages/optional
>
> I'd say use that.
>
> -Steve
Yes, the Optional/Some/None pattern is the "functional" orientation for avoiding the use of "null".
Swift uses a similar pattern (and scala too) and supports the "null safety operators" ?. and ?? (it doesn't work on "null" but on optional/nil).
The more I think about it, the more fervent defender of the use of ?. and ?? I am.
The misinterpretation about "null safety" is we talk about "null" reference safety, but this pattern can be used with "optional" to...
D has not optional/none/some native implementation and this is the reason we think about "?." as a "bad pattern" because we imagine it is for "null" values exclusively.
But like other operators, they could be overloaded and adapted to each library.
Well, I'm digressing: good night!!!
|
January 15, 2021 Re: Open question: what code pattern you use usually for null safety problem | ||||
---|---|---|---|---|
| ||||
Posted in reply to ddcovery | On Thursday, 14 January 2021 at 18:24:44 UTC, ddcovery wrote:
> 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
>
Probably the incremental check solution. A helper function if I find myself doing that more than two or three times.
On the other hand, I don't have to do this that often. I usually design the functions to either except non-null values, or to return early in case of null.
|
January 15, 2021 Re: Open question: what code pattern you use usually for null safety problem | ||||
---|---|---|---|---|
| ||||
Posted in reply to ddcovery | On Thursday, 14 January 2021 at 18:24:44 UTC, ddcovery wrote: > I know there is other threads about null safety and the "possible" ways to support this in D and so on. > [...] > If it's not a bother, I'd like to know how you usually approach it > > [...] > > Thanks!!! I have a opDispatch solution here [1], probably very similar to the other opDispatch solution mentioned. It is used in d-scanner since several years, e.g here [2]. I'd like to have this as a first class operator because as usual in D, you can do great things with templates but then completion is totally unable to deal with them. Also There's a great difference between using the template to do refacts and using it to write new code. Very frustrating to write `safeAcess(stuff). ` and no completion popup appears. [1]: https://gitlab.com/basile.b/iz/-/blob/master/import/iz/sugar.d#L1655 [2]: https://github.com/dlang-community/D-Scanner/blob/2963358eb4a24064b0893493684d4075361297eb/src/dscanner/analysis/assert_without_msg.d#L42 |
Copyright © 1999-2021 by the D Language Foundation