DEV Community

Discussion on: My first impressions of Rust

Collapse
 
eugenebabichenko profile image
Yevhenii Babichenko • Edited

About functions not being 1st class citizens: you can use types like impl Fn(u32, bool) -> u32. This means "return/take something that implements Fn(u32, bool) -> u32 interface". The underlying implementation can be either a function or a closure.

What is unfortunate, that you cannot write something like type MyFn = impl Fn(u32, bool) -> u32. This is a nightly-only feature right now.

Collapse
 
deepu105 profile image
Deepu K Sasidharan

But functions and closures are not interchangeable right? So functions still aren't first class citizens IMO

Collapse
 
eugenebabichenko profile image
Yevhenii Babichenko

What do you mean by "interchangeable"? If a function accepts a parameter of type impl Fn(...) -> ..., then this parameter can be either a function or a closure (so they are interchangeable). You can do many other other things with such types (return them, assign to variables, etc). IMO this is something that looks like 1st class functions.

Thread Thread
 
deepu105 profile image
Deepu K Sasidharan

See my comment above

Collapse
 
grayjack profile image
GrayJack • Edited

They are, the thing is, in Rust, callables are much more complicated than usual languages, at least what is exposed to the programmers.

We have 3 traits for callables, FnOnce, Fn and FnMut.
All functions, function pointers and closures implements FnOnce.
All functions, function pointers and closures which does not move out of any captured variables implements FnMut, indicating that it can be called by mutable reference.
All functions, function pointers and closures which does not mutate or move out of any captured variables implements Fn, indicating that it can be called by shared reference.

The only way to have pass either function or function pointers or closures as parameter are using these traits, so on every context they are interchangeable.

Thread Thread
 
deepu105 profile image
Deepu K Sasidharan

Ok, I need to dwelve into this more. Now its more confusing to be honest. If they are same or interchangeable why have 2 concept/syntax? Why not keep it simple? Was there any specific reason to have both function and closures?

Thread Thread
 
grayjack profile image
GrayJack

Well that's the bit it gets really confusing, they are not the same, but are interchangeable, when we say "function as first class citizen", we meant "callables as first class citizen", my hypothesis is because when the term was created, most major languages at the time had no more than one type of callable down on it's AST level that was functions, but that's not the point.

In Rust all functions have a type, and all closures are a type on it's own, but both are callables.

I have no knowledge why this way, but my instinct is that maybe something related to closures ability to capture the outer environment variables and the type system and optimizations.

I found the blog post that are talks about this:
stevedonovan.github.io/rustificati...