I like functional programming, especially in points-free style: it allows amazingly terse expression, with minimal attention to plumbing. But there is an annoyance that often trips me up: there's a discontinuity between combinator expressions and lambda-expressions.
Consider the commonplace task of iterating over a list and, say, printing out the elements. There is an obvious points-free way:
(mapc #'print numbers)
More complex functions can be handled with combinators...
(mapc (compose #'print #'round) numbers)
...and partial application:
(mapc (compose (op format t " ~S~%" _) #'round) numbers)
But for more complicated functions, points-free style gets awkward quickly, especially if you don't have other combinators like
s. As soon as we want to use some variable twice, it's usually easier to switch to
(mapc (lambda (x) (format t "~S (really ~S)~%" (round x) x)) numbers)
And that switch requires rewriting the whole function in a completely different way.
Having more than one way to write functions is not in itself a problem, of course. The trouble is that I often want to transform between them, when a points-free expression grows to the point where it needs a lambda. At this point I have to stop thinking about what I want the code to do, and instead think about the trivia of combinators and variables. It's only a minor annoyance, but it's a very common one. And it's more common in more points-free code, so it probably discourages good programming style.
Is there an alternative to lambda/combinator calculus that can express simple functions as tersely as combinator style, but without the discontinuity when they grow? In particular, I want to be able to name variables without reorganizing the code that uses them. This is a hard problem and I don't expect to find any good solution, but I'm still looking. Lambda and combinator calculus are wonderful things, but they're not perfect, and even a small improvement in expressiveness of simple functions would be a big deal.