Jump to page: 1 2
Thread overview
Null-Coalescing Operator and Extensions
Aug 25, 2018
SG
Aug 25, 2018
JN
Aug 25, 2018
SG
Aug 25, 2018
Jacob Carlborg
Aug 27, 2018
Simen Kjærås
Aug 27, 2018
SG
Aug 28, 2018
Basile B.
Aug 28, 2018
Simen Kjærås
Aug 28, 2018
aliak
Aug 27, 2018
Basile B.
Aug 28, 2018
Kagamin
August 25, 2018
Hi,

1) I program in C# and I'm wondering if there is something like ?? (Null-Coalescing Operator) in D? (I remember some proposals in the past).


2) Is possible to create Extensions like in C#?

For example:

public int StrToInt (this string s){
   return int.Parse(s);
}

var i = "123456".StrToInt();

Thanks.
August 25, 2018
On Saturday, 25 August 2018 at 13:33:58 UTC, SG wrote:
> Hi,
>
> 1) I program in C# and I'm wondering if there is something like ?? (Null-Coalescing Operator) in D? (I remember some proposals in the past).
>
>
> 2) Is possible to create Extensions like in C#?
>
> For example:
>
> public int StrToInt (this string s){
>    return int.Parse(s);
> }
>
> var i = "123456".StrToInt();
>
> Thanks.

1) no

2) Yes, through UFCS (Uniform Function Call Syntax). It doesn't require any special syntax, for example:

int squared(int i)
{
    return i * i;
}

void main()
{
    writeln(16.squared);
}

will print 256
August 25, 2018
On Saturday, 25 August 2018 at 13:42:30 UTC, JN wrote:
> 2) Yes, through UFCS (Uniform Function Call Syntax). It doesn't require any special syntax, for example:

Very simple indeed.

Thanks.
August 25, 2018
On 2018-08-25 15:33, SG wrote:
> Hi,
> 
> 1) I program in C# and I'm wondering if there is something like ?? (Null-Coalescing Operator) in D? (I remember some proposals in the past).

Not in the language but it can be implemented as a library function by overloading "opDispatch". See [1] for an example.

[1] https://github.com/jacob-carlborg/dlp/blob/9d524e282803070022848c01cf6cd25a61025004/source/dlp/core/optional.d#L228-L238

-- 
/Jacob Carlborg
August 27, 2018
On Saturday, 25 August 2018 at 19:16:26 UTC, Jacob Carlborg wrote:
> On 2018-08-25 15:33, SG wrote:
>> Hi,
>> 
>> 1) I program in C# and I'm wondering if there is something like ?? (Null-Coalescing Operator) in D? (I remember some proposals in the past).
>
> Not in the language but it can be implemented as a library function by overloading "opDispatch". See [1] for an example.
>
> [1] https://github.com/jacob-carlborg/dlp/blob/9d524e282803070022848c01cf6cd25a61025004/source/dlp/core/optional.d#L228-L238

That's the null propagation operator (?.). What SG asked for is the null-coalescing operator (??). Of course, this can also be implemented in D (albeit with a slight more horrible syntax):

struct NullCoalesce {
    static auto opBinaryRight(string op : "|", T)(T lhs) {
        return NullCoalesceImpl!T(lhs);
    }
}

alias NullCoalesce _;

struct NullCoalesceImpl(T) {
    T value;
    auto opBinary(string op = "|", R)(lazy R rhs) {
        if (value is null) return rhs;
        return value;
    }
}

unittest {
    int* a = null;
    int b = 3;
    assert(*(a |_| &b) == 3);
}

--
  Simen
August 27, 2018
On Saturday, 25 August 2018 at 19:16:26 UTC, Jacob Carlborg wrote:
> On 2018-08-25 15:33, SG wrote:
>> Hi,
>> 
>> 1) I program in C# and I'm wondering if there is something like ?? (Null-Coalescing Operator) in D? (I remember some proposals in the past).
>
> Not in the language but it can be implemented as a library function by overloading "opDispatch". See [1] for an example.
>
> [1] https://github.com/jacob-carlborg/dlp/blob/9d524e282803070022848c01cf6cd25a61025004/source/dlp/core/optional.d#L228-L238

In the same vain there's "safeAccess" in my user library, see https://github.com/BBasile/iz/blob/master/import/iz/sugar.d#L1658. It's more or less the same specific D pattern (opDispatch), although the OP asked for "??" and not for "?.", which is strange. I find that the later misses more as a builtin operator.
August 27, 2018
On Monday, 27 August 2018 at 07:59:17 UTC, Simen Kjærås wrote:
> That's the null propagation operator (?.). What SG asked for is the null-coalescing operator (??). Of course, this can also be implemented in D (albeit with a slight more horrible syntax):

Exactly, and I know it is an example, but it doesn't work for Variant.

I was trying something like below, I need to find a way to test for all Nullable types out there, right now only works for Nullable!int.


import std.stdio, std.typecons, std.variant, std.conv;

void foo(T, U...)(T t, U u) if (is(T == Nullable!U) )  {
    if(t.isNull){
        writeln(u);
        return;
    }
    writeln(t);
}

void foo(T, U...)(T t, U u) if (!is(T == Nullable!U) ){
    if(t == null){
        writeln(u);
        return;
    }
    writeln(t);
}

class C {
    Nullable!int m;
}

void main(){
    Nullable!int i;
    auto j = null;
    string k = null;
    Variant l = null;
    C c = new C();

    writefln("%s", i.isNull);
    writefln("%s", j == null);
    writefln("%s", k == null);
    writefln("%s", l == null);
    writefln("%s", c.m.isNull);

    i.foo(1);
    j.foo(2);
    k.foo(3);
    l.foo(4.3);
    c.m.foo(5);
}
August 28, 2018
On Monday, 27 August 2018 at 14:59:20 UTC, SG wrote:
> On Monday, 27 August 2018 at 07:59:17 UTC, Simen Kjærås wrote:
>> That's the null propagation operator (?.). What SG asked for is the null-coalescing operator (??). Of course, this can also be implemented in D (albeit with a slight more horrible syntax):"

IMO not to have the Elvis operator in D (actually "??" is less interesting than the Elvis "?:" because of D automatic dereference and also because of boolean eval of stuff like integers and classes instances or pointer) is not a huge issue.

Not to have the safe access operator is more a problem. One is about having shorter ternary expressions (Elvis), the other is about saving sometimes 4 or 5 "&&" with at new "&&" a longer unary (Safe access).
August 28, 2018
On Saturday, 25 August 2018 at 13:33:58 UTC, SG wrote:
> 1) I program in C# and I'm wondering if there is something like ?? (Null-Coalescing Operator) in D? (I remember some proposals in the past).

Another example: https://github.com/aliak00/optional/blob/master/source/optional/optional.d#L340
August 28, 2018
On Monday, 27 August 2018 at 14:59:20 UTC, SG wrote:
> On Monday, 27 August 2018 at 07:59:17 UTC, Simen Kjærås wrote:
>> That's the null propagation operator (?.). What SG asked for is the null-coalescing operator (??). Of course, this can also be implemented in D (albeit with a slight more horrible syntax):
>
> Exactly, and I know it is an example, but it doesn't work for Variant.
>
> I was trying something like below, I need to find a way to test for all Nullable types out there, right now only works for Nullable!int.

Sadly, Variant's operator overloading is problematic - there seems to be no way to write a struct such that its operator overloading is preferred over Variant's, and Variant's fails to compile. (issue 19200: https://issues.dlang.org/show_bug.cgi?id=19200)

Once that issue has been fixed, this should work:

// Support aliak's optional, if available:
static if (__traits(compiles, {import optional;})) import optional;

struct NullCoalesce {
    static auto opBinaryRight(string op : "|", T)(T lhs) {
        return NullCoalesceImpl!T(lhs);
    }
}

struct NullCoalesceImpl(T) {
    T value;
    auto opBinary(string op : "|", R)(lazy R rhs) {
        static if (is(typeof(value.peek!R))) {
            if (auto tmp = value.peek!R)
                return *tmp;
        } else static if (is(typeof(value.isNull))) {
            if (!value.isNull)
                return value.get;
        } else static if (is(typeof(value.unwrap))) {
            if (auto tmp = value.unwrap)
                return *tmp;
        } else static if (is(typeof(value == null))) {
            if (value != null)
                return value;
        } else {
            static assert(false, "Cannot perform null-coalescing on non-nullable type "~T.stringof~".");
        }
        return rhs;
    }
}

alias NullCoalesce _;

unittest {
    import std.variant;
    import std.typecons;

    int* a = null;
    auto b = new int;
    assert((a |_| b) == b);
    a = new int;
    assert((a |_| b) == a);

    Variant c;
    assert((c |_| 3) == 3);
    c = 4;
    assert((c |_| 3) == 4);

    Nullable!int d;
    assert((d |_| 3) == 3);
    d = 4;
    assert((d |_| 3) == 4);

    static if (is(typeof(Optional!int))) {
        Optional!int e;
        assert((e |_| 3) == 3);
        e = 4;
        assert((e |_| 3) == 4);
    }
}

Now, as has been pointed out, that only work for null-coalescing, not null-propagation. It seems writers of Optional, Variant, SumType, and so on, have decided not to support this out of the box, but rather wrap it separately, like Basile B.'s SafeAccess[1] and aliak's dispatch[2]. There's no real obstacle to wrapping member access directly in Optional!T such that it always return a Optional!(typeof(member)), though.

I've written an Optional somewhere that does safe access out of the box, but it seems to be on my work computer, not this one.

--
  Simen

[1]: https://github.com/BBasile/iz/blob/master/import/iz/sugar.d#L1658
[2]: https://code.dlang.org/packages/optional
« First   ‹ Prev
1 2