This is a fallacy that gets repeated over and over, ad-nauseam. No, you can't do functional programming in any language. In Java it's more than just lack of syntactic sugar. Java's type system actively fights against functional programming. This is a bit like saying that you can do OOP in any language. Yes, you can have GObject in C. Yes, for Java there have been attempts like www.functionaljava.org ; but it sucks so badly that almost nobody does it, unless they are forced to do it.
In fact I challenge the author of this article to show me a piece of FP code that he wrote in Java by himself.
> What about all the wonderful things in the standard library? Yep, filter and map and fold operations on collections out of the box is nice. That the SDK uses Option instead of null is an improvement. These things are nice, but I generally get what I’m looking for by adding some libraries to core Java.
I do know Java's ecosystem and he must be speaking about Guava, as there's no other stable library for Java that has persistent data-structures. And Guava kind of sucks, so if you're looking for persistent data-structures, might as well implement them yourself, it's fun and it might open your eyes to what functional programming is ;-)
Speaking of Guava's Option, lets talk about how Guava's Option is not a Monad, or for those that don't know what that is, basically a context that implements map and flatMap with certain properties. Scala's Option also implements filter and fold, etc... which in regards to the purpose of a Monad, in the words of Erik Meijer, is to guide you through the happy path. Now that's a little closer to functional programming and speaking of Erik Meijer, people might be interested in what he thinks about Scala: https://twitter.com/headinthebox/status/438355100310831104
On the bad things he lists:
> Compile Time
Scala's type-system is much more static, leaving much less room for accidental bugs. Scala's compiler does things that in other languages you'd need to run specialized tools to get the same results or to write more tests. A single sentence or paragraph can't do it justice, but the big compile times are perfectly justified and this is coming from a developer that prior to Scala preferred dynamic languages with instant edit/reload cycles.
Besides, these times have been dropping as the core Scala devs have been making improvements, with another batch of optimizations coming in Scala 2.11. And incremental compilation in general works great. And I'm a developer, I have a good dev machine - if you don't have an SSD and at least 8 GB of RAM, then you've got no excuse.
> The IDEs
I've been using IntelliJ IDEA since a year ago and for people reading the rant exposed by the article - IntelliJ IDEA 13 for Scala is everything you'd expect an IDE to be and more. I never had problems with renaming things. I never had problems with finding all usages of a type. IntelliJ IDEA 13 works flawlessly for viewing the inheritance hierarchy and I'm doing the Cake Pattern which is freakishly heavy on the traits ;-) Other languages only dream about such awesome IDE support.
> Overuse of Operator Overloading
He complains about SBT, but I thought we were talking about the language and the standard library. Pity that he doesn't exemplify an instance in which "+" is overused.
> Implicit
He mentions implicit parameters, but exemplifies with implicit conversions. Implicit conversions are in fact considered experimental and starting with Scala 2.10 the compiler will issue warnings in case you're using them without allowing "language.implicitConversions", being replaced with extension methods by means of implicit classes.
Yet, he doesn't mention Type Classes, the main use-case for implicit parameters. IMHO, I can't stand languages that do not have this form of ad-hoc polymorphism.
> How much of your time, as a software developer, do you spend doing stuff that is language agnostic?
That's setting up a straw-man. The problem we as software developers are trying to solve when picking new languages is one of gaining access to abstractions that are otherwise very difficult to express and use. Implement something like Iteratees in Java, a higher-level abstraction for safe asynchronous stream processing with back-pressure built in and you'll see what I mean.