Merge pull request #3114 from MetaLang/nullable-doc-fixes

Improve Nullable documentation
This commit is contained in:
JakobOvrum 2015-04-18 15:25:09 +09:00
commit ddfd111ab5

View file

@ -1764,6 +1764,9 @@ struct Nullable(T)
/** /**
Constructor initializing $(D this) with $(D value). Constructor initializing $(D this) with $(D value).
Params:
value = The value to initialize this `Nullable` with.
*/ */
this(inout T value) inout this(inout T value) inout
{ {
@ -1789,13 +1792,26 @@ Constructor initializing $(D this) with $(D value).
} }
/** /**
Returns $(D true) if and only if $(D this) is in the null state. Check if `this` is in the null state.
Returns:
true $(B iff) `this` is in the null state, otherwise false.
*/ */
@property bool isNull() const @safe pure nothrow @property bool isNull() const @safe pure nothrow
{ {
return _isNull; return _isNull;
} }
///
unittest
{
Nullable!int ni;
assert(ni.isNull);
ni = 0;
assert(!ni.isNull);
}
/** /**
Forces $(D this) to the null state. Forces $(D this) to the null state.
*/ */
@ -1805,9 +1821,22 @@ Forces $(D this) to the null state.
_isNull = true; _isNull = true;
} }
///
unittest
{
Nullable!int ni = 0;
assert(!ni.isNull);
ni.nullify();
assert(ni.isNull);
}
/** /**
Assigns $(D value) to the internally-held state. If the assignment Assigns $(D value) to the internally-held state. If the assignment
succeeds, $(D this) becomes non-null. succeeds, $(D this) becomes non-null.
Params:
value = A value of type `T` to assign to this `Nullable`.
*/ */
void opAssign()(T value) void opAssign()(T value)
{ {
@ -1815,9 +1844,32 @@ succeeds, $(D this) becomes non-null.
_isNull = false; _isNull = false;
} }
/**
If this `Nullable` wraps a type that already has a null value
(such as a pointer), then assigning the null value to this
`Nullable` is no different than assigning any other value of
type `T`, and the resulting code will look very strange. It
is strongly recommended that this be avoided by instead using
the version of `Nullable` that takes an additional `nullValue`
template argument.
*/
unittest
{
//Passes
Nullable!(int*) npi;
assert(npi.isNull);
//Passes?!
npi = null;
assert(!npi.isNull);
}
/** /**
Gets the value. $(D this) must not be in the null state. Gets the value. $(D this) must not be in the null state.
This function is also called for the implicit conversion to $(D T). This function is also called for the implicit conversion to $(D T).
Returns:
The value held internally by this `Nullable`.
*/ */
@property ref inout(T) get() inout @safe pure nothrow @property ref inout(T) get() inout @safe pure nothrow
{ {
@ -1826,6 +1878,20 @@ This function is also called for the implicit conversion to $(D T).
return _value; return _value;
} }
///
unittest
{
import std.exception: assertThrown, assertNotThrown;
Nullable!int ni;
//`get` is implicitly called. Will throw
//an AssertError in non-release mode
assertThrown!Throwable(ni == 0);
ni = 0;
assertNotThrown!Throwable(ni == 0);
}
/** /**
Implicitly converts to $(D T). Implicitly converts to $(D T).
$(D this) must not be in the null state. $(D this) must not be in the null state.
@ -1836,11 +1902,33 @@ $(D this) must not be in the null state.
/// ///
unittest unittest
{ {
Nullable!int a; struct CustomerRecord
assert(a.isNull); {
a = 5; string name;
assert(!a.isNull); string address;
assert(a == 5); int customerNum;
}
Nullable!CustomerRecord getByName(string name)
{
//A bunch of hairy stuff
return Nullable!CustomerRecord.init;
}
auto queryResult = getByName("Doe, John");
if (!queryResult.isNull)
{
//Process Mr. Doe's customer record
auto address = queryResult.address;
auto customerNum = queryResult.customerNum;
//Do some things with this customer's info
}
else
{
//Add the customer to the database
}
} }
unittest unittest
@ -2121,6 +2209,12 @@ particular value. For example, $(D Nullable!(uint, uint.max)) is an
$(D uint) that sets aside the value $(D uint.max) to denote a null $(D uint) that sets aside the value $(D uint.max) to denote a null
state. $(D Nullable!(T, nullValue)) is more storage-efficient than $(D state. $(D Nullable!(T, nullValue)) is more storage-efficient than $(D
Nullable!T) because it does not need to store an extra $(D bool). Nullable!T) because it does not need to store an extra $(D bool).
Params:
T = The wrapped type for which Nullable provides a null value.
nullValue = The null value which denotes the null state of this
`Nullable`. Must be of type `T`.
*/ */
struct Nullable(T, T nullValue) struct Nullable(T, T nullValue)
{ {
@ -2128,6 +2222,9 @@ struct Nullable(T, T nullValue)
/** /**
Constructor initializing $(D this) with $(D value). Constructor initializing $(D this) with $(D value).
Params:
value = The value to initialize this `Nullable` with.
*/ */
this(T value) this(T value)
{ {
@ -2152,7 +2249,10 @@ Constructor initializing $(D this) with $(D value).
} }
/** /**
Returns $(D true) if and only if $(D this) is in the null state. Check if `this` is in the null state.
Returns:
true $(B iff) `this` is in the null state, otherwise false.
*/ */
@property bool isNull() const @property bool isNull() const
{ {
@ -2168,6 +2268,17 @@ Returns $(D true) if and only if $(D this) is in the null state.
} }
} }
///
unittest
{
Nullable!(int, -1) ni;
//Initialized to "null" state
assert(ni.isNull);
ni = 0;
assert(!ni.isNull);
}
/** /**
Forces $(D this) to the null state. Forces $(D this) to the null state.
*/ */
@ -2176,18 +2287,58 @@ Forces $(D this) to the null state.
_value = nullValue; _value = nullValue;
} }
///
unittest
{
Nullable!(int, -1) ni = 0;
assert(!ni.isNull);
ni = -1;
assert(ni.isNull);
}
/** /**
Assigns $(D value) to the internally-held state. No null checks are Assigns $(D value) to the internally-held state. If the assignment
made. Note that the assignment may leave $(D this) in the null state. succeeds, $(D this) becomes non-null. No null checks are made. Note
that the assignment may leave $(D this) in the null state.
Params:
value = A value of type `T` to assign to this `Nullable`.
If it is `nullvalue`, then the internal state of
this `Nullable` will be set to null.
*/ */
void opAssign()(T value) void opAssign()(T value)
{ {
_value = value; _value = value;
} }
/**
If this `Nullable` wraps a type that already has a null value
(such as a pointer), and that null value is not given for
`nullValue`, then assigning the null value to this `Nullable`
is no different than assigning any other value of type `T`,
and the resulting code will look very strange. It is strongly
recommended that this be avoided by using `T`'s "built in"
null value for `nullValue`.
*/
unittest
{
//Passes
enum nullVal = cast(int*)0xCAFEBABE;
Nullable!(int*, nullVal) npi;
assert(npi.isNull);
//Passes?!
npi = null;
assert(!npi.isNull);
}
/** /**
Gets the value. $(D this) must not be in the null state. Gets the value. $(D this) must not be in the null state.
This function is also called for the implicit conversion to $(D T). This function is also called for the implicit conversion to $(D T).
Returns:
The value held internally by this `Nullable`.
*/ */
@property ref inout(T) get() inout @property ref inout(T) get() inout
{ {
@ -2198,13 +2349,57 @@ This function is also called for the implicit conversion to $(D T).
return _value; return _value;
} }
///
unittest
{
import std.exception: assertThrown, assertNotThrown;
Nullable!(int, -1) ni;
//`get` is implicitly called. Will throw
//an error in non-release mode
assertThrown!Throwable(ni == 0);
ni = 0;
assertNotThrown!Throwable(ni == 0);
}
/** /**
Implicitly converts to $(D T). Implicitly converts to $(D T).
Gets the value. $(D this) must not be in the null state. $(D this) must not be in the null state.
*/ */
alias get this; alias get this;
} }
///
unittest
{
Nullable!(size_t, size_t.max) indexOf(string[] haystack, string needle)
{
//Find the needle, returning -1 if not found
return Nullable!(size_t, size_t.max).init;
}
void sendLunchInvite(string name)
{
}
//It's safer than C...
auto coworkers = ["Jane", "Jim", "Marry", "Fred"];
auto pos = indexOf(coworkers, "Bob");
if (!pos.isNull)
{
//Send Bob an invitation to lunch
sendLunchInvite(coworkers[pos]);
}
else
{
//Bob not found; report the error
}
//And there's no overhead
static assert(Nullable!(size_t, size_t.max).sizeof == size_t.sizeof);
}
unittest unittest
{ {
import std.exception : assertThrown; import std.exception : assertThrown;