# What's the benefit of separating specialised data from behaviour in an algorithm?

Functional programming strongly suggests to separate data from behaviours (functions). However, I can't see the benefit of this for an algorithm's implementation intrinsically tied with particular settings data.

For example, suppose there's a trait `LagrangeAlgorithmOOP` with immutable data being the algorithmic settings, problem specification and dependencies on helpers. The trait's methods all use this data to find a problem solution. Their implementation is specific to the algorithm's type. Almost none of would make sense as a stand-alone function.

Specifically, suppose we refactor

`````` trait LagrangeAlgorithOOP {

val settings: SettingsLagrange
val problem: ConstrainedProblem
val innerMinimiser: Minimiser
val penaltiesFunction: ConstraintPenaltiesFunction

def iteration( s: StateLagrange):  Either[String, StateLagrange]
def lagrangeFunction( lams: Lambdas, pens: Penalties): AugmentedLagrangianFunction
def estimateLambdas( pens: Penalties, las: Lambdas, cons: ConstraintValues): Option[Lambdas]
def updatePenaltiesHistory( h: HistoryLagrange): HistoryLagrange
}
``````

into this

``````case class LagrangeData(settings: SettingsLagrange,
problem: ConstrainedProblem,
innerMinimiser: Minimiser,
penaltiesFunction: ConstraintPenaltiesFunction)

trait LagrangeAlgorithmFUN {

def iteration(d: LagrangeData, s: StateLagrange):  Either[String, StateLagrange]
def lagrangeFunction(d: LagrangeData, lams: Lambdas, pens: Penalties): Lagrangian
def estimateLambdas(d: LagrangeData, pens: Penalties, old: Lambdas, cons: ConstraintValues): Option[Lambdas]
def updatePenaltiesHistory(d: LagrangeData,  h: HistoryLagrange): HistoryLagrange
}
``````

The latter case introduces a data class and an extra parameter into each method. (Instead, I could use a Reader monad, which would, however, also require monad transformers.)

Questions:

1. What is the best refactoring of this algorithm to an FP style?
2. Could some half-way approach work better: eg, to leave some of the data fields in the trait?
3. Is there much difference between the original and refactored versions?
4. What is the benefit of refactoring to FP-style in this case?

Note: I agree with many points in the related post Why is "tight coupling between functions and data" bad?. Still I'm not sure how this applies to immutable settings data that is intrinsic to the functions implementing the algorithm.

• This is very broad. Do you have a specific concern you'd like to address? Oct 16, 2018 at 17:33
• @RobertHarvey I'm happy to modify the question to make it more specific, and welcome any advice on that. Originally I programmed a technical algorithm as an OOP class. Generally, I'm trying to switch to FP-style programming. However, for the specific algorithm, I'm stuck deciding whether to refactor it to FP, and even whether there's any real difference between the two approaches. Oct 16, 2018 at 18:07
• You might be interested in this article: cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.pdf Oct 16, 2018 at 20:31
• @RobertHarvey It's a very interesting article indeed! To use an example from its section 4.1, what I can't understand is the essential difference between the "OOP" - style function `repeat (o.iteration(s))` and the "FP" - style function `repeat (iteration(d, s))`, where `o: LagrangeAlgorithm`, `s: State` and `d: LagrangeData`. If there is no essential difference, then both code snippets in the post are essentially equivalent, aren’t they? Oct 16, 2018 at 21:57
• I consider things like immutability, declarative programming style, recursion, lambda expressions, and functional composition more important than the underlying nuances of loops and data structures. Ultimately, every program resolves to a series of machine instructions and a collection of mutable data, regardless of the overarching programming paradigms in use. Oct 16, 2018 at 22:13

Keep in mind that without inheritance the difference between `foo.bar()` and `bar(foo)` is purely a syntactic one. When you add the fact that modern OOP practice strongly favors using inheritance only for interfaces (which corresponds closely to FP type classes) you will see that there is a lot of convergence between best practices in both OOP and FP. Given this, we now see that in the "best practices" cases, `foo.bar()` and `bar(foo)` (or in an ML language `(bar foo)`) is merely a syntactic difference even taking inheritance/type classes into account.
So in answer to your questions, the difference is largely syntax but IMO the OO style of `obj.func()` allows for a more natural chaining of function calls. Instead of `c(b(a))`, I can do `a.b().c()` which makes the order of operations more clear because it reads in a left to right order.
The counter argument is that the OO call style necessarily gives precedence to one particular parameter of the function over the others which is true and a good reason to avoid the style if there is no natural preference inferred by the algorithm. For example when comparing two objects for equality, `a.equals(b)` just feels silly compared to `equals(a, b)` because there is no reason to preference `a` over `b` in that context. All OO languages that I know of, with the exception of Java, allow for "free" functions that follow the more functional style of not giving precedence to one particular parameter. It's even doable in Java through the use of so-called "static" functions that exist inside a class, but don't actually have a implicit `this` or self parameter.