1

I have the following pure function (f2 and f3 are pure too):

class X { 
 def f1(arg: Type1): Type2 = {
 val x = f2(arg)
 val y = f3(x)
 y
 }
 def f2...
 def f3...
}

Now, I would like to move f2 and f3 and can think of 2 options to do so. Wondering if one is more functional than the other?

Option 1

Move f2 and f3 to a new trait and mix the new trait into X like so:

trait T {
 def f2... // with implementation
 def f3...
}
class X extends T {
 def f1... // same implementation as earlier
}

Option 2

Move f2 & f3 to a new trait (but with the implementation in a class) and dependency inject the trait into X like so:

@ImplementedBy(classOf[T1Impl])
trait T {
 def f2... // No implementation
 def f3... 
}
@Singleton
class TImpl extends T {
 override def f2... // Implementation here
 override def f3... 
}
class X @Inject() (t: T) {
 def f1 ... = {
 val x = t.f2(arg)
 val y = t.f3(x)
 y
 }
}

One half of me thinks option 1 is more functional (involving no OO baggage). The other half (with OOP/Java history I come from) screams that using inheritance for code sharing is a bad idea. Particularly if X and T are un-related then X extends T (X is a T) makes the code look contrived.

Using composition makes the code look more natural (X has a T) but is it less functional?

asked Jan 15, 2018 at 2:36
5
  • 11
    What makes you think any of this code is functional? Commented Jan 15, 2018 at 4:05
  • 1
    Your question is about how to separate methods into classes or traits. I think this is unrelated to "functional" or not, so I would say all options are equally functional. Which option is best is a different question. Commented Jan 15, 2018 at 8:29
  • i'd suggest that the functional approach would probably involve passing f2 and f3 in as functions, but I think it will rather depend on what they all do. fir instance at the moment f1 = flip const - but i'm guessing your real f1 doesnt Commented Jan 15, 2018 at 9:09
  • actually misread it composes f2 and f3 but same point stands Commented Jan 15, 2018 at 9:28
  • 1
    might also like this blog.ploeh.dk/2017/01/27/… Commented Jan 15, 2018 at 9:29

1 Answer 1

6

Functional programming is about minimizing states and all that comes with that. Any and all information that would normally be provided by class members is instead provided through parameters.

It stands to reason that using classes in general is somewhat not functional as it allows you to have states. However, if you are avoiding class members, it makes no difference if you inherit or use traits as pure functions will continue to behave in the same way throughout the program.

In other words, the only reason you should think that you're moving away from a functional design is when the behavior of a function/method changes based on information which doesn't come from the parameters themselves or if the result of a given function/method cannot be unconditionally predetermined by the parameters passed.

answered Jan 15, 2018 at 8:24

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.