Skip to content

Commit

Permalink
Treat pointer types as reference types
Browse files Browse the repository at this point in the history
  • Loading branch information
aliak00 committed Jul 28, 2019
1 parent de223a7 commit 5909d56
Show file tree
Hide file tree
Showing 4 changed files with 11 additions and 24 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ Nullable!C a = null;
writeln(a.isNull); // prints false
```

With classes you end up having to write code like this:
With refernece types (e.g., pointers, classes, functions) you end up having to write code like this:

```d
void f(T)(Nullable!T a) {
Expand Down
14 changes: 2 additions & 12 deletions source/optional/oc.d
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ private string autoReturn(string expression)() {
}
alias R = typeof(val());
static if (is(R == void)) {
if (!empty) {
if (!value.empty) {
val();
}
} else {
if (empty) {
if (value.empty) {
return OptionalChain!R(no!R());
}
static if (isOptional!(typeof(expr()))) {
Expand Down Expand Up @@ -65,16 +65,6 @@ private struct OptionalChain(T) {
}

public template opDispatch(string name) if (hasMember!(T, name)) {
bool empty() @safe @nogc pure const {
import std.traits: isPointer;
static if (isPointer!T) {
// Optional doens't consider a null pointer as empty, so we need to check
// for it explicitly
return value.empty || value.front is null;
} else {
return value.empty;
}
}
import optional: no, some;
static if (is(typeof(__traits(getMember, T, name)) == function)) {
auto opDispatch(Args...)(auto ref Args args) {
Expand Down
15 changes: 6 additions & 9 deletions source/optional/optional.d
Original file line number Diff line number Diff line change
Expand Up @@ -37,23 +37,21 @@ private static string autoReturn(string expression)() {
/**
Optional type. Also known as a Maybe or Option type in some languages.
This can either contain a value or be `none`. It works with any value, including
values that can be null. I.e. null is a valid value that can be contained inside
an optional if T is a pointer type
This can either contain a value or be `none`. If the value is a refernce type then
`null` is considered `none`.
It also has range like behavior. So this acts as a range that contains 1 element or
is empty. Similar to `std.algorithm.only`
is empty.
And all operations that can be performed on a T can also be performed on an Optional!T.
The behavior of applying an operation on a no-value or null pointer is well defined
and safe.
*/

struct Optional(T) {
import std.traits: isMutable, isSomeFunction, isAssignable, Unqual;
import std.traits: isMutable, isSomeFunction, isAssignable, isPointer;

private enum isNullInvalid = is(T == class) || is(T == interface) || isSomeFunction!T;
private enum isNullable = is(typeof(T.init is null));
private enum isNullInvalid = is(T == class) || is(T == interface) || isSomeFunction!T || isPointer!T;

private T _value = T.init; // Set to init for when T has @disable this()
private bool defined = false;
Expand Down Expand Up @@ -170,7 +168,6 @@ struct Optional(T) {
---
*/
auto opUnary(string op, this This)() {
import std.traits: isPointer;
static if (op == "*" && isPointer!T) {
import std.traits: PointerTarget;
alias P = PointerTarget!T;
Expand Down Expand Up @@ -334,7 +331,7 @@ public auto no(T)() {
assert(*a == 9);
assert(a != none);
a = null;
assert(a != none);
assert(a == none);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions tests/optional.d
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ unittest {
assert(!o.empty);
}

@("Should preserve nulls with array of pointers")
@("Should handle nulls with array of pointers")
@safe unittest {
struct S {
int i;
Expand All @@ -426,7 +426,7 @@ unittest {
auto c = [new S(1), new S(2), new S(3)].some;

assert(a[2] == none);
assert(b[2] != none);
assert(b[2] == none);
assert(c[2] != none);
}

Expand Down

0 comments on commit 5909d56

Please sign in to comment.