- Overview
- Function definitions
- Function declarations
- Function calls
- Functions in other features
- Alternatives considered
- References
Functions are the core building block for applications. Carbon's basic function syntax is:
- parameter: identifier
:
expression - parameter-list: [ parameter
,
parameter,
... ] - return-clause: [
->
< expression |auto
> ] - signature:
fn
identifier(
parameter-list)
return-clause - function-definition: signature
{
statements}
- function-declaration: signature
;
- function-call: identifier
(
[ expression,
expression,
... ])
A function with only a signature and no body is a function declaration, or forward declaration. When the body is a present, it's a function definition. The body introduces nested scopes which may contain local variable declarations.
A basic function definition may look like:
fn Add(a: i64, b: i64) -> i64 {
return a + b;
}
This declares a function called Add
which accepts two i64
parameters, the
first called a
and the second called b
, and returns an i64
result. It
returns the result of adding the two arguments.
C++ might declare the same thing:
std::int64_t Add(std::int64_t a, std::int64_t b) {
return a + b;
}
// Or with trailing return type syntax:
auto Add(std::int64_t a, std::int64_t b) -> std::int64_t {
return a + b;
}
The return clause of a function specifies the return type using one of three possible syntaxes:
->
followed by an expression, such asi64
, directly states the return type. This expression will be evaluated at compile-time, so must be valid in that context.- For example,
fn ToString(val: i64) -> String;
has a return type ofString
.
- For example,
->
followed by theauto
keyword indicates that type inference should be used to determine the return type.- For example,
fn Echo(val: i64) -> auto { return val; }
will have a return type ofi64
through type inference. - Declarations must have a known return type, so
auto
is not valid. - The function must have precisely one
return
statement. Thatreturn
statement's expression will then be used for type inference.
- For example,
- Omission indicates that the return type is the empty tuple,
()
.- For example,
fn Sleep(seconds: i64);
is similar tofn Sleep(seconds: i64) -> ();
. ()
is similar to avoid
return type in C++.
- For example,
The return
statement is essential to function
control flow. It ends the flow of the function and returns execution to the
caller.
When the return clause is omitted, the return
statement has
no expression argument, and function control flow implicitly ends after the last
statement in the function's body as if return;
were present.
When the return clause is provided, including when it is -> ()
, the return
statement must have an expression that is convertible to the return type, and a
return
statement must be used to end control flow of the function.
Functions may be declared separate from the definition by providing only a signature, with no body. This provides an API which may be called. For example:
// Declaration:
fn Add(a: i64, b: i64) -> i64;
// Definition:
fn Add(a: i64, b: i64) -> i64 {
return a + b;
}
The corresponding definition may be provided later in the same file or, when the
declaration is in an
api
file of a library, in the impl
file of the same library. The signature of a function declaration must match the
corresponding definition. This includes the return clause;
even though an omitted return type has equivalent behavior to -> ()
, the
presence or omission must match.
Function calls use a function's identifier to pass multiple expression arguments corresponding to the function signature's parameters. For example:
fn Add(a: i64, b: i64) -> i64 {
return a + b;
}
fn Run() {
Add(1, 2);
}
Here, Add(1, 2)
is a function call expression. Add
refers to the function
definition's identifier. The parenthesized arguments 1
and 2
are passed to
the a
and b
parameters of Add
.
Other designs build upon basic function syntax to add advanced features:
- Generic functions adds support for deduced parameters and generic type parameters.
- Class member functions adds support for methods and class functions.