I'm sure they do, but even you must admit that Rust has gotten less 'functional' in nature as time goes on. New syntax or ad-hoc abstractions are being created to handle problems that have well known FP solutions. Take this matching on an Option business. The easy solution is to just add a fold method on the option type. Problem solved, now you never will need to match an option ever again! The harder solution would be to implement HKT and add a real monad trait, but let's not get into that. Another example are the async/await syntax. Why does this syntax need to exist? What value does it provide? Why can't a future just be a regular old class?
A long time ago I thought Rust was going to be a flexible and innovative general purpose language. While it still is undoubtedly innovative, it seems like the target audience has shrunk considerably. And as GCs improve and get more tunable, I think that target audience is going to get even smaller in the future.
> even you must admit that Rust has gotten less 'functional' in nature as time goes on.
I don't think this is true, especially when you look at long timescales.
> New syntax or ad-hoc abstractions are being created to handle problems that have well known FP solutions.
They have known solutions when you have a GC and no control over memory layout. They do not have known solutions in a language like Rust.
> Take this matching on an Option business. The easy solution is to just add a fold method on the option type. Problem solved, now you never will need to match an option ever again!
Sorry, I do not understand what you're talking about. (I coded in Haskell most a decade ago, I'm not on the lang team.) What would fold do on an option, specifically? Fold is usually a list operation, but an option is a list of zero or one... so it would be a no-op?
> The harder solution would be to implement HKT and add a real monad trait, but let's not get into that
Again, this is "we don't know if this is possible in a language like Rust" territory. Which is why you don't want to get into that.
> Another example are the async/await syntax. Why does this syntax need to exist?
Specifically because of the previous statement. It is not clear that a more abstract option is possible. We could wait for more years until maybe it's proven possible, or we could implement a useful feature today that we know is.
Rust doesn't have classes. Futures are a regular old typeclass.
> While it still is undoubtedly innovative, it seems like the target audience has shrunk considerably.
We have seen a massive uptick in adoption over the past few years. async/await, for example, has been a feature that a lot of folks have said "I'll start using Rust once that hits stable."
> What would fold do on an option, specifically? Fold is usually a list operation, but an option is a list of zero or one... so it would be a no-op?
Presumably the fold takes advantage of the fact that the default, "accumulator" value is chosen if the Option is empty and the collapse function just runs what would be the Some arm of the match statement.
If the team had just written Haskell for a year they would have picked the obviously superior "fold" name for this operation. (I think you can actually use fold here if you really wanted it, since Option implements IntoIter?):
For people coming from a functional programming background, `fold` might be the superior name. But setting aside monads, `map_or` expresses the intent much better I find.
The function in Option linked above by steveklabnik has signature
fn map_or(self, default: U, f: FnOnce(T) -> U) -> U
a fold has the signature
fn fold(self, init: U, f: FnMut(U, T) -> U) -> U
The difference is in the closure. in map_or the closure gets called at most once with one argument, in fold it can get called many times with two arguments. This makes `map_or` and `fold` distinct functions. While you could argue that the distinction between FnOnce and FnMut is Rust specific, the difference in number of arguments should also exist in Haskell. And in fact in Haskell the `map_or` function is called `maybe`:
(I'd argue the name `map_or` is more descriptive than `maybe`, although it does lift the result out of the Option monad which is unconventional for a map.)
Besides the GC that is already mentioned, Haskell has lazy evaluation which gives you coroutines for free. Coroutines are more or less synonymous with async, so in Haskell the implementation is a no-op.
From what I read, much of the challenge of adding async to Rust was in designing the coroutine mechanism, which is a substantial language extension.