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.
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.
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.
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?
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.
About functions not being 1st class citizens: you can use types like
impl Fn(u32, bool) -> u32
. This means "return/take something that implementsFn(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.But functions and closures are not interchangeable right? So functions still aren't first class citizens IMO
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.See my comment above
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
andFnMut
.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.
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?
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...