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

Proposal: out patterns #11293

Closed
alrz opened this issue May 13, 2016 · 13 comments
Closed

Proposal: out patterns #11293

alrz opened this issue May 13, 2016 · 13 comments

Comments

@alrz
Copy link
Contributor

alrz commented May 13, 2016

Proposal: out patterns

out var would allow a variable be declared at the same time that is it passed as an out parameter:

public static bool RegexMatch(this string str, string pattern, out string[] captures) {..}

if(str.RegexMatch(pattern, out var captures)) {..}

But if you want to also match the output, you will need to use a separate is expression (assuming array patterns),

if(str.RegexMatch(pattern, out var captures) && captures is { "abc", "123" }) {..}

The idea is to be able to use a pattern in front of out keyword for bool-returning methods, so that the simple form is a var-pattern,

if(str.RegexMatch(pattern, out { "abc", "123" }) {..}

If the method returns false the pattern would not be evaluated and immediately fails. In case of a complete pattern, it always succeeds regardless of the return value,

if(d.TryGetValue(key, out (var x, var y))) {..}

The advantage of this approach compared to the first example (using is and &&) is that you can use recursive patterns right in font of out, while with is and && it will become complicated very fast.

EDIT: The pattern can be restricted to only complete patterns so that it doesn't depend on the method.

@HaloFour
Copy link

If deconstruction and possibly recursive/active patterns are going to employ out parameters then I do think that something like this would be very useful. However it does kind of go against the grain of pattern variables resulting in new readonly variables.

@alrz
Copy link
Contributor Author

alrz commented May 13, 2016

@HaloFour Swift uses let and var to declare both read-only and regular variables in patterns, I think it might come in handy in C# as well.

@HaloFour
Copy link

HaloFour commented May 13, 2016

@alrz

So are you proposing the three following patterns?

var - binds expression to new read/write variable
let - binds expression to a new readonly variable
out - binds expression to an existing read/write variable

public static int Weird((int, int, int) tuple, out int x) {
    let (out x, var y, let z) = tuple; // assigns x
    y += z; // can modify y, but not z
    return y;
)

@alrz
Copy link
Contributor Author

alrz commented May 13, 2016

@HaloFour out is not part of the pattern here, it's a part of argument syntax as it is right now,

argument-value:
expression
ref variable-reference
out variable-reference
out pattern

So you will have:

F(out var x);             // read/write
F(out let x);              // readonly
G(out (var x, var y));
G(out (let x, let y));

There is some interactions between this and already proposed tuple declarators in out var,

G(out var (x, y)); // read/write

Which I think can be still integrated to patterns via the identifier-pattern which I described before,

G(out let (x, y)); // readonly

This is applicable to all the places that we have patterns (like switch) or tuple declarators (like foreach).

@HaloFour
Copy link

I see what you're doing, this is not related to your comment here: #9005 (comment)

I can see some utility in this proposal but it feels weird given that it assumes that the return value from the method is related to the pattern. I honestly think that the first example (with && and is) is cleaner than trying to stuff the pattern directly into the argument.

@alrz
Copy link
Contributor Author

alrz commented May 13, 2016

@HaloFour The thing is, wherever I can deconstruct a tuple (e.g foreach, out), I expect to be able to use other patterns as well. However, the proposed syntax seems to be future-proof for when we actually have "other patterns".

@HaloFour
Copy link

@alrz

So, you'd expect the following to work?

string s = "2";
if (int.TryParse(s, out 2)) {
    Console.WriteLine("Yup, it's a two.");
}

@alrz
Copy link
Contributor Author

alrz commented May 13, 2016

@HaloFour

Yes, it might not be always useful, just like obj is var x, but I don't care much to make it illegal.

Alternatively, if we only allow complete patterns. all of these edge cases would just go away.

@GSPP
Copy link

GSPP commented May 16, 2016

Is this not equivalent to "var patterns" that were proposed before and almost made it into the language?

One could write a function ToVar(T val, out T valOut) { valOut = val; } and say ToVar(1+2, out var myVal) to obtain something equivalent to var patterns.

var patterns would be more general and more convenient. I'd like to have them but I don't remember the reason they did not make it.

@alrz
Copy link
Contributor Author

alrz commented May 16, 2016

@GSPP Currently out vars don't use var patterns, therefore they do not support patterns at all, so the two are not the same thing, but could be. Tuple decomposition in out var is a special case which I proposed it to be not. In fact, I don't know why #10642 exists when we have patterns on the way.

var patterns would be more general and more convenient. I'd like to have them but I don't remember the reason they did not make it.

They did. See #10866.

@GSPP
Copy link

GSPP commented May 16, 2016

I'm not speaking of pattern matching @alrz. I seem to miss the right term. I meant:

if ((var x = F()) > 0) ...

@alrz
Copy link
Contributor Author

alrz commented May 16, 2016

@GSPP that's a declaration expression (#254), not sure how it is related to out var or var patterns.

@alrz
Copy link
Contributor Author

alrz commented Aug 27, 2016

The advantage of this approach compared to the first example (using is and &&) is that you can use recursive patterns right in font of out, while with is and && it will become complicated very fast.

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

No branches or pull requests

4 participants