We've talked about adding the title to the filename several times over the years and it seems really valuable. This requires us to compute a "slug" for the title spelling that can be part of the filename. Beyond that, we crossed 7000 recently, and so it seems likely that we will need to add digits sooner rather than later here, so this goes ahead and moves us to 6 digits so we don't have to adjust again for a reasonable length of time. To implement this and ensure we can sustain it going forward this adds a tool to our pre-commit that validates (and corrects if needed) the filename. In order to update everything and keep links working, there are a _lot_ of changes, but the most interesting for direct review are in `proposals/scripts`. Assisted-by: Antigravity with Gemini --------- Co-authored-by: Richard Smith <richard@metafoo.co.uk>
5.0 KiB
Syntax: return
Table of contents
Problem
Carbon has functions. We should write down how those functions indicate their code should stop running and, if applicable, what result should be provided back to their caller.
Background
The Carbon overview contains a "skeletal
design" for return.
Carbon aims for
familiarity for experienced C++ developers with a gentle learning curve.
C++ returns from functions with a return statement, which is documented well
here.
Proposal
Carbon will have a return statement that is unsurprising to C++ programmers.
Each of these is a valid Carbon function:
// A function that returns no value
fn NoReturn() {
// This function intentionally left blank
}
// A function that returns no value in a different way
fn ReturnNoValue() {
// Usually no expression in a function with no return value.
return;
}
// A function that returns a value
fn ReturnFive() -> Int {
// Must include an expression "convertible" to `Int`.
// The (lack of) definition for "convertible" is addressed later.
return 5;
}
Details
We define a return statement in Carbon. It can occur any place a statement is
allowed. It takes one optional expression, the return value. Functions may
contain multiple return statements.
A function that returns Void may have return statements. Most will have no
return value, though some may provide a Void-type expression, for example the
result of another Void-returning function.
This last affordance is provided to avoid making
Voida special case in templating.
Functions returning Void are also defined to end with an implicit return
statement.
This implicit
returnis intended to make it easier for later designs to refer to "the (now always present)returnstatement" rather than the less well-defined "the point the function returns".
A function that returns anything other than Void must have at least one
return statement. All return statements in the function must provide an
expression "convertible" to the function's return type. If a control flow path
reaches the end of the function without executing a return statement, it is a
compile error.
Deferred questions
This proposal is limited to the syntax and simple static semantics of the
return statement.
Some questions about the full validity and meaning of a return statement in
context are left unresolved, in the expectation they will be addressed when
adjacent parts of the language are specified.
Those include:
-
What does "convertible" mean?
When a function returns a value, we say the
returnstatement takes an expression "convertible" to the function's return type. As a coarse approximation, this may mean "assignable to a variable of the function's return type", but there are likely to be subtleties. We assume this question will be addressed as the type system develops. -
What optimizations are encouraged or guaranteed for return values?
C++ has copy elision and it's a good bet Carbon will too. But first we need to decide what copying means.
-
What code, if any, runs between
returnand returning?Carbon is likely to have approaches for deterministic cleanup that trigger when a function's code stops executing -- analogues to C++ destructors, Golang deferred functions, or Java's
finallyblocks. Once we know what they are and how we intend them to work, we can determine how to slot them in next toreturn.
Alternatives considered
Implicit or expression returns
Some C-family languages allow an unadorned expression in the right context to serve as a return value.
In Rust, for example, function bodies are block expressions, which may have an expression as their final clause and which take the value of that expression.
This Rust function returns 5:
fn return_five() -> i32 {
perhaps_unrelated_action();
5
}
Rust still has a return statement, so this is entirely an ergonomic feature.
We can choose to add a similar feature to Carbon in the future as long as we can unambiguously discern expressions and statements in parsing.