mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-04 22:02:52 +01:00
472 lines
12 KiB
Markdown
472 lines
12 KiB
Markdown
# 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-1)
|
|
- [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](/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`.
|