Description
Preface
Statement-expression is a solution to have a group of statements in place of an expression.
I suggest to have statement-expressions in Cpp2 with syntax : = { ... }
and the result of them are returned with result
keyword. In this way, the following code:
call(: = { n: = num(); result n + 0; },
: = { n: = num(); result n + 1; });
... is somehow equal to the following code except that we don't have to specify the type of arguments:
arg0: int; { n: = num(); arg0 = n + 0; }
arg1: int; { n: = num(); arg1 = n + 1; }
call(arg0, arg1);
Statement-expressions can be used to declare variables too:
// The type of `variable` is `int`.
variable: = {
value: int;
//: statements...
result value;
}
Suggestion Detail
Currently we declare functions in Cpp2 in the following syntax:
// function or lambda style
func0: (param) = {
return param;
}
// expression style
func1: (param) = param;
In a similar syntax, we can declare variables in Cpp2 with statement-expressions:
// statement-expression style
var0: = {
result 0;
}
// expression style
var1: = 0;
Statement-expressions are unnamed variables in a similar manner that lambdas are unnamed functions:
- We have to use
result
instead ofreturn
within statement-expressions. - We can use a statement-expression everywhere that an expression is required.
- A declaration within their
{ ... }
has the lifetime of that scope. - Their
{ ... }
will be executed one time in their place. - They don't create a new function scope, therefore variables from outer scope don't have to be captured within their
{ ... }
.
Statement-expressions will be not allowed to be used in place of statements. Because it's an error to have an unused value (literal or identifier) in Cpp2:
main: () = {
// ERROR! It has to be in place of an expression not an statement.
: = {
x: = 0;
result x + 1;
}
// ERROR! Because `x + 1` is an unused value (literal or identifier).
}
Expressions, Functions and Blocks
Now { ... }
has different meanings in the following categories:
: Type = { ... }
is a statement-expression in whichType
can be omitted and deduced from{ ... }
.- The execution of statements in
{ ... }
ends withresult something;
. - It can be a part of variable declaration, or in place of an expression (e.g. function argument):
x0: = 0; x1: = { result 0; } call(: = { result 0; })
- The execution of statements in
: (params) -> Type = { ... }
is a function or a lambda in which-> Type
can be omitted if the return type isvoid
.- The execution of statements in
{ ... }
ends withreturn something;
or the end of}
. - It can be a part of function declaration, or in place of an expression (e.g. function argument):
x0: (param) = param; x1: (param) = { return param; } call(: (param) = { return param; })
- The execution of statements in
(params) { ... }
is a parameterized statement block. Whereas{ ... }
is a statement block without(params)
in which()
must be omitted.- The execution of statements in
{ ... }
ends with:- ... the end of
}
. - ...
break
andcontinue
in loop control structures. - ...
result something;
when their outer scope is a statement-expression. - ...
return something;
when their outer scope is a function or a lambda.
- ... the end of
- It can be a part of control structures:
for items do (item) { call(item); } if condition { call(); }
- The execution of statements in
In all of the above categories, they have this similarity:
- A declaration within their
{ ... }
has the lifetime of that scope.
Additinally they have different behaviours in statement execution and variable capturing:
- Statement-expressions (case 1) have to execute their
{ ... }
one time in their place.- But other cases can execute their
{ ... }
multiple times in any place.
- But other cases can execute their
- Functions and lambdas (case 2) create a new function scope therefore variables from outer scope have to be captured within their
{ ... }
.- But other cases don't create a new function scope, therefore variables from outer scope don't have to be captured within their
{ ... }
.
- But other cases don't create a new function scope, therefore variables from outer scope don't have to be captured within their
I should mention that statement-expressions, functions and lambdas, statement blocks and parameterized statement blocks can be nested inside each other.
Your Questions
Will your feature suggestion eliminate X% of security vulnerabilities of a given kind in current C++ code?
Yes. In a way that it helps Xto organize code and separate related statements in nested blocks to easily fix or prevent unwanted bugs which are a result of having mixed unrelated statements together.
Will your feature suggestion automate or eliminate X% of current C++ guidance literature?
Yes. In the following ways:
- It will make the declaration syntax of variables and functions to be similar and consistent.
- It helps programmers to separate related statements easily without defining extra variables.
- It allows programmers to use
if
,while
and other control structures as an expression that is more readable in variable assignment, because the intention is clearly written in code, see the example below. - It allows programmers to be less specific about types in generic programming, see the example below.
Consider how the following code:
variable: = {
if condition {
result hello();
}
else {
result bye();
}
}
... is more readable and generic than the following code which we have to also specify the type of the variable:
variable: int;
if condition {
variable: = hello();
}
else {
variable: = bye();
}
Considered Alternatives
Instead of result
keyword, it's possible to use symbols such as =>
or nothing (like in Rust). For example:
variable: = {
if condition {
=> hello();
}
else {
=> bye();
}
}
... or this one (like in Rust):
variable: = {
if condition {
hello() // without ;
}
else {
bye() // without ;
}
}
Howerver I think that having a keyword like result
or a notation like =>
, is more readable than having nothing.
References
This suggestion is inspired from discussions in this issue and this paper mentioned by @JohelEGP and this informative comment from @hsutter which describes Unifying Functions and Blocks.