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