On Friday, 20 October 2017 at 00:26:19 UTC, bauss wrote:
On Wednesday, 18 October 2017 at 08:56:21 UTC, Satoshi wrote:
conditional dereferencing and stuff about that (same as in C#)
foo?.bar;
foo?[bar];
return foo ?? null;

Tbh. these are some I really wish were in D, because it becomes tedious having to write something like this all the time:

return foo ? foo : null;

where

return foo ?? null; would be so much easier.

It especially becomes painful when you have something with multiple member accesses.

Like:

return foo ? foo.bar ? foo.bar.baz ? foo.bar.baz.something : null;

Which could just be:

return foo?.bar?.baz?.something;


async/await (vibe.d is nice but useless in comparison to C# or js async/await idiom) I want to create function returning Promise/Task and await where I want to.
e.g.
auto result = device.start(foo, bar); // This is RPC to remote server returning Task!Bar
// do some important stuff
return await result; // wait for RPC finish, then return it's result

I don't think this is much necessary, because the fiber implementations already are able to let you write code close to this.

The only difference is you have to import the modules, but it's such a small thing I don't think you really need this.


implement this thing from C# (just because it's cool)
new Foo() {
  property1 = 42,
  property2 = "bar"
};



Thanks for your time.
- Satoshi

I really wish this was implemented for classes too! Currently it exist for structs and it completely baffles me why it has never been implemented for structs.

http://forum.dlang.org/post/[email protected]

From that thread:

Here's a slightly improved version that collapses nested wrappers into a single wrapper, so that Maybe!(Maybe!(Maybe!...Maybe!T)...) == Maybe!T:

        /**
         * A safe-dereferencing wrapper resembling a Maybe monad.
         *
* If the wrapped object is null, any further member dereferences will simply * return a wrapper around the .init value of the member's type. Since non-null * member dereferences will also return a wrapped value, any null value in the * middle of a chain of nested dereferences will simply cause the final result
         * to default to the .init value of the final member's type.
         */
        template SafeDeref(T)
        {
            static if (is(T U == SafeDeref!V, V))
            {
                // Merge SafeDeref!(SafeDeref!X) into just SafeDeref!X.
                alias SafeDeref = U;
            }
            else
            {
                struct SafeDeref
                {
                    T t;

                    // Make the wrapper as transparent as possible.
                    alias t this;

                    // This is the magic that makes it all work.
                    auto opDispatch(string field)()
                        if (is(typeof(__traits(getMember, t, field))))
                    {
alias Memb = typeof(__traits(getMember, t, field));

// If T is comparable with null, then we do a null check. // Otherwise, we just dereference the member since it's
                        // guaranteed to be safe of null dereferences.
                        //
// N.B.: we always return a wrapped type in case the return
                        // type contains further nullable fields.
                        static if (is(typeof(t is null)))
                        {
                            return safeDeref((t is null) ? Memb.init
: __traits(getMember, t, field));
                        } else {
return safeDeref(__traits(getMember, t, field));
                        }
                    }
                }
            }
        }

        /**
* Wraps an object in a safe dereferencing wrapper resembling a Maybe monad.
         *
* If the object is null, then any further member dereferences will just return * a wrapper around the .init value of the wrapped type, instead of * dereferencing null. This applies recursively to any element in a chain of
         * dereferences.
         *
         * Params: t = data to wrap.
* Returns: A wrapper around the given type, with "safe" member dereference
         * semantics.
         */
        auto safeDeref(T)(T t)
        {
            return SafeDeref!T(t);
        }

        unittest
        {
            class Node
            {
                int val;
                Node left, right;

                this(int _val, Node _left=null, Node _right=null)
                {
                    val = _val;
                    left = _left;
                    right = _right;
                }
            }

            auto tree = new Node(1,
                new Node(2),
                new Node(3,
                    null,
                    new Node(4)
                )
            );

            import std.stdio;
            writeln(safeDeref(tree).right.right.val);
            writeln(safeDeref(tree).left.right.left.right);
            writeln(safeDeref(tree).left.right.left.right.val);
        }

        // Static test of monadic composition of SafeDeref.
        unittest
        {
            {
                struct Test {}
                alias A = SafeDeref!Test;
                alias B = SafeDeref!A;

                static assert(is(B == SafeDeref!Test));
                static assert(is(SafeDeref!B == SafeDeref!Test));
            }

            // Timon Gehr's original test case
            {
                class C
                {
                    auto foo = safeDeref(C.init);
                }

                C c = new C;

                //import std.stdio;
//writeln(safeDeref(c).foo); // SafeDeref(SafeDeref(null))

                import std.string;
                auto type = "%s".format(safeDeref(c).foo);
                assert(type == "SafeDeref!(C)(null)");
            }
        }

Reply via email to