People say that Groovy is imperative, and Scala is more like a functional language.
But Groovy supports high order functions, and immutable variables so in theory, you can write functional code in it.
What specific features make it easier to write functional code in Scala than in Groovy?
You can write functional code in C! If being a functional language is simply a yes/no question, and the only requirement is "in theory you can write functional code in it", then pretty much every language I can think of is "functional".
To be clear, I'm going to say that when I talk about functional programming I'm primarily thinking about pure functional programming. I know some would object to this and say that use of features like higher order functions, closures, etc that have come from the functional world is the more important criteria, and that using these features and also using side effects is still functional programming. I consider things higher order functions and closures to be extremely valuable additions to imperative programming, but I don't consider adding them to your toolkit to move you over the line into a different kind of programming, so if we're going to have a grand distinction between "functional" and "not functional" then I think it's more useful for it to be a distinction between pure functional and imperative programming.
What it really comes down to in my experience is the "attitude" of the language and its ecosystem, rather than a specific set of technical features. It's about what's considered "normal" in a language, because that's what ends up informing the API design of the standard libraries and all the other third party code you'll be dealing with.
Scala is clearly designed with functional programming very much in mind. Even without reading statements to that effect by its designers, we can see it in language features like class fields being immutable unless you specifically ask for them to be mutable, case classes and pattern matching to make immutable plain old data structures easy to use, and for-comprehensions specifically aimed at letting you write looping code without using mutation (traditional for/while loops by definition cannot do anything useful without at least local side effects).
But what's almost more important is the standard library; because they expect you to be writing pure functional code, the libraries are explicitly designed to support this: all the important basic immutable collection types are there (there are mutable versions, but the immutable ones are the default), and just generally most of the functionality a standard library needs was implemented with the idea that programmers would want to access this functionality through an interface that fits well into functional code. The whole package is designed with functional programming highly in mind (though of course it's also designed not to get in the way when you don't want to do functional programming).
Groovy I've only just started learning at work, but my initial impressions are that its level of "functionalness" is similar to that of Python (which I've used extensively). It has higher order functions and lambdas, but much of the APIs you interact with were designed primarily for imperative use. It looks a little better than Python in that it has immutable collections1, but mutability is still the default, and so nobody thinks twice about making an interface that requires the uses of side effects.
If you are attempting to program functionally in a language (and library ecosystem) that isn't designed to cater for this, you find that you have to be ever vigilant to do so. The onus is on you to determine the subset of the interface available to you that you can use in pure code, fill in the gaps in whatever you think the basic functional toolkit is (maps, folds, option types, etc), wrap pure interfaces around things that refuse to let you use them without mutation, etc, etc. It's not that hard, but it is extra conceptual workload, and it definitely reduces some of the benefits of functional programming (error reduction chief among them).
That's what I consider to be the difference between a language that is "really functional" and one that merely "supports functional programming"; whether it makes functional programming easy or hard. And it's really more of a property of the APIs you're interacting with than language features per se.
1 As a digression, I find a basic set of immutable collections are far more important to supporting functional programming than immutable variables. And even then, it's not actually the immutability that's the issue, it's the API that allows you to use collections without mutating them (which is necessarily present if the collections are immutable). Unless you're in a language like Haskell that enforces purity everywhere it's always going to be a matter of programmer discipline to simply refrain from side effects. Choosing not to assign to mutable variables is easy; using a list or map without mutating it when the basic operations one would have on an immutable list or map are not present is much more of a pain.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With