My two cents
Meta
jared771 at gmail.com
Fri Oct 20 14:34:08 UTC 2017
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/mailman.2562.1403196857.2907.digitalmars-d@puremagic.com
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)");
}
}
More information about the Digitalmars-d
mailing list