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

checking-keyword expression as a statement, where x is not a function-call-expr or method-call-expr #588

Closed
MaryamZi opened this issue Aug 13, 2020 · 8 comments
Assignees
Labels
design/dislike Do not like something about the design lang Relates to the Ballerina language specification sl-update-priority Priority for Swan Lake Updates

Comments

@MaryamZi
Copy link
Member

Description:
Can we use check x; or checkpanic x; as statements, where x is not a call-expr?

@pubudu91 pointed out that the spec only allows checking-keyword in call-stmt in statements.

IMO, this could be useful.

For example,

public function main() returns error? {
    error? x = dbCall();

    // Call a clean-up function that should be called
    // irrespective of whether the db call was successful 
    // (returned nil) or resulted in an error.
    cleanUp();

    // If `dbCall` failed, don't proceed.
    check x;

    // If `dbCall` was successful, proceed.
    onSuccess();
}

If this is not allowed, the user would have to use a type guard to check if x is an error and return?

The implementation allows this at the moment.

@jclark
Copy link
Collaborator

jclark commented Aug 13, 2020

That's an interesting example. The spec doesn't allow this currently.

We don't want to allow statements to arbitrary expressions, because something like:

1 + 2;

makes no sense. Similarly, we don't want to allow check expr to be a statement for arbitrary expressions.

We could change checking-action to:

checking-action := checking-keyword (action|variable-reference-expr)

Are there any other kinds of expression that make sense after check that are not currently allowed?

@jclark jclark self-assigned this Aug 13, 2020
@jclark jclark added this to the Swan Lake alpha milestone Aug 13, 2020
@jclark jclark added design/dislike Do not like something about the design lang Relates to the Ballerina language specification labels Aug 13, 2020
@MaryamZi
Copy link
Member Author

MaryamZi commented Aug 14, 2020

Even though not as appealing as the original example, I would think even an expression like member access may be used with the checking-keyword?

import ballerina/log;

map<error> errMap = {};

function getError(string key) returns error {
    // If the map has an entry with the specified key, return the value.
    check errMap[key];

    // If not, add a new error to the map, and return the new error.
    log:printInfo(string `Adding a new error entry for key '${key}'`);

    error e = error(string `Key '${key}' not found`);
    errMap[key] = e;
    return e;
}

We can of course write the same in different ways; a combination of lang.map:hasKey and lang.map:get, assigning the result of the member access to a variable and using checking-keyword with a variable reference (if that is allowed), etc.

But, should we consider allowing this with any expression whose static type is a subtype of error?, containing subtypes of both
error and ()?

@jclark
Copy link
Collaborator

jclark commented Aug 16, 2020

So your idea is:

  • the grammar should allow check expr for any expression
  • we should deal with meaningless cases via a constraint on the static type of the expression

? That's an interesting idea. I don't understand why you suggest that the constraint should require that it contain a subtype of ().

We should in any case have a constraint on check that the static type contains an error shape. Now that we are adding fail in #337, we should perhaps also have a constraint on check that the static type contains a non-error shape.

@MaryamZi
Copy link
Member Author

The suggestion to require a subtype of nil in this scenario was because if that is not the case, the static type of expr will be a subtype of error, where we can use return expr; (or fail expr;) directly instead of check expr;.

@jclark
Copy link
Collaborator

jclark commented Aug 17, 2020

Let me rephrase: why does it make sense to restrict the static type to be a subtype of error?. Couldn't you have a variable access that was e.g. error|string?

@jclark jclark modified the milestones: Swan Lake alpha, Later Aug 17, 2020
@MaryamZi
Copy link
Member Author

Sorry, that suggestion was specifically for the proposed change to checking-action.

Using check/checkpanic with an error|string static typed variable access (or any expression) is already allowed by checking-expr, right? Since the static type of checking-keyword expr in this case would be string (a non-nil type), we wouldn't be able to use it as a statement?

@jclark
Copy link
Collaborator

jclark commented May 12, 2022

We currently have in https://ballerina.io/spec/lang/2022R1/#call-stmt

call-stmt := call-expr ";"
call-expr :=
 function-call-expr ";"
   | method-call-expr ";"  
   | checking-keyword call-expr

We would then change this to be two statements. First:

call-stmt := call-expr ";"
call-expr :=
   function-call-expr ";"
    | method-call-expr ";"

with the constraint that the static type of call-expr is nil or never.

Second:

checking-stmt := checking-expr ";"

with the constraint that the static type of the checking-expr must be nil.

@MaryamZi Please review.

@jclark
Copy link
Collaborator

jclark commented May 12, 2022

This grammar will get changed by #1059

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
design/dislike Do not like something about the design lang Relates to the Ballerina language specification sl-update-priority Priority for Swan Lake Updates
Projects
None yet
Development

No branches or pull requests

2 participants