Jump to page: 1 2
Thread overview
Is there a simple way to check if value is null for every case?
Aug 26, 2018
SG
Aug 26, 2018
rikki cattermole
Aug 27, 2018
SG
Aug 27, 2018
rikki cattermole
Aug 27, 2018
SG
Aug 27, 2018
rikki cattermole
Aug 27, 2018
SG
Aug 27, 2018
Jacob Shtokolov
Aug 27, 2018
aliak
Aug 27, 2018
Alex
Aug 28, 2018
aliak
Aug 27, 2018
vit
August 26, 2018
Hi again,

The code below works for some cases but not for the Nullable!Type.

A way to fix it should be check the type and use ".isNull" for Nullabe!Type. But is there a simple way to test if value is null for every case?


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

bool foo(T)(T t){
    return (t is null);
}

class S{
    Nullable!int i;
}

void main(){
    string x = "a";
    writeln(x is null," - " ,x.foo);

    string y = null;
    writeln(y is null," - ", y.foo);

    auto z = null;
    writeln(z is null," - ", z.foo);


    S s = new S();
    writeln(s.i.isNull); // Ok

    //writeln(s.i is null); // Error
    //s.i.foo(2); // Error
}
August 27, 2018
On 27/08/2018 4:37 AM, SG wrote:
> Hi again,
> 
> The code below works for some cases but not for the Nullable!Type.
> 
> A way to fix it should be check the type and use ".isNull" for Nullabe!Type. But is there a simple way to test if value is null for every case?
> 
> 
> import std.stdio, std.typecons, std.variant, std.conv;
> 
> bool foo(T)(T t){
>      return (t is null);
> }
> 
> class S{
>      Nullable!int i;
> }
> 
> void main(){
>      string x = "a";
>      writeln(x is null," - " ,x.foo);
> 
>      string y = null;
>      writeln(y is null," - ", y.foo);
> 
>      auto z = null;
>      writeln(z is null," - ", z.foo);
> 
> 
>      S s = new S();
>      writeln(s.i.isNull); // Ok
> 
>      //writeln(s.i is null); // Error
>      //s.i.foo(2); // Error
> }

UFCS function called isNull.

e.g.

import std.traits : isPointer;
bool isNull(T)(T value) if (is(T == class) || isPointer!T) {
	return value is null;
}
August 27, 2018
On Sunday, 26 August 2018 at 16:39:53 UTC, rikki cattermole wrote:
> UFCS function called isNull.
>
> e.g.
>
> import std.traits : isPointer;
> bool isNull(T)(T value) if (is(T == class) || isPointer!T) {
> 	return value is null;
> }

Hi Rikki,

I'm still confused, I want to create a extension for checking null for every type, so in D I'll need to handle each case with Templates?

Because in C# I just need to compare an object/variable with null,

x == null;
myObject == null;
myObject.i == null;
myStruct == null;
myStruct.j == null;

This works fine in C#.


But again, in D I'll need the check the type? Is possible to make one Template for all cases?

The code below works, but I don't think this is a right thing to do, right?


import std.stdio, std.typecons, std.variant, std.conv;
import std.traits : isPointer;

bool foo(T)(T value) if (is(T == VariantN!32LU)) {
	return value == null;
}

bool foo(T)(T value) if (is(T == Nullable!int) || isPointer!T) {
	return value.isNull;
}

bool foo(T)(T t) if (!is(T == Nullable!int) && !is(T == VariantN!32LU)){
    if (is(T == typeof(null))){
        return true;
    }
    return (t is null);
}

class S{
    Nullable!int i;
}

void main(){
    Variant v = null;
    writeln(v == null," - " ,v.foo);

    Variant v2 = "a";
    writeln(v2 == null," - " ,v2.foo);

    string x = "a";
    writeln(x is null," - " ,x.foo);

    string y = null;
    writeln(y is null," - ", y.foo);

    auto z = null;
    writeln(z is null," - ", z.foo);

    S s = new S();
    writeln(s.i.isNull," - ", s.i.foo);
}






August 27, 2018
On 27/08/2018 12:51 PM, SG wrote:
> On Sunday, 26 August 2018 at 16:39:53 UTC, rikki cattermole wrote:
>> UFCS function called isNull.
>>
>> e.g.
>>
>> import std.traits : isPointer;
>> bool isNull(T)(T value) if (is(T == class) || isPointer!T) {
>>     return value is null;
>> }
> 
> Hi Rikki,
> 
> I'm still confused, I want to create a extension for checking null for every type, so in D I'll need to handle each case with Templates?

Templates make it the easiest way, since common patterns, like arrays, classes and pointers have the exact same null check syntax.

> Because in C# I just need to compare an object/variable with null,
> 
> x == null;
> myObject == null;
> myObject.i == null;
> myStruct == null;
> myStruct.j == null;
> 
> This works fine in C#.

That code is only for classes. C# also has structs which are a value type. Which it would not work for.

> But again, in D I'll need the check the type? Is possible to make one Template for all cases?
> 
> The code below works, but I don't think this is a right thing to do, right?

You don't need isNull function for Nullable because it has a method called it. That will be preferred (hence I specifically used isNull as the name).

For Variant, use hasValue.

bool isNull(Variant value) {
	return !value.hasValue;
}

Writing a Unified Function Call Syntax function isn't really an extension. You're defining a function that is to be preferred when you ask for a method of the same name. So that it appears as if it was actually described as a method instead of a free-function (not attached to class/interface/struct/union).
August 27, 2018
On Monday, 27 August 2018 at 03:21:04 UTC, rikki cattermole wrote:
> Templates make it the easiest way, since common patterns, like arrays, classes and pointers have the exact same null check syntax.

I see.

> That code is only for classes. C# also has structs which are a value type. Which it would not work for.

The same thing for struct in C#

Struct S{
   public int? i;
}

S.i == null; // This works nicely.

> You don't need isNull function for Nullable because it has a method called it. That will be preferred (hence I specifically used isNull as the name).
>
> For Variant, use hasValue.
>
> bool isNull(Variant value) {
> 	return !value.hasValue;
> }

The problem I'm trying to solve is beyond that. This is just an example. But bear with me, right now all I want is a function to check the value from 'a' type and return if it is null.

The type could be a: Class, Struct, a Basic data type, Variant, Nullable and so.

And what I see, these types has different behaviors, while in C# at least for this same case, I would write the same thing in few lines to perform it, in D I found very hard.

Isn't counter intuitive the way D works? Because for each type Class/Nullable you check with .isNull, for Variant with .hasValue, for string (variable is null).

Thanks.

August 28, 2018
On 28/08/2018 12:54 AM, SG wrote:
> The same thing for struct in C#
> 
> Struct S{
>     public int? i;
> }
> 
> S.i == null; // This works nicely.

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/nullable-types/index

So Nullable in D and C# is basically the same except C#'s has language support.
August 27, 2018
On Monday, 27 August 2018 at 12:54:59 UTC, SG wrote:
> On Monday, 27 August 2018 at 03:21:04 UTC, rikki cattermole wrote:
>> Templates make it the easiest way, since common patterns, like arrays, classes and pointers have the exact same null check syntax.
>
> I see.
>
>> That code is only for classes. C# also has structs which are a value type. Which it would not work for.
>
> The same thing for struct in C#
>
> Struct S{
>    public int? i;
> }
>
> S.i == null; // This works nicely.
>
>> You don't need isNull function for Nullable because it has a method called it. That will be preferred (hence I specifically used isNull as the name).
>>
>> For Variant, use hasValue.
>>
>> bool isNull(Variant value) {
>> 	return !value.hasValue;
>> }
>
> The problem I'm trying to solve is beyond that. This is just an example. But bear with me, right now all I want is a function to check the value from 'a' type and return if it is null.
>
> The type could be a: Class, Struct, a Basic data type, Variant, Nullable and so.
>
> And what I see, these types has different behaviors, while in C# at least for this same case, I would write the same thing in few lines to perform it, in D I found very hard.
>
> Isn't counter intuitive the way D works? Because for each type Class/Nullable you check with .isNull, for Variant with .hasValue, for string (variable is null).
>
> Thanks.

hasValue isn't equivalent of isNull or is null. 'null' is valid value in Variant:


        import std.variant;
        Variant v;

        v = null;
        assert(v.hasValue);		       //v has value
        assert(v.get!(typeof(null)) is null);  //value in v is null

Nullable!T.isNull isn't equivalent of is null:

    	int* i = null;
    	Nullable!(int*) ni;
    	ni = i;
        assert(ni.isNull == false);	///ni has value
        assert(ni is null);	        ///ni value is null

string is null isn't equivalent of empty:

    	string str = "test";
    	str = str[0 .. 0];
        assert(str !is null);	///str isn't null
        assert(str.empty);	///str is empty


August 27, 2018
On Monday, 27 August 2018 at 13:02:28 UTC, rikki cattermole wrote:
> So Nullable in D and C# is basically the same except C#'s has language support.

The big difference is that in there I could do:

   int? i = null;
   string j = null;
   var k = null;

and test all like:

    i == null;
    j == null;
    k == null;

but in D:

    Nullable!int i;
    auto j = null;
    string k = null;

    writefln("%s", i.isNull); // I need to invoke Nullable property isNull;
    writefln("%s", i == null); // I can't just do this.

    writefln("%s", j == null);
    writefln("%s", k == null);
August 27, 2018
On Monday, 27 August 2018 at 14:11:32 UTC, SG wrote:
> On Monday, 27 August 2018 at 13:02:28 UTC, rikki cattermole wrote:
>> So Nullable in D and C# is basically the same except C#'s has language support.


Shouldn't it be in the standard library?

I think it's worth it to create a feature request in Phobos for that. Or at least make a bug report.

Such inconsistencies must be handled by a standard library, not manually, I believe.
August 27, 2018
On Monday, 27 August 2018 at 14:11:32 UTC, SG wrote:
> On Monday, 27 August 2018 at 13:02:28 UTC, rikki cattermole wrote:
>> So Nullable in D and C# is basically the same except C#'s has language support.
>
> The big difference is that in there I could do:
>
>    int? i = null;
>    string j = null;
>    var k = null;
>
> and test all like:
>
>     i == null;
>     j == null;
>     k == null;
>
> but in D:
>
>     Nullable!int i;
>     auto j = null;
>     string k = null;
>
>     writefln("%s", i.isNull); // I need to invoke Nullable property isNull;
>     writefln("%s", i == null); // I can't just do this.
>
>     writefln("%s", j == null);
>     writefln("%s", k == null);

I hear you. IMO Nullable should be modified a bit to serve the purpose of turning non-nullable types in to nullable types and only that (right now it's confusing itself with an optional type). Then we could implement opEquals(typeof(null)) so that nullable == null would work.

I.e.

struct Nullable(T) {
  static if (isPointer!T) {
    private PointerTarget!T _value = PointerTarget!T.init;
  } else {
    private T _value = T.init;
  }
  bool opEquals(typeof(null)) {
    return isNull;
  }
}

Then Nullable!(int*) would be the same as int*. Or even better maybe is to give a compiler error when you try and stuff a nullable type inside a Nullable. Because ... why?

Cheers,
- Ali
« First   ‹ Prev
1 2