You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/cpp2/declarations.md
+165-6Lines changed: 165 additions & 6 deletions
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
-
# Declaration syntax
1
+
# Declarations and aliases
2
2
3
-
## Overview: Unified declaration syntax
3
+
## Unified declarations
4
4
5
5
All Cpp2 declarations are written as **"_name_`:`_kind_`=`_statement_"**.
6
6
@@ -20,10 +20,70 @@ Various parts of the syntax allow a `_` "don't care" wildcard or can be omitted
20
20
>
21
21
> - When the type is omitted, whitespace does not matter, and writing `#!cpp x: = 0;` or `#!cpp x : = 0;` or `#!cpp x := 0;` or other whitespace is just a stylistic choice. This documentation's style uses the last one, except when there are multiple adjacent declaration lines this style lines up their `:` and `=`.
22
22
>
23
-
> -`==` stresses that this name will always have the given value, to express [aliases](aliases.md) and side-effect-free 'constexpr' [function aliases](aliases.md/#function-aliases).
23
+
> -`==` stresses that this name will always have the given value, to express [aliases](#aliases) and side-effect-free 'constexpr' [function aliases](#function-aliases).
In an expression, most declarations can be written without a name (just starting with `:`). Such unnamed declaration expressions are useful for single-use temporary variables or 'lambda' functions that don't need a name to be reused elsewhere. For example:
29
+
30
+
-`#!cpp :widget = 42` is an unnamed expression-local (aka temporary) object of type `widget` defined as having the initial value `#!cpp 42`. It uses the same general syntax, just
31
+
32
+
-`#!cpp :(x) = std::cout << x` is an unnamed expression-local generic function expression (aka lambda) defined as having the given one-statement body. The body can include [captures](expressions.md/#captures)
33
+
34
+
Both just omit the name and make the final `;` optional. Otherwise, they have the identical syntax and meaning as if you declared the same thing with a name outside expression scope (e.g., `w: widget = 42;` or `f: (x) = std::cout << x;`) and then used the name in the expression.
35
+
36
+
> Note: Throughout Cpp2, every declaration is written with `:`, and every use of `:` is a declaration.
37
+
38
+
39
+
40
+
### <aid="function-scope-unification"></a> From functions to local scopes, and back again
41
+
42
+
The function syntax is deliberately designed to be general, so you can omit parts. This means Cpp2 has no special "lambda function" syntax for unnamed functions; an unnamed function is really an unnamed function, written using the ordinary function just without a name. This scales all the way down to ordinary blocks and statements, which are written the same as functions that have no name or parameters.
43
+
44
+
We can illustrate this in two directions. First, let's start with a full function, and successively omit optional parts that we aren't currently using:
45
+
46
+
```cpp title="Start with a full function, and successively omit optional parts if unused" hl_lines="1 5 9 13"
47
+
// Full named function
48
+
f:(x: int = init) = { /*...*/ } // x is a parameter to the function
49
+
f:(x: int = init) = statement; // same, { } is implicit
50
+
51
+
// Omit name => anonymous function (aka 'lamba')
52
+
:(x: int = init) = { /*...*/ } // x is a parameter to the function
53
+
:(x: int = init) = statement; // same, { } is implicit
54
+
55
+
// Omit declaration => local and immediate (aka 'let' in other languages)
56
+
(x: int = init) { /*...*/ } // x is a parameter to this
57
+
(x: int = init) statement; // compound or single-statement
58
+
59
+
// Omit parameters => ordinary block or statement
60
+
{ /*...*/ } // ordinary compound statement
61
+
statement; // ordinary statement
62
+
```
63
+
64
+
Conversely, we can start with an ordinary block or statement, and successively build it up to make it more powerful:
65
+
66
+
``` cpp title="Start with an ordinary block or statement, and successively add parts" hl_lines="1 5 9 13"
67
+
// Ordinary block or statement
68
+
{ /*...*/ } // ordinary compound statement
69
+
statement; // ordinary statement
70
+
71
+
// Add parameters => more RAII locally-scoped variables
72
+
(x: int = init) { /*...*/ } // x is destroyed after this
73
+
(x: int = init) statement; // compound or single-statement
74
+
75
+
// Add declaration => treat the code as a callable object
76
+
:(x: int = init) = { /*...*/ } // x is a parameter to the function
77
+
:(x: int = init) = statement; // same, { } is implicit
78
+
79
+
// Add name => full named function
80
+
f:(x: int = init) = { /*...*/ } // x is a parameter to the function
81
+
f:(x: int = init) = statement; // same, { } is implicit
A template parameter list is enclosed by `<``>` angle brackets, and the parameters separated by commas. Each parameter is declared using the [same syntax as any type or object](declarations.md). If a parameter's **`:`*****kind*** is not specified, the default is `: type`.
A `#!cpp requires`***condition*** constraint appears at the end of the ***kind*** of a templated declaration. If the condition evaluates to `#!cpp false`, that specialization of the template is ignored as if not declared.
// n is a namespace defined as the following scope
@@ -121,3 +181,102 @@ n: namespace
121
181
```
122
182
123
183
> Note: `@enum` is a metafunction, which provides an easy way to opt into a group of defaults, constraints, and generated functions. For details, see [`@enum`](metafunctions.md#enum).
184
+
185
+
186
+
## <aid="aliases"></a> Aliases
187
+
188
+
Aliases are pronounced **"synonym for**, and written using the same **name `:` kind `=` value**[declaration syntax](../cpp2/declarations.md) as everything in Cpp2:
189
+
190
+
-**name** is declared to be a synonym for **value**.
191
+
192
+
-**kind** can be any of the kinds: `namespace`, `type`, a function signature, or a type.
193
+
194
+
-**`==`**, pronounced **"defined as a synonym for"**, always precedes the value. The `==` syntax stresses that during compilation every use of the name could be equivalently replaced with the value.
195
+
196
+
-**value** is the expression that the **name** is a synonym for.
A namespace alias is written the same way as a [namespace](namespaces.md), but using `==` and with the name of another namespace as its value. For example:
A function alias is written the same way as a [function](functions.md), but using `==` and with a side-effect-free body as its value; the body must always return the same value for the same input arguments. For example:
0 commit comments