소스 검색

Add statement syntax for function declarations (#438)

Add statement syntax (either `fn` or `func`, see proposal) for function declarations.

- Follows C++-style trailing return syntax.

Co-authored-by: Geoff Romer <gromer@google.com>
Co-authored-by: josh11b <josh11b@users.noreply.github.com>
Jon Meow 5 년 전
부모
커밋
59add8c8de
2개의 변경된 파일472개의 추가작업 그리고 0개의 파일을 삭제
  1. 1 0
      proposals/README.md
  2. 471 0
      proposals/p0438.md

+ 1 - 0
proposals/README.md

@@ -51,6 +51,7 @@ request:
 -   [0353 - `for` loops](p0353.md)
 -   [0353 - `for` loops](p0353.md)
 -   [0415 - Syntax: `return`](p0415.md)
 -   [0415 - Syntax: `return`](p0415.md)
 -   [0426 - Governance & evolution revamp](p0426.md)
 -   [0426 - Governance & evolution revamp](p0426.md)
+-   [0438 - Functions](p0438.md)
 -   [0444 - GitHub Discussions](p0444.md)
 -   [0444 - GitHub Discussions](p0444.md)
 -   [0447 - Generics terminology](p0447.md)
 -   [0447 - Generics terminology](p0447.md)
 
 

+ 471 - 0
proposals/p0438.md

@@ -0,0 +1,471 @@
+# Functions
+
+<!--
+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/438)
+
+<!-- toc -->
+
+## Table of contents
+
+-   [Problem](#problem)
+-   [Background](#background)
+    -   [C++ syntax](#c-syntax)
+    -   [Other languages](#other-languages)
+    -   [Forward declarations](#forward-declarations)
+-   [Proposal](#proposal)
+    -   [Functions](#functions)
+    -   [Forward declarations](#forward-declarations-1)
+-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)
+-   [Open questions](#open-questions)
+    -   [Calling functions defined later in the same file](#calling-functions-defined-later-in-the-same-file)
+    -   [Optional argument names](#optional-argument-names)
+-   [Alternatives considered](#alternatives-considered)
+    -   [Function keyword](#function-keyword)
+        -   [Type](#type)
+        -   [`-` (dash)](#--dash)
+        -   [`def`](#def)
+        -   [`fn`](#fn)
+        -   [`fun`](#fun)
+        -   [`func`](#func)
+        -   [`function`](#function)
+    -   [Conclusion](#conclusion)
+
+<!-- tocstop -->
+
+## Problem
+
+We currently have
+[placeholder guidance on functions](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/functions.md).
+The intent of this proposal is to establish agreement on the basics, providing a
+baseline for future evolution.
+
+## Background
+
+### C++ syntax
+
+C++ syntax for function declarations comes in two forms:
+
+```cpp
+std::int64_t Sum(std::int64_t a, std::int64_t b) {
+  return a + b;
+}
+
+// Or with trailing return type syntax:
+auto Sum(std::int64_t a, std::int64_t b) -> std::int64_t {
+  return a + b;
+}
+```
+
+Bodies are always wrapped by braces.
+
+### Other languages
+
+To summarize keyword use from other languages:
+
+-   Type: C# and Java
+-   `-`: Objective-C
+-   `def`: Python and Ruby
+-   `fn`: Rust
+-   `fun`: Kotlin
+-   `func`: Go and Swift
+-   `function`: JavaScript, MatLab, PHP, R, and TypeScript
+
+For exhaustive function examples:
+
+-   C#
+
+    ```csharp
+    int Sum(int a, int b) {
+      return a + b;
+    }
+    ```
+
+-   Go
+
+    ```go
+    func add(a int, b int) int {
+      return a + b
+    }
+    ```
+
+-   Java
+
+    ```java
+    Int Sum(Int a, Int b) {
+      return a + b;
+    }
+    ```
+
+-   JavaScript
+
+    ```javascript
+    function Sum(a, b) {
+        return a + b;
+    }
+    ```
+
+-   Kotlin
+
+    ```kotlin
+    fun add(a: Int, b: Int): Int {
+      return a + b
+    }
+    ```
+
+-   Matlab
+
+    ```matlab
+    function s = sum(a,b)
+      s = a+b;
+    end
+    ```
+
+-   Objective-C
+
+    ```objc
+    - (int)sum:(int)a
+               (int)b {
+      return a + b;
+    }
+    ```
+
+-   PHP
+
+    ```php
+    function sum(int $a, int $b) {
+      return $a + $b;
+    }
+    ```
+
+-   Python
+
+    ```python
+    def sum(a, b):
+      return a + b
+
+    def sum(a: int, b: int) -> int:
+      return a + b
+    ```
+
+-   R
+
+    ```r
+    sum <- function(a, b) {
+      a + b
+    }
+    ```
+
+-   Ruby
+
+    ```ruby
+    def sum(a, b)
+      return a + b
+    end
+    ```
+
+-   Rust
+
+    ```rust
+    fn sum(a: i64, b: i64) -> i64 {
+      a + b
+    }
+    ```
+
+-   Swift
+
+    ```swift
+    func sum(a: Int, b: Int) -> Int {
+      return a + b
+    }
+    ```
+
+-   TypeScript
+
+    ```typescript
+    function sum(a: number, b: number): number {
+        return a + b;
+    }
+    ```
+
+### Forward declarations
+
+[Forward declarations](https://en.wikipedia.org/wiki/Forward_declaration) of
+functions are largely unique to C++. Objective-C also has this. However, most
+other languages being discussed do not.
+
+## Proposal
+
+### Functions
+
+Function declarations and definitions should look like:
+
+`fn` _function name_ `(` _type identifier \[_ `,` _type identifier ]..._ `)` _[_
+`->` _return type_ _] [_ `{` _body_ `}` _|_ `;` _]_
+
+Arguments should be comma-separated and imitate
+[`var` syntax](https://github.com/carbon-language/carbon-lang/pull/339),
+although `var` itself is not used.
+
+For example:
+
+```carbon
+fn Sum(Int a, Int b) -> Int {
+  <body>
+}
+
+fn UnusedArgument(Int _) -> Int {
+  <body>
+}
+```
+
+The return type may optionally be omitted if `()`. For example, these two
+function declarations both return `()`:
+
+```carbon
+fn Print(String s) -> ();
+fn Print(String s);
+```
+
+### Forward declarations
+
+Forward declarations will be supported in order to support separation of API and
+implementation, as explained in
+[code and name organization](https://github.com/carbon-language/carbon-lang/tree/trunk/docs/design/code_and_name_organization).
+For example:
+
+```carbon
+package Math api;
+
+fn Sum(Int a, Int b) -> Int;
+```
+
+Forward declarations will experimentally _only_ be allowed in `api` files, and
+_only_ when the definition is in the library's `impl` file. The intent is to
+minimize use, consistent with most other languages that have no forward
+declaration support at all.
+
+## Rationale based on Carbon's goals
+
+Carbon needs functions in order to be writable by developers. That functionality
+needs a syntax.
+
+Relevant goals are:
+
+-   [3. Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write):
+
+    -   Adding a keyword makes it easy for developers to visually identify
+        functions.
+    -   Trailing return syntax should be easier to understand than C++'s older
+        preceding return syntax. Only allowing one avoids requiring developers
+        to recognize and choose between equivalent syntaxes.
+
+-   [5. Fast and scalable development](/docs/project/goals.md#fast-and-scalable-development):
+    The addition of a keyword should make parsing easy.
+
+-   [7. Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code):
+    Keeping syntax close to C++ will make it easier for developers to
+    transition.
+
+## Open questions
+
+### Calling functions defined later in the same file
+
+C++ supports forward declaring functions in a `.cpp` file, and this may be
+useful for handling interdependencies between functions. In Carbon, we should
+instead aim to allow having a function able to call a function defined later in
+the same file without requiring a forward declaration.
+
+Advantages:
+
+-   Minimize accidents with forward declarations not matching implementation.
+-   Fewer forward declarations for developers to find while reading.
+
+Disadvantages:
+
+-   Shifts burden onto how code is parsed and executed.
+
+We'll need to evaluate how this works. There is tracked by
+[#472](https://github.com/carbon-language/carbon-lang/issues/472). This does not
+need to block this proposal, as we can allow it later if that's the decision; it
+may also be helpful to give more time to consider how name lookup should work.
+
+### Optional argument names
+
+Argument names are required under this proposal. It's likely that developers
+will want a way to indicate unused arguments. This is tracked by
+[#476](https://github.com/carbon-language/carbon-lang/issues/476).
+
+## Alternatives considered
+
+### Function keyword
+
+We may have anchored on `fn` without much consideration. A key piece of this
+proposal is to suggest reconsidering the choice, even if we end up with the
+same.
+
+#### Type
+
+Advantages:
+
+-   Echoes C++, C#, and Java.
+-   Simpler to write; a type will often be present for the return regardless.
+
+Disadvantages:
+
+-   Makes function syntax more difficult to parse.
+    -   In C++, it's notable that functions with a trailing return still start
+        with `auto` to indicate a "type".
+
+There's a consensus that _some_ keyword should be used in order to simplify
+parsing, so this option is not expected to receive much support.
+
+#### `-` (dash)
+
+Advantages:
+
+-   Echoes Objective-C instance method syntax.
+    -   Class methods use `+` and we could echo that too.
+-   This is the most succinct option.
+
+Disadvantages:
+
+-   Easy to miss, and hard to read as a result.
+-   Might be ambiguous with the `-` operator.
+
+Although this alternative is mentioned, it is not expected to receive much
+support due to its readability problem.
+
+#### `def`
+
+Advantages:
+
+-   Echoes Python and Ruby.
+
+Disadvantages:
+
+-   `def` is presumably short for "define", which may not be as obvious as a
+    "function" derivative.
+
+#### `fn`
+
+Advantages:
+
+-   Echoes Rust.
+-   The shortest "function" derivative.
+    -   Likely comes from the [fn key](https://en.wikipedia.org/wiki/Fn_key).
+
+Disadvantages:
+
+-   Abbreviation by removing letters in the middle of a word is
+    [disallowed by Carbon's C++ style](https://google.github.io/styleguide/cppguide.html#General_Naming_Rules).
+    -   Even though the abbreviation is in Wikipedia, it is not associated with
+        [functions in programming](https://en.wikipedia.org/wiki/Subroutine).
+    -   Would likely be the only keyword abbreviated this way.
+
+#### `fun`
+
+Advantages:
+
+-   Echoes Kotlin.
+-   Could be used with `var` as a push towards three letter abbreviations.
+    -   Not clear there are other examples of three letter abbreviations.
+    -   `let` may be used in a similar way, although it's not an abbreviation.
+
+Disadvantages:
+
+-   "fun" is a common English word and may be a mildly confusing choice as a
+    result.
+-   When wrapping function definitions, the function name and wrapped types
+    would end up on the same column when indenting by 4 spaces. These use the
+    same casing, so it may make it slower to understand code.
+
+    -   For example:
+
+        ```carbon
+        fun Print(
+            String message) {
+          ...
+        }
+        // Similar confusion if the body of the function is indented 4 spaces.
+        fun Print(String message) {
+            SomeFunctionCall();
+            ...
+        }
+        ```
+
+    -   This is also true for `var`, but wrapping arguments is expected to be
+        more common for functions, and the casing more likely to match.
+
+#### `func`
+
+Advantages:
+
+-   Echoes Go and Swift.
+
+Disadvantages:
+
+-   The longest abbreviated form of "function".
+
+#### `function`
+
+Advantages:
+
+-   Echoes JavaScript, MatLab, PHP, R, and TypeScript.
+-   Clear meaning without any abbreviation.
+
+Disadvantages:
+
+-   The longest "function" derivative.
+
+### Conclusion
+
+`fn` and `func` are the favored options:
+
+-   Desire to abbreviate "function":
+    -   `fn` is clearly shorter than `func`. Both are shorter than "function".
+-   Consistency with other abbreviations:
+    -   We are using abbreviations like `var`, and something like `mut` or
+        `const` seems likely. `ptr` is possible.
+        -   `func` is consistent with abbreviation by removing letters at the
+            end.
+        -   `fn` is more consistent with abbreviations like `ptr` that remove
+            letters in the middle, but a three letter abbreviation like `fcn`
+            would be more consistent.
+    -   We are using
+        [Google C++ style](https://google.github.io/styleguide/cppguide.html#General_Naming_Rules)
+        as a base, which explicitly discourages abbreviating by deleting letters
+        within a word.
+        -   `fn` deletes letters in the middle of "function", `func` does not.
+-   Familiarity for developers:
+    -   `func` is used by Go and Swift, both of which are common languages.
+        -   [`func`](https://www.google.com/search?q=func) is very searchable.
+    -   `fn` is only used by Rust, which by most measures has less adoption than
+        either Go or Swift at present. However, it is used in
+        [Hungarian notation](https://docs.microsoft.com/en-us/windows/win32/stg/coding-style-conventions),
+        so some C++ developers will be familiar with `fn` for function pointers.
+        -   It's also used for the
+            [Fn key](https://en.wikipedia.org/wiki/Fn_key), although assumptions
+            about the meaning of "Fn" as abbreviation for "function" versus
+            "F-number key" (as in F5) may mislead some developers.
+        -   [`fn`](https://www.google.com/search?q=fn) is difficult to search
+            for.
+-   Pronunciation:
+    -   Both may be pronounced as "function", but may also be pronounced by
+        their abbreviation.
+    -   `func` could be as "funk", defined as a music genre or state of
+        depression.
+    -   `fn` could be as:
+        -   "eff en", which has no direct meaning but could be misheard as
+            "effing", or profanity. However, it's not clear that this potential
+            mishearing is a pragmatic issue.
+        -   "fun", defined as enjoyment.
+
+Note that both are argued here as reasonable solutions that would satisfy many.
+This was asked on
+[#463](https://github.com/carbon-language/carbon-lang/issues/463). We are using
+`fn`.