February 14, 2020
On Friday, 14 February 2020 at 17:04:28 UTC, Adnan wrote:
> 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?


It seems to be an attempt to implement a functor in idiomatic D.
In Haskell you have lists and you can map over lists. For example:

fmap (+1) [1, 2, 3]

will add 1 to each element of the list [1, 2, 3]. But you can map over many other different types, such as Maybe

fmap (+1) Nothing

will return Nothing.

fmap (+1) (Just 1)

will return (Just 2).

You can map over Eithers, e.g. for either string or integer:

fmap (+1) (Left "some type")

will return 'Left "some type"'.

fmap (+1) (Right 5)

will return 'Right 6'.

Haskell has even an "empty" function which returns "Nothing" for Maybe, or an empty list for lists. But maybes have nothing to do with lists in Haskell.

Functors allow to write concise, type safe code without all that "if-noise"

if (a.isNothing) {
    do some stuff
} else {
    I don't care
}

Functors is a very generic concept, appliable to many data types and there is a bunch of functions that work on functors. Since in D all kinds of algorithms are implemented for ranges, Optional seems to try to use it and say: Well let us imagine we have a range which can be empty or contain at most one element. It is pretty the same as Maybe/Option/Optional, but many algorithms that work on ranges (such as map) can be applied to this type.

Not sure if it is an answer, but I think it is the actual background.
February 14, 2020
On Friday, 14 February 2020 at 17:04:28 UTC, Adnan wrote:
> 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)`?

Aliak's package offers several features in addition to the range interface that make it more convenient to work with than a simple array. You can see a list in the README:

https://github.com/aliak00/optional/blob/v1.0.0/README.md#features
February 14, 2020
On Friday, 14 February 2020 at 17:04:28 UTC, Adnan wrote:
> 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?

Ya! If you take scala for e.g. Optional!T is an attempt to model a lot of what scala does. I.e. it's a range. If you want to get to the element you have to check if it exists first, else you manipulate it via functional primitives like map. You need to do the same in scala, kotlin, swift for e.g.

I used to have an unwrap function in there as well, and you could do:

if (auto v = optional.unwrap) {
  // you get a pointer to T here and in D you can access members of a pointer
  // just like it wasn't a pointer.
}

But that proved to be hard to keep @safe.

I've never been a 100% on the whole operator overloading though. The difference between how it's implemented here and other places is that it's a noop if the optional is empty.

In swift you can call functions on optionals even if they're empty, so that's what the oc utility in optional is for, and the opBinary was a way to add that same functionality for D operators and array access.

Basically, operating on an optional is ok and always results in an optional. And it must always maintain it's emptiness if any of the operands are empty.

>
> 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)`?

I've tried to outline as much as possible in the readme. In a nutshell though: intent, @nogc, safe access, no need to worry about having more than one element - I may be forgetting some things.

Cheers,
- ali
1 2
Next ›   Last »