Function Keyword vs Return Type: Why Modern Languages Use fn/func
Purpose
This post explains why modern programming languages like Go, Rust, and Kotlin use dedicated fn/func keywords instead of the C-style return-type-first syntax.
When I started learning these languages, I noticed they all put the function name before the return type. This seemed different from C and C++. I wanted to understand why.
The C-Style Approach
In C and C++, you write functions like this:
int calculate(int x) { return x * 2;}The return type comes first. This is how I learned programming. But there’s a problem: you don’t know if int x is a variable or a function until you see what comes next.
int x = 5; // Variableint x() { ... } // Functionint x(); // Function declarationThe parser and your brain have to look ahead to figure it out.
The Modern Approach
Modern languages use a keyword first:
fn calculate(x: i32) -> i32 { x * 2}func calculate(x int) int { return x * 2}The fn or func keyword tells you immediately: this is a function. No ambiguity.
Why This Matters
Less Mental Load
When I read code, I scan it quickly. With keyword-first syntax, I can see fn or func and know it’s a function without parsing the whole line.
With return-type-first, I have to check:
- Is this a variable declaration?
- Is this a function definition?
- Is this a function declaration?
This takes more cognitive effort.
Easier Scanning
I scan for function names more often than return types. When I look at a file, I want to see what functions are available.
Return-Type-First Keyword-First
int calculate() fn calculate() -> intstd::string getName() fn getName() -> Stringstd::map<K,V> getData<K,V>() fn getData<K,V>() -> Map<K,V>With keyword-first, all function names start at the same column. They align visually. This makes scanning easier.
Better with Generics
Modern languages use generics a lot. Return types can get complex.
// This would be hard to read with return-type-firstResult<HashMap<String, Vec<Arc<Mutex<Box<dyn Any>>>>>, Box<dyn Error>> parse(input: &str)
// Actual Rust syntax is clearerfn parse(input: &str) -> Result<HashMap<String, Vec<Arc<Mutex<Box<dyn Any>>>>>, Box<dyn Error>>The function name parse comes first. I can see what it does before wading through the complex return type.
Parser Efficiency
I read about how language parsers work. The fn keyword is the first token. The parser knows it’s a function immediately.
[email protected] "fn" // Instant recognitionThis means:
- Faster syntax highlighting
- Quicker code navigation
- Better IDE autocomplete
Language Comparison
Let me show how different languages handle this:
Go:
func process(data []byte) (result []byte, err error) { // Implementation}Rust:
fn parse_with_lifetime<'a>(input: &'a str) -> &'a str { // Implementation}Kotlin:
fun processData(input: String): Result<String> { // Implementation}C++ (for comparison):
std::vector<std::pair<std::string, int>> processData(const std::string& input) { // Implementation}Notice how the C++ example has the function name processData buried in the middle. In the modern languages, it’s right after the keyword.
What About Trade-offs?
I tried to think about when return-type-first might be better.
When Return-Type-First Works
- Simple functions with short return types
- When you care more about what a function returns than what it’s named
- Type inference scenarios like C++
auto
When Keyword-First Shines
- Generic programming with complex types
- Large codebases where you need to scan quickly
- Code with lots of function declarations
- When function names matter more than return types
My Experience
When I started learning Rust after years of C++, I found the fn keyword strange at first. It felt like extra typing.
But after using it for a while, I noticed:
- I could scan code faster
- I understood new codebases quicker
- Function signatures felt more natural
Now when I go back to C++, I find myself searching for function names in the middle of lines.
Summary
In this post, I explained why modern languages use fn/func keywords instead of return-type-first syntax.
The key point is that keyword-first syntax reduces cognitive load and makes code easier to scan. You can identify functions immediately without parsing the whole line. This matters more as code gets complex with generics and large codebases.
Modern language designers chose readability and tooling support over minimal syntax. The extra keyword token is a small price to pay for clearer code.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
- 👨💻 Go Language Specification
- 👨💻 Rust Reference - Functions
- 👨💻 Kotlin Functions Documentation
- 👨💻 C++ Function Declarations
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments