-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
single expression function syntax #3369
Comments
What do you mean? Your example using |
yeah, that was an mistake. updated example code to also demonstrate |
fair point. that's the reason why I've added that to disadvantages section.
since statement ends with semicolon, and expression ends without semicolon, the syntax musn't have trailing semicolon. example
it's a matter of formatting, it could be written as fn foo<T: ops::Deref<Target = str>>(
bar: T,
qux: impl Iterator<Item = (T, i32)>,
corge: impl Fn() -> bool
) -> bool = loop {
// ...
}
it should go before the expression body( |
This feature is more important for Kotlin, because Kotlin doesn't have Rust's "returned trailing expression" rule. This works in Rust: fn f(x: Foo) -> Bar {
match x {
Foo::A(y) => y,
Foo::B(z) => bbb(z),
Foo::C(_) => ccc(),
}
} In Kotlin, this would be written in one of the following ways: // Either a return statement:
fun f(x: Foo): Bar {
return when(x) {
is Foo.A -> x.y
is Foo.B -> bbb(x.z)
is Foo.C -> ccc()
};
}
// Or several return statements insinde of `when` block:
fun f(x: Foo): Bar {
when(x) {
is Foo.A -> return x.y
is Foo.B -> return bbb(x.z)
is Foo.C -> return ccc()
}
} Note that there is more syntactic noise, and an ambiguity on the placement of fun f(x: Foo) = when(x) {
is Foo.A -> x.y
is Foo.B -> bbb(x.z)
is Foo.C -> ccc()
} This is simpler, and also allows to omit the return type. But the equivalent in Rust wouldn't be much simpler, as @SOF3 notes above. We also wouldn't want to allow omitting the return type of the function, since this complicates type checking and turns it into a global, rather than function-local, problem. The expression body in Kotlin also increases the symmetry between functions and Nothing like that exists in Rust. There is no concept of "property". Any callable is always explicitly demarcated from variables, constants and statics, because knowing that arbitrary code may be executed is considered vital information. Moreover, arbitrary sequence of statements can be used to compute the value of constant/variable, unlike in Kotlin, and that syntax itself parallels the funciton body syntax: const FOO: Foo = {
let x = call_one();
let y = call_two(x);
call_three(y)
}; So from that perspective, insisting too on a symmetry between function definitions and variables is counterproductive, and it already exists. We already have expression as a function's body today in current Rust, it's just that this expression must always have block expression form, for parsing simplicity reasons. fn $f( $($args),* ) -> $ret $expr
// where $expr is the block expr computing the function And instead of avoiding nested block for more complex block expression as fn f() -> T = async { .. } we write it even simpler, as async fn f() -> T { .. } |
For one, the entire feature shouldn't be predicated on what can or cannot be implemented as a macro. For another, you simply have to add a semicolon to the macro |
closing since it seems to have more disadvantages to the new syntax. |
Summary
allow kotlin-style single expression function syntax in form of
fn name() = expr
example implementation
Advantages
one less brackets improve readability, espcially for functions with single match block.
Disadvantages
being able to do same things in two different way may be confusing.
Previous Discussion
there was previous discussion on this topic, but the it was mostly about implicit return type. however, that is beyond this RFC's scope.
The text was updated successfully, but these errors were encountered: