Jump to page: 1 2
Thread overview
What is the rationale behind enabling Nullable!T to be used as a regular T?
Feb 14
Adnan
Feb 14
DanielG
Feb 14
Adnan
Feb 14
Adnan
Feb 14
aliak
Feb 14
Elronnd
February 14
Nullable!T, as I understand is somewhat similar to Rust's Option<T>. It's meant to be an alternative to sentinel value based error checking.

In regular Rust code if you do something like

let x: Option<i32> = None;
println!("{}", x + 4);

It should throw compile error, since the `x` in `x + 4` is not checked for null. OpAdd<rhs = i32> is not implemented for Option<i32> for that reason.

Of course, you can get the value using the unwrap() method, which would create runtime crash for null option. However when typing-out "unwrap()" you understand what you are signing up for.


Back to D.

const Nullable!int a;
assert(a.isNull);
writeln(a + 4); // compiles with 0 warnings

Why is opBinary implemented for Nullable!T? Doesn't it defeat its purpose?


February 14
On Friday, 14 February 2020 at 08:54:41 UTC, Adnan wrote:
> What is the rationale behind enabling Nullable!T to be used as a regular T?

The rationale is we have a few more months to wait before the deprecation period for that functionality runs out and we can remove it. :)

> Back to D.
>
> const Nullable!int a;
> assert(a.isNull);
> writeln(a + 4); // compiles with 0 warnings
>
> Why is opBinary implemented for Nullable!T? Doesn't it defeat its purpose?

If you switch to 2.090.1, you will get warnings there. If you run with -de, the warnings will be errors.

---

The original reason was I believe that Nullable was never really intended to be Optional, it was intended to give types a "null" state like objects and pointers. Well, objects and pointers crash when you access them if they're null, so...

(No, it's not a very good reason.)
February 14
There's also the 'optional' package if you're looking for something more functional-program-ey:

https://code.dlang.org/packages/optional


February 14
On Friday, 14 February 2020 at 10:35:52 UTC, DanielG wrote:
> There's also the 'optional' package if you're looking for something more functional-program-ey:
>
> https://code.dlang.org/packages/optional

Not sure if this is any better

/+dub.sdl:
dependency "optional" version="~>1.0.0"
+/
import optional;

void main(const string[] args) {
    static import std;
    const auto n = no!int();
    std.writeln(n + 4); // []
}
February 14
On Friday, 14 February 2020 at 12:40:54 UTC, Adnan wrote:
> On Friday, 14 February 2020 at 10:35:52 UTC, DanielG wrote:
>> There's also the 'optional' package if you're looking for something more functional-program-ey:
>>
>> https://code.dlang.org/packages/optional
>
> Not sure if this is any better
>
> /+dub.sdl:
> dependency "optional" version="~>1.0.0"
> +/
> import optional;
>
> void main(const string[] args) {
>     static import std;
>     const auto n = no!int();
>     std.writeln(n + 4); // []
> }

It's by design. optional presents a range interface of length 0 or 1.

See the docs for more info: https://github.com/aliak00/optional/#summary
February 14
On Friday, 14 February 2020 at 08:54:41 UTC, Adnan wrote:
> Nullable!T, as I understand is somewhat similar to Rust's Option<T>. It's meant to be an alternative to sentinel value based error checking.
>
> In regular Rust code if you do something like
>
> let x: Option<i32> = None;
> println!("{}", x + 4);
>
> It should throw compile error, since the `x` in `x + 4` is not checked for null. OpAdd<rhs = i32> is not implemented for Option<i32> for that reason.

The two ends of the design spectrum (as I see it) are:
1. `Optional(T) x` as a range of [0,1] elements of type `T`. For all possible operations `op` on type `T` there exists an operation `Option(T).op` and the effect of executing is equivalent to `x.map!fun`. This is what aliak's optional package provides.

2. `Optional(T) x` behaves like a null-able pointer. The compiler statically prevents dereferencing if it can't prove that x is non-null. Such as scheme (although limited to just pointers for now) is work in progress:
https://github.com/dlang/dmd/blob/master/changelog/ob.md
February 14
On Friday, 14 February 2020 at 14:43:22 UTC, Petar Kirov [ZombineDev] wrote:
>
> The two ends of the design spectrum (as I see it) are:
> 1. `Optional(T) x` as a range of [0,1] elements of type `T`. For all possible operations `op` on type `T` there exists an operation `Option(T).op` and the effect of executing is equivalent to `x.map!fun`.

Edit: `x.map!op`.


February 14
On Friday, 14 February 2020 at 12:40:54 UTC, Adnan wrote:
> On Friday, 14 February 2020 at 10:35:52 UTC, DanielG wrote:
>> There's also the 'optional' package if you're looking for something more functional-program-ey:
>>
>> https://code.dlang.org/packages/optional
>
> Not sure if this is any better
>
> /+dub.sdl:
> dependency "optional" version="~>1.0.0"
> +/
> import optional;
>
> void main(const string[] args) {
>     static import std;
>     const auto n = no!int();
>     std.writeln(n + 4); // []
> }

With std.typecons post deprecation:

import std.typecons;

void main() {
  static import std;
  const auto n = Nullable!int();
  std.writeln(n.apply!(i => i + 4)); // Nullable!int()
}

February 14
On Friday, 14 February 2020 at 08:54:41 UTC, Adnan wrote:
> Nullable!T, as I understand is somewhat similar to Rust's Option<T>. It's meant to be an alternative to sentinel value based error checking.

Not exactly, as others have mentioned.  But there is https://github.com/moon-chilled/tenbots-opensource/blob/master/maybe.d (which originally comes from https://github.com/dkhasel/maybe-d, but I cleaned it up a bit).  At one point, I wrote a wrapper which would let you write a function with a return type of Maybe!T, but which actually returned objects of type T.  But that was a giant hack and not at all worth it.
February 14
On Friday, 14 February 2020 at 14:43:22 UTC, Petar Kirov [ZombineDev] wrote:
> On Friday, 14 February 2020 at 08:54:41 UTC, Adnan wrote:
> The two ends of the design spectrum (as I see it) are:
> 1. `Optional(T) x` as a range of [0,1] elements of type `T`. For all possible operations `op` on type `T` there exists an operation `Option(T).op` and the effect of executing is equivalent to `x.map!fun`. This is what aliak's optional package provides.

Very interesting. I always thought that Option<T> is a type-guard for enforced null checks (I could be wrong here). But seems to me that this design circles back to square 1: having the callee remember to check if the length of the range is 0 or 1. Which is essentially similar to check sentinel values (i.e. check if the binarysearch returns -1 as index). What languages do this?

What does Aliak's package provide that's fundamentally different to just returning a T[]? Empty T[] would mean `None` and a T[] with 1 item means `Some(T)`?

> 2. `Optional(T) x` behaves like a null-able pointer. The compiler statically prevents dereferencing if it can't prove that x is non-null. Such as scheme
Nim's optional works this way too:

import options

let v = none(int)
echo v + 4 # error

Scala:

val a: Option[Int] = None
println(a + 4) // compile error

Even C++:

#include <iostream>
#include <optional>

auto main() -> int {
   std::optional<int> a;
   std::cout << a + 4 << std::endl; // compile error
}

>(although limited to just
> pointers for now) is work in progress:
> https://github.com/dlang/dmd/blob/master/changelog/ob.md

Nice, any chance it's going to work with non-ptrs too?

« First   ‹ Prev
1 2