I don't think currying is that big a deal, it's just syntactic sugar that might or might not make things easier to read, unlike ADTs or closures which are important core concepts.
I'd love to have a syntax like
{ foo(%1, bar) }
standing for
|x| { foo(x, bar) }
though. I'm not aware of any language that has this!
As noted in other comments, a bunch of languages has it, but the problem with this syntax is that it doesn't generalize well. For example, let's say we have:
foo(%1, bar(%1, 42))
does this desugar to:
|x| foo(x, |y| bar(y, 42))
or to:
|x| foo(x, bar(x, 42))
and do you trust the person reading this code later to remember which one it is?
I think currying is an important concept and not sugar at all, as it means each function takes exactly one parameter, i.e. in OCaml foo bar baz is equal to (foo bar) baz. Of course, some other languages can try to emulate the use of currying and the original original idea no longer exists there.
I'm relatively sure there exists such a language you are looking for, but I've forgotten its name :(.
There was a syntax extension pa_holes for OCaml (which you perhaps know, as it is natively currying) that worked like
(\ foo \1 bar)
and it would become
fun x -> foo x bar
I'm sure the extension was inspired by some other language.. And the pa syntax extension extension mechanism for OCaml has been replaced by ppx a long time ago already; maybe the new system doesn't enable such succinct extensions.
I'd argue that currying is actively harmful (I suspect you agree). I've seen functions take one argument in one source file, and the next argument in another source file. In JavaScript no less. Horrendous stuff. One of my most hated anti-features, along with Scala's implicits. These kinds of features are mostly misused rather than used.
From what I've seen, partial application tends to be used for utmost good in dialects of ML, and utmost evil most everywhere else. Chaotic neutral in R/tidyverse.
I've occasionally wondered about the lack of currying in Rust; it feels like something that can be done mechanically at compile time, so why not support it? Perhaps to do it cleanly (without more magical privileged functions in core) would require variadic generics?
You can absolutely curry functions in Rust. You just have to do it manually because there's no syntactic sugar for it.
I think that's a good thing. A curried function is a function that takes one argument, and returns a closure that captures the argument. That closure might itself take another argument, and return a new closure that captures both the original argument and the second one. And so on ad infinitum. How ownership and borrowing works across that chain of closures could easily become a touchy issue, so you probably want to be making it as explicit as possible.
Or perhaps better yet, find an easier way to accomplish the same task. Maybe use a struct to explicitly carry the arguments along until you're ready to call the function.
Currying is just syntactic sugar for a lambda that binds the first argument and passes the rest unchanged, and you can achieve the same level of conciseness in other ways - e.g. "pipeline" operators - but with a syntax that is more readable and more extensible. E.g. https://docs.rs/piping/latest/piping/
This isn’t Rust-specific, but one reason a language designer might deliberately not implement currying is that it makes function call sites a bit harder to read. You need to already know how many arguments a function takes to make sense of the call’s return type.
It takes ADT, but not function currying, and so on.