scalapartialfunction

Composition of partial functions to reduce code length


I want to compose a functions in a specific way to reduce code length

For instance composing a simple add function as such :


    val add3 = (a: Int, b:Int) => (c:Int) => a+b+c

    val composed = (a:Int, b:Int) => n:add3(a, b) => n(1) + n(2) + n(3)

That would be very useful so that I don't have to pass a and b as parameters every time.

Is there a way of doing that in Scala ?


Solution

  • I'm a bit confused by these notations, like @Dima... But, I've been through this kind of ... trying to handle partial function by writing down intuitive way to... comprehend them? Is that what you're doing? So I'll try to interpret you step by step.

    First, we have to be clear about add3

    This code you give, maybe just as scratch to understand I guess, won't compile in scala:

    val add3 = (a: Int, b:Int)(c:Int) => a+b+c
    

    Indeed, we get in a REPL:

    error: not a legal formal parameter. Note: Tuples cannot be directly destructured in method or function parameters. Either create a single parameter accepting the Tuple1, or consider a pattern matching anonymous function: `{ case (param1, param1) => ... } val add3 = (a: Int, b:Int)(c:Int) => a+b+c ^

    But I may have got the idea you wanted to suggest...

    add3 is either a method like:

    def add3Method (a: Int, b:Int)(c:Int) = a+b+c
    

    which can be then partially applied:

    val add3 = add3Method _
    

    Or it can directly be a function like:

    val add3 = (a: Int, b:Int) => (c: Int) => a+b+c
    

    Either way, it give a function of type (Int, Int) => Int => Int. Is that what you want?

    Then we have to be clear about "composed"

    This code you give, maybe just as scratch to understand I guess, won't compile in scala neither:

    val composed = (a:Int, b:Int) => n:add3(a, b) => n(1) + n(2) + n(3)
    

    But I may... Well, at least, might have got the idea you wanted to suggest too...

    (a) closure?

    The way you express it make me think is like a closure which would mean ultimately that composed has a type (Int, Int) => Int. Is that what you meant?

    (b) a function which takes kind of a add3?

    Or, you just want add3 to be just any function of the same type to pass to composed I assume is (Int, Int) => Int => Int. Is that what you meant?

    Then, you have some ways to define "composed"

    Either by mapping or by an intermediate variable.

    closure, intermediate variable way

    val composedCI = (a:Int, b:Int) => { val n = add3(a,b); n(1) + n(2) + n(3)}
    

    closure, mapping way

    val composedCM = (a:Int, b:Int) => (1 to 3).map(add3(a,b)).sum
    

    taking as argument add3, intermediate variable way

    val composedTI = (a:Int, b:Int) => (myAdd3asAnArg: (Int, Int) => Int => Int) => { val n = myAdd3asAnArg(a,b); n(1) + n(2) + n(3) }
    

    taking as argument add3, mapping way

    val composedTM = (a:Int, b:Int) => (myAdd3asAnArg: (Int, Int) => Int => Int) => (1 to 3).map(myAdd3asAnArg(a,b)).sum
    

    Using "composed"

    println(composedCM(4,5))
    println(composedCI(4,5))
    println(composedTM(4,5)(add3))
    println(composedTI(4,5)(add3))
    

    Will give

    33
    33
    33
    33
    

    Hope it helps...