mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 10:41:03 +01:00
Updating function and variable docs (#1017)
I was doing this for #851 initially, but I think #438 and #826 hadn't made it in (possibly intentionally due to #851? I don't recall). Co-authored-by: Chandler Carruth <chandlerc@gmail.com> Co-authored-by: Richard Smith <richard@metafoo.co.uk>
This commit is contained in:
committed by
GitHub
co-authored by
Chandler Carruth
Richard Smith
parent
6c3e1f6d7c
commit
a2728f82bb
+8
-10
@@ -301,23 +301,21 @@ Some common expressions in Carbon include:
|
||||
### Functions
|
||||
|
||||
> References: [Functions](functions.md)
|
||||
>
|
||||
> **TODO:** References need to be evolved.
|
||||
|
||||
Functions are the core unit of behavior. For example:
|
||||
|
||||
```carbon
|
||||
fn Sum(a: Int, b: Int) -> Int;
|
||||
fn Add(a: i64, b: i64) -> i64;
|
||||
```
|
||||
|
||||
Breaking this apart:
|
||||
|
||||
- `fn` is the keyword used to indicate a function.
|
||||
- Its name is `Sum`.
|
||||
- It accepts two `Int` parameters, `a` and `b`.
|
||||
- It returns an `Int` result.
|
||||
- Its name is `Add`.
|
||||
- It accepts two `i64` parameters, `a` and `b`.
|
||||
- It returns an `i64` result.
|
||||
|
||||
You would call this function like `Sum(1, 2)`.
|
||||
You would call this function like `Add(1, 2)`.
|
||||
|
||||
### Blocks and statements
|
||||
|
||||
@@ -354,8 +352,8 @@ work similarly to function parameters.
|
||||
For example:
|
||||
|
||||
```carbon
|
||||
fn Foo() {
|
||||
var x: Int = 42;
|
||||
fn DoSomething() {
|
||||
var x: i64 = 42;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -363,7 +361,7 @@ Breaking this apart:
|
||||
|
||||
- `var` is the keyword used to indicate a variable.
|
||||
- Its name is `x`.
|
||||
- Its type is `Int`.
|
||||
- Its type is `i64`.
|
||||
- It is initialized with the value `42`.
|
||||
|
||||
### Lifetime and move semantics
|
||||
|
||||
+143
-36
@@ -10,54 +10,161 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
## Table of contents
|
||||
|
||||
- [TODO](#todo)
|
||||
- [Basic functions](#basic-functions)
|
||||
- [Overview](#overview)
|
||||
- [Function definitions](#function-definitions)
|
||||
- [Return clause](#return-clause)
|
||||
- [`return` statements](#return-statements)
|
||||
- [Function declarations](#function-declarations)
|
||||
- [Function calls](#function-calls)
|
||||
- [Functions in other features](#functions-in-other-features)
|
||||
- [Alternatives considered](#alternatives-considered)
|
||||
- [References](#references)
|
||||
|
||||
<!-- tocstop -->
|
||||
|
||||
## TODO
|
||||
## Overview
|
||||
|
||||
This is a skeletal design, added to support [the overview](README.md). It should
|
||||
not be treated as accepted by the core team; rather, it is a placeholder until
|
||||
we have more time to examine this detail. Please feel welcome to rewrite and
|
||||
update as appropriate.
|
||||
Functions are the core building block for applications. Carbon's basic function
|
||||
syntax is:
|
||||
|
||||
## Basic functions
|
||||
- _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_ `,` _...
|
||||
]_ `)`
|
||||
|
||||
Programs written in Carbon, much like those written in other languages, are
|
||||
primarily divided up into "functions" (or "procedures", "subroutines", or
|
||||
"subprograms"). These are the core unit of behavior for the programming
|
||||
language. Let's look at a simple example to understand how these work:
|
||||
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.
|
||||
|
||||
```
|
||||
fn Sum(a: Int, b: Int) -> Int;
|
||||
## Function definitions
|
||||
|
||||
A basic function definition may look like:
|
||||
|
||||
```carbon
|
||||
fn Add(a: i64, b: i64) -> i64 {
|
||||
return a + b;
|
||||
}
|
||||
```
|
||||
|
||||
This declares a function called `Sum` which accepts two `Int` parameters, the
|
||||
first called `a` and the second called `b`, and returns an `Int` result. C++
|
||||
might declare the same thing:
|
||||
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.
|
||||
|
||||
```
|
||||
std::int64_t Sum(std::int64_t a, std::int64_t b);
|
||||
C++ might declare the same thing:
|
||||
|
||||
```cpp
|
||||
std::int64_t Add(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;
|
||||
auto Add(std::int64_t a, std::int64_t b) -> std::int64_t {
|
||||
return a + b;
|
||||
}
|
||||
```
|
||||
|
||||
Let's look at how some specific parts of this work. The function declaration is
|
||||
introduced with a keyword `fn` followed by the name of the function `Sum`. This
|
||||
declares that name in the surrounding scope and opens up a new scope for this
|
||||
function. We declare the first parameter as `Int a`. The `Int` part is an
|
||||
expression (here referring to a constant) that computes the type of the
|
||||
parameter. The `:` marks the end of the type expression and introduces the
|
||||
identifier for the parameter, `a`. The parameter names are introduced into the
|
||||
function's scope and can be referenced immediately after they are introduced.
|
||||
The return type is indicated with `-> Int`, where again `Int` is just an
|
||||
expression computing the desired type. The return type can be completely omitted
|
||||
in the case of functions which do not return a value.
|
||||
### Return clause
|
||||
|
||||
Calling functions involves a new form of expression: `Sum(1, 2)` for example.
|
||||
The first part, `Sum`, is an expression referring to the name of the function.
|
||||
The second part, `(1, 2)` is a parenthesized list of arguments to the function.
|
||||
The juxtaposition of one expression with parentheses forms the core of a call
|
||||
expression, similar to a postfix operator.
|
||||
The return clause of a function specifies the return type using one of three
|
||||
possible syntaxes:
|
||||
|
||||
- `->` followed by an _expression_, such as `i64`, 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 of
|
||||
`String`.
|
||||
- `->` followed by the `auto` keyword indicates that
|
||||
[type inference](type_inference.md) should be used to determine the return
|
||||
type.
|
||||
- For example, `fn Echo(val: i64) -> auto { return val; }` will have a
|
||||
return type of `i64` through type inference.
|
||||
- Declarations must have a known return type, so `auto` is not valid.
|
||||
- The function must have precisely one `return` statement. That `return`
|
||||
statement's expression will then be used for type inference.
|
||||
- Omission indicates that the return type is the empty tuple, `()`.
|
||||
- For example, `fn Sleep(seconds: i64);` is similar to
|
||||
`fn Sleep(seconds: i64) -> ();`.
|
||||
- `()` is similar to a `void` return type in C++.
|
||||
|
||||
### `return` statements
|
||||
|
||||
The [`return` statement](control_flow/return.md) is essential to function
|
||||
control flow. It ends the flow of the function and returns execution to the
|
||||
caller.
|
||||
|
||||
When the [return clause](#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.
|
||||
|
||||
## Function declarations
|
||||
|
||||
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:
|
||||
|
||||
```carbon
|
||||
// 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](code_and_name_organization/#libraries), in the `impl`
|
||||
file of the same library. The signature of a function declaration must match the
|
||||
corresponding definition. This includes the [return clause](#return-clause);
|
||||
even though an omitted return type has equivalent behavior to `-> ()`, the
|
||||
presence or omission must match.
|
||||
|
||||
## Function calls
|
||||
|
||||
Function calls use a function's identifier to pass multiple expression arguments
|
||||
corresponding to the function signature's parameters. For example:
|
||||
|
||||
```carbon
|
||||
fn Add(a: i64, b: i64) -> i64 {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
fn Main() {
|
||||
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`.
|
||||
|
||||
## Functions in other features
|
||||
|
||||
Other designs build upon basic function syntax to add advanced features:
|
||||
|
||||
- [Generic functions](generics/overview.md#generic-functions) adds support for
|
||||
deduced parameters and generic type parameters.
|
||||
- [Class member functions](classes.md#member-functions) adds support for
|
||||
methods and class functions.
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
- [Function keyword](/proposals/p0438.md#function-keyword)
|
||||
- [Only allow `auto` return types if parameters are generic](/proposals/p0826.md#only-allow-auto-return-types-if-parameters-are-generic)
|
||||
- [Provide alternate function syntax for concise return type inference](/proposals/p0826.md#provide-alternate-function-syntax-for-concise-return-type-inference)
|
||||
- [Allow separate declaration and definition](/proposals/p0826.md#allow-separate-declaration-and-definition)
|
||||
|
||||
## References
|
||||
|
||||
- Proposal
|
||||
[#438: Add statement syntax for function declarations](https://github.com/carbon-language/carbon-lang/pull/438)
|
||||
- Proposal
|
||||
[#826: Function return type inference](https://github.com/carbon-language/carbon-lang/pull/826)
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
# Type inference
|
||||
|
||||
<!--
|
||||
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
|
||||
-->
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
## Table of contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Open questions](#open-questions)
|
||||
- [Inferring a variable type from literals](#inferring-a-variable-type-from-literals)
|
||||
- [Alternatives considered](#alternatives-considered)
|
||||
- [References](#references)
|
||||
|
||||
<!-- tocstop -->
|
||||
|
||||
## Overview
|
||||
|
||||
[Type inference](https://en.wikipedia.org/wiki/Type_inference) occurs in Carbon
|
||||
when the `auto` keyword is used. This may occur in
|
||||
[variable declarations](variables.md) or [function declarations](functions.md).
|
||||
|
||||
At present, type inference is very simple: given the expression which generates
|
||||
the value to be used for type inference, the inferred type is the precise type
|
||||
of that expression. For example, the inferred type for `auto` in
|
||||
`fn Foo(x: i64) -> auto { return x; }` is `i64`.
|
||||
|
||||
Type inference is currently supported for [function return types](functions.md)
|
||||
and [declared variable types](variables.md).
|
||||
|
||||
## Open questions
|
||||
|
||||
### Inferring a variable type from literals
|
||||
|
||||
Using the type on the right side for `var y: auto = 1` currently results in a
|
||||
constant `IntLiteral(1)` value, whereas most languages would suggest a variable
|
||||
integer type, such as `i64`. Carbon might also make it an error. Although type
|
||||
inference currently only addresses `auto` for variables and function return
|
||||
types, this is something that will be considered as part of type inference in
|
||||
general, because it also affects generics, templates, lambdas, and return types.
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
- [Use `_` instead of `auto`](/proposals/p0851.md#use-_-instead-of-auto)
|
||||
|
||||
## References
|
||||
|
||||
- Proposal
|
||||
[#851: auto keyword for vars](https://github.com/carbon-language/carbon-lang/pull/851)
|
||||
@@ -22,7 +22,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
Carbon's local variable syntax is:
|
||||
|
||||
> `var` _identifier_`:` _type_ _[_ `=` _value_ _]_`;`
|
||||
- `var` _identifier_`:` _< expression |_ `auto` _> [_ `=` _value ]_`;`
|
||||
|
||||
Blocks introduce nested scopes and can contain local variable declarations that
|
||||
work similarly to function parameters.
|
||||
@@ -31,7 +31,7 @@ For example:
|
||||
|
||||
```
|
||||
fn Foo() {
|
||||
var x: Int = 42;
|
||||
var x: i32 = 42;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -40,6 +40,9 @@ type `Int` and is initialized with the value `42`. These variable declarations
|
||||
(and function declarations) have a lot more power than what we're covering just
|
||||
yet, but this gives you the basic idea.
|
||||
|
||||
If `auto` is used in place of the type, [type inference](type_inference.md) is
|
||||
used to automatically determine the variable's type.
|
||||
|
||||
While there can be global constants, there are no global variables.
|
||||
|
||||
## Notes
|
||||
@@ -61,6 +64,7 @@ discover that their convenience outweighs any improvements afforded.
|
||||
- [Colon between type and identifier](/proposals/p0339.md#colon-between-type-and-identifier)
|
||||
- [Type elision](/proposals/p0339.md#type-elision)
|
||||
- [Type ordering](/proposals/p0618.md#type-ordering)
|
||||
- [Elide the type instead of using `auto`](/proposals/p0851.md#elide-the-type-instead-of-using-auto)
|
||||
|
||||
## References
|
||||
|
||||
@@ -68,3 +72,5 @@ discover that their convenience outweighs any improvements afforded.
|
||||
[#339: `var` statement](https://github.com/carbon-language/carbon-lang/pull/339)
|
||||
- Proposal
|
||||
[#618: `var` ordering](https://github.com/carbon-language/carbon-lang/pull/618)
|
||||
- Proposal
|
||||
[#851: auto keyword for vars](https://github.com/carbon-language/carbon-lang/pull/851)
|
||||
|
||||
Reference in New Issue
Block a user