|
@@ -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`.
|