> is unnecessarily insulting.
I know that it's insulting! And it doesn't make sense, because I generally think Rust programmers are smart people. But right now, it's the only explanation I've got, so it is alas necessarily insulting. So please, please, please give me a better explanation that actually makes sense.
> The truth is that some things are harder in Rust but a) often those things are best avoided anyway (e.g. callbacks), and b) it's worth the trade-off because of the other good things it allows.
This sounds like the seeds of a better explanation, but it needs a lot more to actually suffice. E.g.: why are callbacks best avoided anyway, when they're virtually required for a large number of important programming patterns? (In more technical language: they're effectively the only way to eliminate duplication in non-leaf-expressions. In even more technical language: they're the way to do second-order anti-unification.)
> Surely as a Haskell user of all things you must understand that sometimes making things harder is worth the trade-off. Yeay everything is pure! Great for many reasons. Now how do I add logging to this deeply nested function?
And this is a great illustration of the difference. First, you will seldom find Haskell programmers trying to argue that, actually, things like deeply-nested logging that everyone wants are actually "best avoided anyway." Second, you'll actually get a solution if you ask about them -- in this case, to either use MTL-style, to use a fixed alias for your monad stack, or that unsafePerformIO isn't actually that bad.
BTW, similar to my unpleasant conclusion for Rust above, I have another unpleasant conclusion for Haskell: Haskell is incredible for medium-sized programs, but it has its own missing modularity features that make it non-ideal for large programs (e.g.: >50k lines). But this is a much smaller problem than it sounds because Haskell is so compact that, while many projects can be huge, very few individual codebases will need to approach that size.
> why are callbacks best avoided anyway
Look up "callback hell". Basically they encourage spaghetti.
> you'll actually get a solution if you ask about them
You got solutions to your problems didn't you? Macros are a perfectly reasonable thing to use in Rust, even if they are best avoided where possible. Exactly like unsafePerformIO.
If you were expecting Rust to work perfectly in every situation... well it doesn't. GUI programming in particular is still awkward, and async Rust has more footguns than anyone is happy with.
Despite that it's still probably the best language we have for a surprisingly large range of domains.
> Look up "callback hell". Basically they encourage spaghetti.
Ah. I think you're confusing the general idea of a callback with one particular style of use. "callback hell" refers to the deep indentation that occurs when trying to program in monadic style in languages without syntactic support for monads. It was mostly solved by adding async/await syntax, aka syntactic support for the continuation monad. "Callback hell" is not spaghetti in any deep sense, merely syntactically cumbersome.
But a "callback" is a more general term, sometimes a synonym for "function parameter," sometimes for more narrow kinds of function parameter (e.g.: void function, invokable once). Many people will refer to the function argument of the `map` function as a callback, but no-one would refer to that as "callback hell."
Callbacks are quite universal, and most uses do not lead at all to callback hell. I've engaged with this topic a little bit at https://us16.campaign-archive.com/?u=8b565c97b838125f69e75fb... , above the header "Serious Business."
> You got solutions to your problems didn't you?
Mostly no :(
And when I did, I largely got it by figuring stuff out myself, while being told by multiple Rust experts that I either shouldn't care about the verbosity and lack of modularity, or that if I have a problem like "using the interface instead of the implementation" it must be because I'm a Haskeller.
Well, my ultimate solution was to start working on a new product, and to not use any Rust, except for some performance-heavy libraries. With the first product, the market had changed too much by the time we were ready for prime-time, and I'd put somewhere between 25% and 70% of the reason for that delay on our choice to start building new parts of the backend in Rust.
> Macros are a perfectly reasonable thing to use in Rust, even if they are best avoided where possible. Exactly like unsafePerformIO.
Good comparison!
> Despite that it's still probably the best language we have for a surprisingly large range of domains.
I agree with this. I just don't agree that that list of domains has a very large intersection with the set of applications.