Revolutionizing Rust Function Syntax: Moving Towards a More Concise Declaration Style?

About Rust Function Syntax

This article presents some thoughts on aspects that were not deeply considered during Rust’s early days, hoping to inspire those who are creating new languages.

First, let’s discuss the existing <span>fn</span> syntax. Rust excels in many areas, allowing various elements to integrate well together. Although it is not a small language, this integration makes it feel more compact. However, there is one inconsistency in the syntax and semantics of functions.

Declaring a function simply looks like this:

fn foo(x: i32)-> i32{
todo!()
}

But for more complex declarations, things become complicated. Compared to C-style function definitions:

int foo(int x){
// todo
}

Most new programming languages tend to adopt syntax closer to Rust rather than C. There are several reasons for this, and it is not to say that Rust invented this style. One core advantage is <span>fn IDENTIFIER</span>, meaning if you want to find the definition of <span>foo()</span>, you can quickly search for <span>fn foo</span>. Using the <span>int</span> style is not as effective. Some coding styles require you to write it as:

int foo(int x){
// todo
}

Particularly, the GNU project recommends this style: starting the function definition name from the first column helps people search for function definitions and may assist certain tools in recognizing them. At this point, you can search using <span>^foo</span> to achieve a similar effect.

So, what is the problem with this syntax? When adding useful “modifiers” to functions, such as wanting <span>foo</span> to be callable in a const context, we turn it into a const function:

const fn foo(x: i32)-> i32{
  todo!()
}

While this retains the convenience of “searching for fn”, these modifiers can also be used for arbitrary code blocks:

let x = const{
  1+2
};

This example, while simple and not very practical, illustrates the syntax. The key point is that it starts to feel a bit inconsistent. In function declarations, we place <span>const</span> at the front, but in other code blocks, we place it directly before the code block. Although Rust’s function bodies share many similarities with block expressions in other languages, such as the evaluation of the final expression, they differ in how they describe function bodies.

To improve this, we could try a slightly different syntax structure, borrowing from variable declaration styles. Just like in C, Rust’s variable declaration syntax is similar to function declaration syntax:

// Rust
let x: i32=5;
// C
int x=5;

We have <span>let</span> replacing <span>fn</span>, with the name followed by the type instead of the type preceding it. We can also declare a variable without initializing it:

let x: i32;

Rust requires it to be initialized before use, but allows declaring the variable first and then assigning a value.

Based on this, why not adjust regular function definitions to also follow the syntax of variable declarations?

fn foo(x: i32)-> i32={
  todo!()
}

By adding an equals sign after the return type, we can more easily unify the remaining syntax around blocks:

// Full signature
fn foo(x: i32)-> i32={
  todo!()
};
// Empty return type
fn foo(x: i32)= {
  todo!()
};
// const
fn foo(x: i32)-> i32=const{
  todo!()
};

This small change not only simplifies the syntax but also makes the structure neater.

let name=value;
fn name()=value;

Whether both are values or blocks, <span>let</span> is usually a value while <span>fn</span> is typically a block. This symmetry is pleasing.

Of course, this also raises another point of divergence, but that might be going a bit too far, especially when dealing with types. The syntax of name: type is better because it performs better in the presence of type inference. However, since Rust function signatures do not have type inference, there is no need to emphasize graceful degradation. Choosing not to provide type inference in function signatures is the right decision for Rust, but for languages that may support this feature in the future, they could unify them, for example:

// Explicit type
fn foo(x): fn(i32)-> i32={
  todo!()
}
// Inferred type
fn foo(x)= {
  todo!()
}

This discussion seems to compare different styles of function declarations in the Rust language, particularly in contrast to the syntax familiar to the C++ community. While Rust does not have named parameters and may never have them, what is explored here is what it would look like if a new syntax style were adopted. This style eliminates the repetitive use of the <span>fn</span> keyword and borrows from the syntax style designed by Herb Sutter for another language.

Considering that Rust has already faced some criticism for its uniqueness, a complete overhaul of function declaration styles might be seen as too radical. However, this idea is not entirely out of the realm of possibility. In fact, the syntax proposed by Herb Sutter specifically targets the C++ developer community, who may be skeptical of new syntax. This suggests that perhaps such changes are not unfeasible.

Let’s see how this syntax would work in hypothetical Rust code:

fn main()=println!("Hello, world!");
fn hello(name): fn(&str)=println!("Hello, {name}!");

This concise expression is indeed appealing. It not only reduces redundancy but also makes the code look more intuitive and clear. For those accustomed to C++ or similar languages, this change may be more easily accepted as it reduces the learning curve while maintaining logical coherence.

However, it is important to recognize that the design of any language does not exist in isolation. Consistency is a good goal, but it is not the only goal. Sometimes, bold leaps made in pursuit of consistency and simplicity may not suit all users. After all, programming languages are not just technical tools; they are also mediums of communication that need to consider users’ habits and preferences.

So the question arises, if Rust were to adopt this syntax style, how would it affect the experience of existing users? More importantly, would it attract more developers to join the Rust community, or would it further alienate those who already find Rust “a bit strange”?

Click 👇 to follow

Like + Share + View to quickly enhance your programming skills👇

Reference link: https://steveklabnik.com/writing/too-many-words-about-rusts-function-syntax/

Leave a Comment