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

Reply via email to