Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 46 additions & 1 deletion docs/design/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- [`return`](#return)
- [`returned var`](#returned-var)
- [`match`](#match)
- [`let`...`else` and `var`...`else`](#letelse-and-varelse)
- [User-defined types](#user-defined-types)
- [Classes](#classes)
- [Assignment](#assignment)
Expand Down Expand Up @@ -1231,6 +1232,39 @@ fn Foo() -> f32 {
> - Question-for-leads issue
> [#1283: how should pattern matching and implicit conversion interact?](https://github.com/carbon-language/carbon-lang/issues/1283)

#### `let`...`else` and `var`...`else`

**Note:** This is provisional, this design has not been through the proposal
process yet.
Comment on lines +1237 to +1238
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you help me understand the motivation for documenting this prior to formally proposing/adopting it? Unlike the initial stuff in #83 or your more recent design doc updates, this doesn't seem like it will help bootstrap the language design or provide important context, and unlike the discussion of const in #1378, I don't think this is something people will be asking about if we don't address it.

Copy link
Contributor Author

@josh11b josh11b Jul 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It actually came up because I was trying to figure out what belonged in "refutable patterns" versus "match control flow statement" when working on the design overview. (Resolution: the if clause is part of the case part of a match, not refutable patterns in general because they aren't as clearly useful for let/var...else.) It seemed like there were any design questions left for this feature after the Discord discussion, so I thought I'd just put a quick write up to show the direction we were thinking. I'm happy to follow this up with a real proposal, but I didn't expect that the leads would have the bandwidth to land one of those before the going-public talk, and I wanted to flesh out this design overview with as much of what we were thinking as I could before it got a lot of viewers.

I do think it is helpful to start pinning this down for thinking about the pattern matching (and possibly error handling) design space.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, I'm happy either way, no strong opinion.

I have lots of questions in this space, but I'm fine with the provisional writeup here. I don't think its going to cause deep misunderstandings even if we end up changing anything, or be off-putting for folks in any way absent a full rationale.

I wasn't part of the Discord discussion, I'd defer to @zygoloid and @KateGregory here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW I'm not worried about misunderstandings, I'm worried about anchoring.

For example, I think there's at least one major design question that the Discord discussion doesn't really address, which is whether we should have this feature at all. There may be other combinations of pattern matching/error handling features which would make this one superfluous, but I think this being in the language design, even provisionally, will tend to steer us away from considering them.

I understand the desire to put as much of what we're thinking as possible in front of people when we go public, but I don't think this is the right venue for that. docs/design should be the current actual design of Carbon, as determined by the evolution process, not our informal thoughts about where the evolution process will go in the future.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@josh11b created an issue to create a proposal out of this: #1758

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@geoffromer: Writing a propsal here: #1871 (WIP).


A [`let`](#constant-let-declarations) or [`var`](#variable-var-declarations)
declaration may be used with a [refutable pattern](#refutable-patterns) if an
`else` clause is supplied, as in:

```carbon
let (x: i32, true) = F(1) else {
// Can't use `x` here.
return false;
}
// `x` is an r-value

var (y: i32, true) = F(x) else {
return false;
}
// `y` is an l-value
y += 2;
```

If the pattern successfully matches the runtime value, values are bound
according to the pattern, and execution skips over the `else` code block and
proceeds to the next statement.

If the pattern does not match, the `else` code block will be executed. None of
the bindings from the pattern will be in scope in the `else` code block. No
control flow path in the `else` code block may continue to the statement after.
All paths must end with a `break`, `continue`, `return`, or call to a function
that never returns.

## User-defined types

> **TODO:** Maybe rename to "nominal types"?
Expand Down Expand Up @@ -1718,7 +1752,8 @@ fn ParseAsInt(s: String) -> IntResult {
}
```

Choice type values may be consumed using a [`match` statement](#match):
Choice type values may be consumed using a [`match` statement](#match) or
[`else` at the end of a `var` or `let` declaration](#letelse-and-varelse):

```carbon
match (ParseAsInt(s)) {
Expand All @@ -1732,6 +1767,16 @@ match (ParseAsInt(s)) {
Terminate();
}
}

let .Success(r_value: i32) = ParseAsInt(s) else {
return false;
}
// `r_value` is an r-value

var .Success(l_value: i32) = ParseAsInt(s) else {
return false;
}
// `l_value` is an l-value
```

They can also represent an
Expand Down