D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 8304 - writeln of empty Nullables too
Summary: writeln of empty Nullables too
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: phobos (show other issues)
Version: D2
Hardware: All All
: P2 enhancement
Assignee: No Owner
URL:
Keywords: bootcamp, rejects-valid
Depends on:
Blocks:
 
Reported: 2012-06-26 16:30 UTC by bearophile_hugs
Modified: 2019-07-13 15:37 UTC (History)
4 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description bearophile_hugs 2012-06-26 16:30:32 UTC
In D you can't print an empty Nullable:


import std.stdio: writeln;
import std.typecons: Nullable;
void main() {
    Nullable!int ni;
    writeln(ni);
}


DMD 2.060alpha:

object.Exception@C:\dmd2\src\phobos\std\typecons.d(1218): Enforcement failed


But I'd like something similar to Haskell, where you are allowed to print an empty Nullable (named Maybe):

...>ghci
GHCi, version 7.0.2: ...
Prelude> import Data.Maybe
Prelude Data.Maybe> Nothing :: Maybe Int
Nothing


In D when the Nullable is empty I'd like writeln to print something like "EmptyNullable".


As temporarily workaround I've added this method to Nullable, but it's not a good general solution:

    string toString() const
    {
        return this.isNull ? "EmptyNullable": text(get());
    }
Comment 1 bearophile_hugs 2013-03-19 19:43:12 UTC
In DMD 2.063alpha if you print a const null Nullable:


import std.stdio: writeln;
import std.typecons: Nullable;
void main() {
    auto a = Nullable!int(10);
    writeln(a);
    auto b = const(Nullable!int)(10);
    writeln(b);
    const(Nullable!int) c;
    writeln(c);
    Nullable!int d;
    writeln(d);
}


You get:


10
const(Nullable!(int))(10, false)
const(Nullable!(int))(0, true)
==> core.exception.AssertError@C:\dmd2\src\phobos\std\typecons.d(1212): Called `get' on null Nullable!int.
Comment 2 Andrej Mitrovic 2013-03-19 19:53:36 UTC
This could work:

    string toString() const
    {
        return this.isNull ?
            format("Nullable!%s is null", T.stringof) : text(get());
    }

How sophisticated does this have to be anyway?
Comment 3 bearophile_hugs 2013-03-19 20:34:06 UTC
(In reply to comment #2)

> How sophisticated does this have to be anyway?

Sorry, I don't remember why I have written "but it's not a good general solution:" :-)


> This could work:
> 
>     string toString() const
>     {
>         return this.isNull ?
>             format("Nullable!%s is null", T.stringof) : text(get());
>     }
> 

But I have two notes and half:

1) Maybe using a sink in toString is a bit more efficient.

2) Think about printing an array of nullables, do you like this?
[Nullable!int is null, 55, Nullable!int is null, 22]

This looks a bit better:
[Nullable!int(), 55, Nullable!int(), 22]

2b) But what's even better is something similar to Python, that uses __str__ and __repr__ if you print an item or if you print a collection of items.

So if you print a single Nullable you get:
55
or:
Nullable!int()

If you print an array/range of nullables you get:
[Nothing, 55, Nothing, 22]


D already does that in some cases:

writeln("hello");
writeln(["hello"]);

It outputs:
hello
["hello"]

In the first case it doesn't show the "".
Comment 4 Meta 2014-10-08 11:59:17 UTC
*** Issue 10915 has been marked as a duplicate of this issue. ***
Comment 5 bearophile_hugs 2014-10-31 20:37:05 UTC
This has improved the situation:
https://github.com/D-Programming-Language/phobos/pull/2587


But the example in comment #1 still fails:


void main() {
    import std.stdio: writeln;
    import std.typecons: Nullable;
    const(Nullable!int) c;
    writeln(c);
}


core.exception.AssertError@C:\dmd2\src\phobos\std\typecons.d(1529): Called `get' on null Nullable!int.
Comment 6 bearophile_hugs 2014-10-31 20:38:23 UTC
*** Issue 10915 has been marked as a duplicate of this issue. ***
Comment 7 Tobias Pankrath 2019-07-13 15:37:19 UTC
import std.stdio;
import std.typecons;

void main() {
	Nullable!string s;
	writeln(s);
}

now prints "Nullable.null".