Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nilability ergonomics: optional chaining #17577

Open
vasslitvinov opened this issue Apr 16, 2021 · 4 comments
Open

Nilability ergonomics: optional chaining #17577

vasslitvinov opened this issue Apr 16, 2021 · 4 comments

Comments

@vasslitvinov
Copy link
Member

Nilability ergonomics / convenience features have been proposed in #12614 and forked off into #16931. The first of them is the topic of #13639, already implemented.

This issue requests the second convenience feature that is akin to Swift's Optional Chaining

This feature is a shorthand for this kind of conditional expression:

if const xTemp = x then xTemp.someMethod() else nil

that uses this syntax, which is inspired by Swift:

x?.someMethod()

This syntax probably entails defining a new postfix operator ?. to differentiate from the the postfix ?, which is allowed only on types.

The semantics is clear when x is a class and someMethod() returns a class, nilable or non-nilable.

A design question is: should we allow it for other types? For non-classes, the semantics could be:

x?.someMethod()
// is equivalent to:
if x then x.someMethod() else <the default value of x.type>

A consideration here is whether the user can tell, from the result of the expression, whether the then or else branch was taken. It is possible in the case where x is a class and someMethod() returns a non-nilable class, otherwise it is not possible to tell.

@vasslitvinov vasslitvinov self-assigned this Apr 16, 2021
@mppf
Copy link
Member

mppf commented Apr 19, 2021

Sounds good to me.

should we allow it for other types?

I'd expect it would work with e.g. option(int) once that exists.

@vasslitvinov
Copy link
Member Author

I'd expect it would work with e.g. option(int) once that exists.

Right. Then, what if there is no option? Ex.

var x = 5;
var y = x?.someMethodOnInts();

Should x?. be an error in this case?

If so, should x?. be an error when x is a non-"option" class type, i.e., a non-nilable class?
One can view a non-nilable class as a couterpart to a non-option int.

@mppf
Copy link
Member

mppf commented Apr 19, 2021

I'd lean towards having x?. be an error if there is no option class. However it also seems like it might be useful to do something else for it, to enable generic programming. Let's suppose we have int.someMethod(): real. Then I would expect 1?.someMethod() to return new option(1.someMethod()) - in other words, to wrap the result in an option.

Taken back to classes, let us suppose we have class types C and D.
If we write myC?.methodReturningD()then I would expect the result to be D? (with the appropriate memory management according to the return type of methodReturningD).

It would be good to know what approach Swift takes for these cases. Can you investigate?

@vasslitvinov
Copy link
Member Author

Optional chaining In Swift states that the result of an ?. expression is always an optional, even when the invoked function is non-optional.

This is necessary -- because ?. can be applied only to an optional value. Therefore the result of a ?. may indeed be a nil.

So, should we disallow ?. on non-optional things in Chapel, too, by analogy with Swift?

Alas, the Chapel-Swift analogy does not go very far. In particular, Chapel allows postfix-! on non-nilable classes, while Swift does not allow postfix-! on non-optional values.

With that in mind, I propose the following rules:

  • Allow ?. on non-nilable classes (in addition to allowing it for nilable classes), so users can write generic code that works in both cases.
  • Make the result of ?. be non-nilable when both the receiver and the method are known to be non-nilable. Because this gives me more precise type information.
  • Disallow ?. on non-classes, by analogy to postfix-! being currently disallowed on non-classes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants