Firstly, I suspect you might mean partial appplication; many functional languages in that family support implicit partial application, so that if f is a three argument function, f a b c is be regarded as the partial applications ((f a) b) c).
Currying is a mechanism of representing all functions with two or more arguments using functions of only one argument; with currying we can "bootstrap" functions of higher arities in a substrate like a lambda calculus that has only one argument functions.
This arrangement of implicit partial application is a syntactic sugar.
Syntactic sugar for partial application is not partial application itself. Manual partial application is just as "functional". Functions are being applied, and passed around as values.
Implicit partial application can be obtained with Lisp macros, but that can never be fully general for at least two reasons.
One is that Lisps support something very useful, namely variadic functions, and functions with optional arguments. Variadic functions mean that you don't need ugly shims like "zipwith3" in a Lisp.
However, implicit partial application also requires static typing. In order to know that f is a three argument function being called with two arguments, and therefore reduced to a partially applied one-argument function, our syntactic sugar processor needs complete arity information about f.
In a Lisp, f can be redefined at run-time from having three arguments to having four.
In principle, in spite of that, all function calls could be treated as partial applications in a very generic way, but it would be horribly, horribly inefficient --- and the diagnostics when things go wrong would be pretty terrible.
Agree with all your points, and I did mean partial application, not partial evaluation.
And yes currying is not the same thing but it's common in informal settings to say "Haskell has automatic currying" and everybody knows you're talking about automatic partial application.
Lisp can of course do partial application and currying but not automatically; as you say you'd have to write special macros and sacrifice variadic functions to make it work (and I have done so). And it's really not that necessary in Lisp because we have parentheses; Haskell is the only example I've yet found of a Lisp-like language that has successfully removed most of the parentheses, and it succeeded because of its implicit partial application. But it had to sacrifice variadic functions.
When I first started using Haskell I lamented not having macros, and then I realized that many of my use cases for macros in Common Lisp weren't necessary in Haskell because of its laziness.
CL is still my daily-use language. But Haskell expanded how I think about programming almost as much as Lisp did all those years ago; that happened because Haskell took the functional metaphor to an extreme. I now write better Lisp programs because of my exposure to Haskell.
Currying is a mechanism of representing all functions with two or more arguments using functions of only one argument; with currying we can "bootstrap" functions of higher arities in a substrate like a lambda calculus that has only one argument functions.
This arrangement of implicit partial application is a syntactic sugar.
Syntactic sugar for partial application is not partial application itself. Manual partial application is just as "functional". Functions are being applied, and passed around as values.
Implicit partial application can be obtained with Lisp macros, but that can never be fully general for at least two reasons.
One is that Lisps support something very useful, namely variadic functions, and functions with optional arguments. Variadic functions mean that you don't need ugly shims like "zipwith3" in a Lisp.
However, implicit partial application also requires static typing. In order to know that f is a three argument function being called with two arguments, and therefore reduced to a partially applied one-argument function, our syntactic sugar processor needs complete arity information about f.
In a Lisp, f can be redefined at run-time from having three arguments to having four.
In principle, in spite of that, all function calls could be treated as partial applications in a very generic way, but it would be horribly, horribly inefficient --- and the diagnostics when things go wrong would be pretty terrible.