www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Adding the ?. operator to D

reply Per =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
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.



[1] 
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/member-access-operators#null-conditional-operators--and-
Sep 12 2020
next sibling parent Paul Backus <snarwin gmail.com> writes:
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.
The package 'optional' on dub has a library version of this: https://aliak00.github.io/optional/optional/oc/oc.html
Sep 12 2020
prev sibling next sibling parent reply Stefan Koch <uplink.coder googlemail.com> writes:
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.
Sep 12 2020
next sibling parent aberba <karabutaworld gmail.com> writes:
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.
However, its been implemented in most places due its common use in code.
Sep 13 2020
prev sibling next sibling parent Per =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Saturday, 12 September 2020 at 19:26:30 UTC, Stefan Koch wrote:
 Rather than encouraging a state in which existence and logic 
 are statically asserted.
Are you referring to non-nullable classes? Which has been discussed at older DConfs.
Sep 13 2020
prev sibling parent ddcovery <antoniocabreraperez gmail.com> writes:
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 :-)
Sep 18 2020
prev sibling next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2020-09-12 18:51, 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.
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`. -- /Jacob Carlborg
Sep 16 2020
next sibling parent reply Per =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Wednesday, 16 September 2020 at 19:01:28 UTC, Jacob Carlborg 
wrote:
      C ? C.EXPR : nullable(EXPR).init
 
I would like that. It should work for an Optional/Nullable type as well.
You're saying you want the variant with `nullable` and make `nullable` builtin? A interesting alternative would be to return `&C.EXPR` on success and null otherwise. Kind of like the `in` operator does.
Sep 16 2020
parent Jacob Carlborg <doob me.com> writes:
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
Sep 18 2020
prev sibling next sibling parent reply Paul Backus <snarwin gmail.com> writes:
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);
Sep 16 2020
next sibling parent Aliak <something something.com> writes:
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
Sep 16 2020
prev sibling parent Seb <seb wilzba.ch> writes:
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 ```
Sep 17 2020
prev sibling next sibling parent Russel Winder <russel winder.org.uk> writes:
On Wed, 2020-09-16 at 21:01 +0200, Jacob Carlborg via Digitalmars-d wrote:

 It's a good idea to add an `??` operator at the same time as well:
=20
 auto a =3D A ?? B;
=20
 if `A` is not null, assign `A` to `a`. Otherwise assign `B` to `a`.
Groovy 1.5 introduced the Elvis Operator, ?:, for this, and most other JVM languages have since followed suit. It seems though GNU C and C++ got there first: https://en.wikipedia.org/wiki/Elvis_operator a =3D x ?: y is a =3D x ? x : y with the semantics "if x does not have Boolean evaluation false then x else y". --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D Dr Russel Winder t: +44 20 7585 2200 41 Buckmaster Road m: +44 7770 465 077 London SW11 1EN, UK w: www.russel.org.uk
Sep 16 2020
prev sibling parent reply FeepingCreature <feepingcreature gmail.com> writes:
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.
Sep 17 2020
parent reply Per =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
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.
Sep 17 2020
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.com> writes:
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.
Sep 17 2020
next sibling parent Per =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
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.
Sep 17 2020
prev sibling next sibling parent Jacob Carlborg <doob me.com> writes:
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
Sep 18 2020
prev sibling parent Atila Neves <atila.neves gmail.com> writes:
On Thursday, 17 September 2020 at 19:38:01 UTC, Andrei 
Alexandrescu wrote:
 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.
Perl5 has `or` *and* `||` and they have different precedence because, well, it's Perl.
Sep 22 2020
prev sibling parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Thursday, 17 September 2020 at 19:33:43 UTC, 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.
Languages with Flow-typing.
Sep 22 2020
prev sibling next sibling parent Denis Feklushkin <feklushkin.denis gmail.com> writes:
On Saturday, 12 September 2020 at 16:51:20 UTC, Per Nordlöw wrote:
 Has there been any discussions on adding the ?. operator
?: Try to search word "Elvis" on this forum
Sep 16 2020
prev sibling parent Atila Neves <atila.neves gmail.com> writes:
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.



 [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.
Sep 17 2020