Search code examples
javafunctional-programmingjava-8imperative-programmingdeclarative-programming

Translating Imperative Java to Functional Java (A Game)


I'm learning a lot more about Java 8 and its functional capabilities, and I wanted to do some more practice with it. Say, for example, I have the following imperative code which is for wrapping a circle around the bounds of the screen:

if (circle.getPosition().getX() > width + circle.getRadius()){
    circle.getPosition().setX(-circle.getRadius());
}else if (circle.getPosition().getX() < -circle.getRadius()){
    circle.getPosition().setX(width + circle.getRadius());
}
if (circle.getPosition().getY() > height + circle.getRadius()){
    circle.getPosition().setY(-circle.getRadius());
}else if (circle.getPosition().getY() < -circle.getRadius()){
    circle.getPosition().setY(height + circle.getRadius());
}
  1. How could I go about trying to "Functionalize" it? Maybe some pseudo-code? It seems to me that mutability and state seem inherent in this example.
  2. Is functional programming not a good fit for game development? I love the both, so I'm trying to combine them.

Solution

  • There is nothing inherent about the requirement for mutability in this example. The imperative approach is to modify an existing circles by applying side-effects which alter the state of an existing circle.

    The functional approach is to have an immutable data structure and create a function that takes data from the first structure and creates a new structure. In your example, a functional approach would have the circle being immutable, i.e. no setX() or setY() methods.

    private Circle wrapCircleAroundBounds(Circle circle, double width, double height) {
        double newx = (circle.getPosition().getX() > width + circle.getRadius()) ? -circle.getRadius() : width + circle.getRadius()
        double newy = (circle.getPosition().getY() > height + circle.getRadius()) ? -circle.getRadius() : height + circle.getRadius()
        return new Circle(newx, newy)
    }
    

    Using Java8's functional features, you could then imagine mapping a list of circles to wrapped circles:

    circles.stream().map(circ -> wrapCircleAroundBounds(circ, width, height))
    

    The imperative and functional approaches have different advantages, the functional approach, for example, is intrisicaly threadsafe because of the immutability so you should be able to more readily parallelise this kind of code. For instance, one could equally safely write:

    circles.parallelStream().map(circ -> wrapCircleAroundBounds(circ, width, height))
    

    I don't think that functional programming is necessarily badly suited to game development but, although it has be done, it's certainly not a standard approach so you won't get the same level of library support if you're using a functional language.

    As dfeuer states in his answer, Java's functional features are pretty primitive - you don't have support for algebraic data types, pattern matching, etc which will make it much easier to express problems in a functional style (at least once you get used to those idioms). I agree that at least reading a bit about Haskell, which has an excellent tutorial: http://learnyouahaskell.com/chapters would be a good way to get started. Unlike Scala, which is very much a multiparadigm language, you won't have OOP features to fall back on while you're learning the new style.