www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to simplify nested ifs

reply Ozan =?UTF-8?B?U8O8ZWw=?= <ozan.sueel gmail.com> writes:
Hi

I have a construction like the following

if (source) {
   if (source.pool) {
     if (source.pool.repository) {
       if (source.pool.repository.directory) {
	if (source.pool.repository.directory.users) {
	  // do something

Any chance to simplify this nested ifs?
I know some languages has a way like.

if (source?pool?repository?directory?users) // do something


Similar ways in D?

Thanks and Regards, Ozan
Mar 13 2018
next sibling parent rikki cattermole <rikki cattermole.co.nz> writes:
On 14/03/2018 1:23 AM, Ozan Süel wrote:
 Hi
 
 I have a construction like the following
 
 if (source) {
    if (source.pool) {
      if (source.pool.repository) {
        if (source.pool.repository.directory) {
      if (source.pool.repository.directory.users) {
        // do something
 
 Any chance to simplify this nested ifs?
 I know some languages has a way like.
 
 if (source?pool?repository?directory?users) // do something
 
 
 Similar ways in D?
 
 Thanks and Regards, Ozan
if (source !is null && source.pool !is null && source.pool.repository !is null && source.pool.repository.directory !is null && source.pool.repository.directory.users !is null) { //... } That is what I'd do.
Mar 13 2018
prev sibling next sibling parent reply rumbu <rumbu rumbu.ro> writes:
On Tuesday, 13 March 2018 at 12:23:06 UTC, Ozan Süel wrote:
 Hi

 I have a construction like the following

 if (source) {
   if (source.pool) {
     if (source.pool.repository) {
       if (source.pool.repository.directory) {
 	if (source.pool.repository.directory.users) {
 	  // do something

 Any chance to simplify this nested ifs?
 I know some languages has a way like.

 if (source?pool?repository?directory?users) // do something


 Similar ways in D?

 Thanks and Regards, Ozan
You need the null conditional operator which is not available in D. A library solution can be found there: https://forum.dlang.org/post/mailman.2562.1403196857.2907.digitalmars-d puremagic.com SafeDeref(source).pool.repository.directory.users
Mar 13 2018
parent aliak <something something.com> writes:
On Tuesday, 13 March 2018 at 13:13:07 UTC, rumbu wrote:
 On Tuesday, 13 March 2018 at 12:23:06 UTC, Ozan Süel wrote:
 Hi

 I have a construction like the following

 if (source) {
   if (source.pool) {
     if (source.pool.repository) {
       if (source.pool.repository.directory) {
 	if (source.pool.repository.directory.users) {
 	  // do something

 Any chance to simplify this nested ifs?
 I know some languages has a way like.

 if (source?pool?repository?directory?users) // do something


 Similar ways in D?

 Thanks and Regards, Ozan
You need the null conditional operator which is not available in D. A library solution can be found there: https://forum.dlang.org/post/mailman.2562.1403196857.2907.digitalmars-d puremagic.com SafeDeref(source).pool.repository.directory.users
This library may help as well: https://code.dlang.org/packages/optional It will handle safe dispatching of reference types and pointer types and give you back the actual return result as well wrapped up in an optional value. class C0 { C1 f() { return new C1(); } class C1 { C2 f() { return new C2(); } class C2 { int f() { return 0; } } } } auto res1 = some!C0(null).dispatch.f.f.f; // all no ops auto res2 = some!C0(new C0()).dispatch.f.f.f // calls all fs assert(res1 == none); assert(res2 == some(0));
Mar 13 2018
prev sibling next sibling parent reply Satoshi <satoshi rikarin.org> writes:
On Tuesday, 13 March 2018 at 12:23:06 UTC, Ozan Süel wrote:
 Hi

 I have a construction like the following

 if (source) {
   if (source.pool) {
     if (source.pool.repository) {
       if (source.pool.repository.directory) {
 	if (source.pool.repository.directory.users) {
 	  // do something

 Any chance to simplify this nested ifs?
 I know some languages has a way like.

 if (source?pool?repository?directory?users) // do something


 Similar ways in D?

 Thanks and Regards, Ozan
null conditional operators are not implemented in D because, as a (I think Walter) said, D is not language designed to work with classes or advanced OOP stuff. Nobody uses it, so please, if you are using it, stop and use structs and meta programming instead.
Mar 16 2018
next sibling parent reply drug <drug2004 bk.ru> writes:
On 16.03.2018 09:34, Satoshi wrote:
 On Tuesday, 13 March 2018 at 12:23:06 UTC, Ozan Süel wrote:
 Hi

 I have a construction like the following

 if (source) {
   if (source.pool) {
     if (source.pool.repository) {
       if (source.pool.repository.directory) {
     if (source.pool.repository.directory.users) {
       // do something

 Any chance to simplify this nested ifs?
 I know some languages has a way like.

 if (source?pool?repository?directory?users) // do something


 Similar ways in D?

 Thanks and Regards, Ozan
null conditional operators are not implemented in D because, as a (I think Walter) said, D is not language designed to work with classes or advanced OOP stuff. Nobody uses it, so please, if you are using it, stop and use structs and meta programming instead.
I think that null conditional operator is intended for OOP only. It's really useful if your data field may be nullable. May be start review about this?
Mar 16 2018
parent drug <drug2004 bk.ru> writes:
On 16.03.2018 09:51, drug wrote:
 I think that null conditional operator is intended for OOP only. It's
 really useful if your data field may be nullable. May be start review
 about this?
Oops. I mean *isn't intended for OOP only*
Mar 16 2018
prev sibling parent bauss <jj_1337 live.dk> writes:
On Friday, 16 March 2018 at 09:34:38 UTC, Satoshi wrote:
 null conditional operators are not implemented in D because, as 
 a (I think Walter) said, D is not language designed to work 
 with classes or advanced OOP stuff. Nobody uses it, so please, 
 if you are using it, stop and use structs and meta programming 
 instead.
Tbh. the real reason is because there is no real backing and there has never been proposed a DIP on it.
Mar 16 2018
prev sibling next sibling parent bauss <jj_1337 live.dk> writes:
On Tuesday, 13 March 2018 at 12:23:06 UTC, Ozan Süel wrote:
 Hi

 I have a construction like the following

 if (source) {
   if (source.pool) {
     if (source.pool.repository) {
       if (source.pool.repository.directory) {
 	if (source.pool.repository.directory.users) {
 	  // do something

 Any chance to simplify this nested ifs?
 I know some languages has a way like.

 if (source?pool?repository?directory?users) // do something


 Similar ways in D?

 Thanks and Regards, Ozan
Kind of an ugly hack, but: string createCondition(string[] entries) { string result = ""; string lastEntry = ""; foreach (entry; entries) { if (lastEntry && lastEntry.length) lastEntry ~= "." ~ entry; else lastEntry = entry; result ~= lastEntry ~ " !is null &&"; } result.length -= 2; return result; } bool isDefined(alias symbol,T)(T arg) { import std.array : split; enum symbolEntries = symbol.split("."); enum entriesCondition = createCondition(["arg"] ~ symbolEntries[1..$]); mixin("return " ~ entriesCondition ~ ";"); } ... Usage: Let's say we have these: class A {} class B { A a; } class C { B b; } class D { C c; } class E { D d; } Then instead of: auto e = new E; if (e !is null && e.d !is null && e.d.c !is null && e.d.c.b !is null && e.d.c.b.a !is null) { // ... } Then we can just do: if (isDefined!((e.d.c.b.a).stringof)(e)) { // ... } ... The ugly part tbh. is that we need to stringof when passing the symbol and we also have to pass the object itself to the function. A preferred version would have been: if (isDefined!(e.d.c.b.a)) { // ... } Unfortunately that's not possible. You can see it live here: https://run.dlang.io/is/e2ACNc
Mar 16 2018
prev sibling parent Tony <tonytdominguez aol.com> writes:
On Tuesday, 13 March 2018 at 12:23:06 UTC, Ozan Süel wrote:

 if (source?pool?repository?directory?users) // do something
That type of chain is sometimes referred to as a "train wreck" (see Law of Demeter). If this is a common lookup it could be: if (source && source.GotSomeUsers() )
Mar 16 2018