Jon Meow 5 лет назад
Родитель
Сommit
6df0d51516
2 измененных файлов с 242 добавлено и 0 удалено
  1. 1 0
      proposals/README.md
  2. 241 0
      proposals/p0285.md

+ 1 - 0
proposals/README.md

@@ -65,5 +65,6 @@ request:
     -   [0199 - Decision](p0199_decision.md)
 -   [0253 - 2021 Roadmap](p0253.md)
     -   [0253 - Decision](p0253_decision.md)
+-   [0285 - if/else](p0285.md)
 
 <!-- endproposals -->

+ 241 - 0
proposals/p0285.md

@@ -0,0 +1,241 @@
+# if/else
+
+<!--
+Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+Exceptions. See /LICENSE for license information.
+SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+-->
+
+[Pull request](https://github.com/carbon-language/carbon-lang/pull/285)
+
+<!-- toc -->
+
+## Table of contents
+
+-   [Problem](#problem)
+-   [Background](#background)
+-   [Proposal](#proposal)
+-   [Details](#details)
+    -   [Executable semantics form](#executable-semantics-form)
+-   [Caveats](#caveats)
+    -   [C++ as baseline](#c-as-baseline)
+    -   [if/else in expressions](#ifelse-in-expressions)
+    -   [Indentation](#indentation)
+    -   [Ambiguous else](#ambiguous-else)
+-   [Alternatives considered](#alternatives-considered)
+    -   [No parentheses](#no-parentheses)
+    -   [Require braces](#require-braces)
+
+<!-- tocstop -->
+
+## Problem
+
+`if`/`else` is noted in the [language overview](/docs/design/README.md#ifelse),
+but is provisional. Control flow is important, and `if`/`else` is basic; the
+form is similar in many languages, even if details may change.
+
+## Background
+
+`if`/`else` is a common
+[conditional](<https://en.wikipedia.org/wiki/Conditional_(computer_programming)>),
+seen in
+[many languages](<https://en.wikipedia.org/wiki/Conditional_(computer_programming)#Choice_system_cross_reference>).
+A few syntaxes that are likely to influence `if`/`else` are:
+
+-   C++
+
+    ```cc
+    if (x) {
+      printf("x is true");
+    } else if (y) {
+      printf("y is true");
+    } else {
+      printf("Neither was true");
+    }
+    ```
+
+-   Python
+
+    ```python
+    if x:
+      print("x is true");
+    elif y:
+      print("y is true");
+    else:
+      print("Neither was true");
+    ```
+
+-   Swift
+
+    ```swift
+    if x {
+      print("x is true")
+    } else if y {
+      print("y is true")
+    } else {
+      print("Neither was true")
+    }
+    ```
+
+-   Rust -- versus other cases where `if` is a statement, Rust makes `if` an
+    expression, allowing:
+
+    ```rust
+    let x = if y {
+        1
+    } else {
+        0
+    };
+    ```
+
+## Proposal
+
+We should make `if`/`else` syntax consistent with C/C++, rather than adopting
+the syntax of another language.
+
+## Details
+
+`if`/`else` is a statement. The syntax looks like:
+
+`if` `(`_boolean expression_`)` `{` _statements evaluated when true_ `}` [
+`else` `{` _statements evaluated when false_ `}` ]
+
+The braces are optional, but must be paired (`{ ... }`) if present. When there
+are no braces, only one statement is allowed.
+
+### Executable semantics form
+
+```bison
+statement:
+  "if" '(' expression ')' statement optional_else
+| /* pre-existing statements elided */
+;
+
+optional_else:
+  /* empty */
+| "else" statement
+;
+```
+
+## Caveats
+
+### C++ as baseline
+
+This baseline syntax is based on C++, following the migration sub-goal
+[Familiarity for experienced C++ developers with a gentle learning curve](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code).
+To the extent that this proposal anchors on a particular approach, it aims to
+anchor on C++'s existing syntax, consistent with that sub-goal.
+
+Alternatives will generally reflect breaking consistency with C++ syntax. While
+most proposals may consider alternatives more, this proposal suggests a
+threshold of only accepting alternatives that skew from C++ syntax if they are
+clearly better; the priority in this proposal is to _avoid debate_ and produce a
+trivial proposal. Where an alternative would trigger debate, it should be
+examined by an advocate in a separate proposal.
+
+### if/else in expressions
+
+This proposal covers `if`/`else` as a statement. A Rust-like form of `if`/`else`
+as an expression could be supported, but is not part of this proposal because
+it's more complex.
+
+### Indentation
+
+It may be desirable to require meaningful indentation of the body of an
+`if`/`else`, in particular to help catch errors when there are no braces.
+
+For example, this could be a compiler error due to inconsistent indentation of
+the `do_parse` assignment:
+
+```carbon
+if (missing_data)
+  Print("Missing data!");
+  do_parse = false;
+if (do_parse)
+  ParseData();
+```
+
+This is _not_ part of this proposal.
+
+### Ambiguous else
+
+It may be desirable to reject cases where an `else` is ambiguous. For example,
+this could be a compiler error due to the ambiguous `else`:
+
+```carbon
+if (a) if (b) f(); else g();
+```
+
+This is _not_ part of this proposal. This proposal takes C++ syntax as a
+baseline, so an `else` binds to the innermost enclosing `if` that doesn't
+already have an `else`.
+
+This desire might also be addressed by choosing to require consistent
+indentation and disallowing multiple `if`s on the same line.
+
+## Alternatives considered
+
+See [C++ as baseline](#c-as-baseline) for an explanation of how alternatives are
+evaluated in this proposal.
+
+### No parentheses
+
+Parentheses could be optional (essentially not part of `if`/`else`, but addable
+as part of the expression), instead of required (as proposed).
+
+Advantages:
+
+-   Removing parentheses gives developers less to type.
+    -   Consistent with several other languages, including Swift and Rust.
+
+Disadvantages:
+
+-   Requiring parentheses is consistent with C++, and will be intuitive for C++
+    developers, from both a writability and readability perspective.
+-   Parentheses help avoid ambiguities.
+    -   The Swift and Rust model is ambiguous if it's ever possible for an
+        expression to optionally be followed by braces. That is possible in
+        Rust, at least, where `Type{...}` is a valid expression. As a result,
+        Rust rejects `if Type{.value = true}.value { thing1 } else { thing2 }`
+        because it misinterprets the braces.
+-   Parentheses allow making the braces optional without any risk of ambiguity.
+-   Parentheses allow introducing syntactic variants in the future without
+    ambiguity.
+    -   For example, C++'s `if constexpr (...)` wouldn't have been possible if
+        the parentheses were optional.
+
+The benefits of this are debatable, and it should be examined by an advocate in
+a focused proposal. For now, we should match C++'s decision.
+
+### Require braces
+
+Braces could be required, instead of optional (as proposed).
+
+Advantages:
+
+-   Braces avoid syntax ambiguities.
+    -   For example, `if (x) if (y) { ... } else { ... }` has
+        difficult-to-understand binding of `else`.
+-   Braces avoid errors when adding statements.
+
+    -   For example, if:
+
+        ```carbon
+        if (x)
+          do_parse = false;
+        ```
+
+        has a statement added:
+
+        ```carbon
+        if (missing_data)
+          Print("Missing data!");
+          do_parse = false;
+        ```
+
+Disadvantages:
+
+-   Inconsistent with C++.
+
+The benefits of this are debatable, and it should be examined by an advocate in
+a focused proposal. For now, we should match C++'s decision.