September 17, 2020
On Thursday, 17 September 2020 at 00:09:43 UTC, Paul Backus wrote:
> On Wednesday, 16 September 2020 at 19:01:28 UTC, Jacob Carlborg wrote:
>>
>> I would like that. It should work for an Optional/Nullable type as well. It's a good idea to add an `??` operator at the same time as well:
>>
>> auto a = A ?? B;
>>
>> if `A` is not null, assign `A` to `a`. Otherwise assign `B` to `a`.
>
> Last time this was discussed, someone posted the following library version:
>
> T orElse(T)(T value, lazy T alternative)
> {
>     return value ? value : alternative;
> }
>
> auto a = A.orElse(B);

Also in the same library previously mentioned: https://aliak00.github.io/optional/optional/or/or.html


September 17, 2020
On Wednesday, 16 September 2020 at 19:01:28 UTC, Jacob Carlborg wrote:
>
> I would like that. It should work for an Optional/Nullable type as well. It's a good idea to add an `??` operator at the same time as well:
>
> auto a = A ?? B;
>
> if `A` is not null, assign `A` to `a`. Otherwise assign `B` to `a`.

This is also known as "||". :-)

It only requires the change that || return the merged truthy type of its parameters rather than bool. For instance, for objects 'a || b' would merge to the most derived superclass of a and b.
September 17, 2020
On Thursday, 17 September 2020 at 00:09:43 UTC, Paul Backus wrote:
> On Wednesday, 16 September 2020 at 19:01:28 UTC, Jacob Carlborg wrote:
>>
>> I would like that. It should work for an Optional/Nullable type as well. It's a good idea to add an `??` operator at the same time as well:
>>
>> auto a = A ?? B;
>>
>> if `A` is not null, assign `A` to `a`. Otherwise assign `B` to `a`.
>
> Last time this was discussed, someone posted the following library version:
>
> T orElse(T)(T value, lazy T alternative)
> {
>     return value ? value : alternative;
> }
>
> auto a = A.orElse(B);

`orElse` was also proposed for Phobos, but it was intended for ranges.
It could be combined though:

```
myClassInstance.orElse(otherClassInstance); // class
"".orElse("fallback"); // ranges
Nullable!int nInt;
nInt.orElse(42); // nullable
```
September 17, 2020
On Saturday, 12 September 2020 at 16:51:20 UTC, Per Nordlöw wrote:
> Has there been any discussions on adding the ?. operator to simplify structure matching on class trees typically found in compilers such as dmd.
>
> Basically, implemented via lowering of
>
>     C ?. EXPR
>
> to
>
>     C ? C.EXPR : EXPR.init
>
> when EXPR has type class or pointer and for the other cases either
>
>     C ? C.EXPR : EXPR.init
>
> or perhaps even
>
>     C ? C.EXPR : nullable(EXPR).init
>
> if nullable is made part of the runtime or even builtin.
>
> Given that `C` is a class or pointer to an aggregate.
>
> C# supports has this [1].
>
> [1] https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/member-access-operators#null-conditional-operators--and-

In general I'm wary of special syntax for particular instances of monads.
September 17, 2020
On Thursday, 17 September 2020 at 07:06:24 UTC, FeepingCreature wrote:
> It only requires the change that || return the merged truthy type of its parameters rather than bool. For instance, for objects 'a || b' would merge to the most derived superclass of a and b.

That is an interesting idea. Which statically typed languages has taken a similar approach? I wonder what Andrei thinks about this.
September 17, 2020
On 9/17/20 3:33 PM, Per Nordlöw wrote:
> On Thursday, 17 September 2020 at 07:06:24 UTC, FeepingCreature wrote:
>> It only requires the change that || return the merged truthy type of its parameters rather than bool. For instance, for objects 'a || b' would merge to the most derived superclass of a and b.
> 
> That is an interesting idea. Which statically typed languages has taken a similar approach? I wonder what Andrei thinks about this.

I recall Perl does something similar with its "or" operator. Changing || that way now would be too much breakage.
September 17, 2020
On Thursday, 17 September 2020 at 19:38:01 UTC, Andrei Alexandrescu wrote:
> I recall Perl does something similar with its "or" operator. Changing || that way now would be too much breakage.

Python's `or` behaves the same which is mimicked by

https://dlang.org/phobos/std_algorithm_comparison.html#either

Note that I explicitly asked for statically typed languages. I wonder what the behavior is for functional languages.
September 18, 2020
On 2020-09-16 23:26, Per Nordlöw wrote:

> You're saying you want the variant with `nullable` and make `nullable` builtin?

Not necessarily. It could be an overloadable operator that could be used on any struct/class.

Ideally I would like pointers and reference types to be non-nullable by default. Then have built-in support for optional types. Kind of like Swift.

int* a = null; // error, pointers cannot be null
int*? a = null; // fine, optional pointer to int
int? a = null; // fine, optional int

-- 
/Jacob Carlborg
September 18, 2020
On 2020-09-17 21:38, Andrei Alexandrescu wrote:

> I recall Perl does something similar with its "or" operator.
Ruby does the same thing too.

-- 
/Jacob Carlborg
September 18, 2020
On Saturday, 12 September 2020 at 19:26:30 UTC, Stefan Koch wrote:
> On Saturday, 12 September 2020 at 16:51:20 UTC, Per Nordlöw wrote:
>> Has there been any discussions on adding the ?. operator to simplify structure matching on class trees typically found in compilers such as dmd.
>
> Hmm the problem with .? making implicit null checks is that it encourages
> null checks.
> Rather than encouraging a state in which existence and logic are statically asserted.

Absolutely.

Using a "functional" orientation with "only(p)" as alternative to  "MayBe" monad, an unwrapping with "fold( fun )(initialValue)" function with a default value:


> void main(){
>   Person p = new Person("Peter", new Person("John",null));
>   auto name =  only(p).
>                filter!"a !is null".map!"a.father".
>                filter!"a !is null".map!"a.father".
>                filter!"a !is null".map!"a.name".
>                fold!"b"("Unknown");
>   writeln( format!"The name of your great grandfather is %s"(name) );
> }
> 
> class Person {
>   string name;
>   Person father;
>   this(string name, Person father) {
>     this.name=name;
>     this.father=father;
>   }
> }

We can unify

> .filter!"a !is null".map!(func)

as an alternative template

> .n!(func)

and unfold using

> .getOrElse(defaultValue)

that unifies

> .fold!"b"(initValue)

The result could be

> auto name =  only(p).n!"a.father".n!"a.father".n!"a.name".getOrElse("Unknown");

That is verbose, may be inneficient, but a nice experiment :-)