6

I've been convinced for awhile now that some strategies in functional programming are better suited to a number of computations (i.e immutability of data structures). However, due to the popularity of imperative languages, its unlikely that I will always be working on projects that are functionally implemented. Many languages (Matlab, Python, Julia) support using a functional paradigm, but it feels tacked on in many cases (looking at you, anonymous functions in Matlab). That being said, what are functional methods and strategies that I can use even in OOP/Imperative code? How can I write solid functional code that does not allow side effects even in languages that have mutable state and global variables?

6
  • 1
    While specific to perl, glance at Higher-Order Perl which is about applying many functional concepts into perl (a language rife with mutable state and global vars).
    – user40980
    Commented Jun 29, 2014 at 3:01
  • 7
    A word of caution: use of immutability in a functional language may have a low execution overhead because a functional compiler can make optimizations which avoids excessive copying. Use of immutability in an imperative language will incur a higher execution overhead, because you are explicitly forbidding the imperative compiler from making changes to objects. As a result, using immutability in imperative language means that each object update will require a copy. For non-trivial software, this copy overhead can be overwhelming. Choose your battle carefully, and don't be dogmatic.
    – rwong
    Commented Jun 29, 2014 at 3:26
  • 1
    @rwong I think that's not a matter of using the right compiler, it's a matter of using the right data structures. For example, in immutable code, you shouldn't use arrays, you should use singly linked immutable lists instead.
    – svick
    Commented Jun 29, 2014 at 5:26
  • 1
    @JörgWMittag Depends on perspective. A dozen CPU cores of garbage collector for 700 worker CPUs is excessive from the view of high-performance computing. Still, my main point is that immutability in functional language has to do with symbols and values (much as static single assignment does not imply an infinite number of registers), whereas in imperative language it constrains how data can be manipulated in memory.
    – rwong
    Commented Jun 29, 2014 at 18:48
  • 1
    That said, immutability has great value in multithreaded and asynchronous programming, so the ease of programming and safety issues can easily trump performance (unless the performance measurement shows otherwise).
    – rwong
    Commented Jun 29, 2014 at 18:54

3 Answers 3

13

Mutable state is easily avoidable using immutable objects. In the same way, global variables are usually the choice of the developer (or a poorly implemented framework).

This being said, you may also want to use additional functional paradigms in non-functional languages. It's all about the expressiveness of your code. If you see that a list comprehension in Python makes your code easy, go for it. If you find it more readable in a particular case to have an immutable structure used through method chaining, great.

But don't forget, some people find imperative variants easier than functional ones, even if it means writing three times the original LOC and risking to introduce subtle bugs. More importantly, some programmers don't understand the basic concepts. Many C# programmers struggle with lazy evaluation and are completely unable to explain why, if you take an IEnumerable<T> which returns a bunch of elements from the database and you first count the number of elements, then loop through them, there would be not one, but two queries to the database. I'm not even talking about monads and other concepts which are mostly unused in mainstream non-functional languages.

Also, don't worry that you won't work with functional languages. Non-functional languages tend to be inspired the last few years by functional ones. C# is a great example. Python and JavaScript are two other mainstream languages which tend to introduce more and more functional aspects in them. In essence, any language which support lazy evaluation and lambda expressions is a good candidate for functional-style code.

1
  • "In essence, any language which support lazy evaluation and lambda expressions is a good candidate for functional-style code.": Most mainstream languages do not support lazy evaluation natively. Did you mean that you can implement lazy evaluation using lambda expressions?
    – Giorgio
    Commented Jul 10, 2014 at 15:11
2

How can I write solid functional code that does not allow side effects even in languages that have mutable state and global variables?

The simple answer is, do not use global or mutable variables, or just because you can mutate them does not mean you have to.

Consider a class like this:

class ImmutableClass
{
    private int myImmutableField;

    public ImmutableClass(int fieldValue)
    {
        this.myImmutableField = fieldValue;
    }

    public int FieldValue { get { return this.myImmutableVariable; } }
}    

That class is immutable and even thread-safe. There is no way to mutate the state after it is constructed, even though the field is technically mutable.

2
  • Why not also make it technically immutable by using readonly?
    – svick
    Commented Jun 29, 2014 at 5:35
  • 5
    @svick - I deliberately left it out. I was trying to show that it doesn't matter if the language doesn't support immutability. Commented Jun 29, 2014 at 23:00
1

Prefer pure functions and immutable variables/objects.

Apart from that, keep in mind the limits and the conventions of the language you are using. Don't forget:

  • Readability. Your colleagues will find your non-idiomatic code harder to understand

  • Lack of tail call optimization

  • Lack of laziness

  • Lack of useful optimizations (ex. stream fusion)

  • Lack of convenient syntax (ex. for anonymous functions) etc...

In my experience, except for a few maps and filters here and there, pushing functional abstractions too far has never worked well. Functional programming is very powerful, but it doesn't mean it is the "absolute true way" in all contexts.