"andThen" and "compose" methods for functions with more than 1 argument

Now they are exist for Function1 only, but it is useful to have them for any Function, since Tuples are converted to function arguments in Scala 3.

The logic is: if someFunction return type is a some Tuple(T1, T2…) , you can compose it with otherFunction, which has (T1, T2…) arguments with the same types, as returned Tuple from someFunction.

For example, if

val f1: (T1, T2) => (T3, T4, T5)
val f2: (T3, T4, T5) => R

then

f2 compose f1

or

f1 andThen f2

gives you the function

(x1: T1, x2: T2) => R = f2( f1(x1, x2) )

It has some symmetry with “function-chain call” proposal.

1 Like

FunctionN#andThen(g: Function1) and Function1#compose(g: FunctionN) sound more useful to me than the other varieties that you could tuple or curry to get composition for.

I have had the intent to make a PR for those when I needed them in practice for years, but it seems it just never comes up.

1 Like

Easiest example is 2d-point operations without declaration of class Point (it makes them independent of particular class and, this way, more general).

def move(shiftX: Int, shiftY: Int)(x: Int, y: Int) = (x + shiftX, y + shiftY)
def drawPoint(implicit canvas: Canvas) = (x: Int, y: Int) =>
   {canvas.point(x, y); (x, y)}

val movements = 
  move(1,  1) andThen 
    drawPoint andThen 
    move(-5, 10) andThen 
    drawPoint andThen 
    move(10, 0)

movements(100, 100)

ignoring the canvas, in scala 3, you have to tuple the first one, and then it’ll flow along:

val movements =
  move(1, 1).tupled andThen
    drawPoint andThen
    move(-5, 10) andThen
    drawPoint andThen
    move(10, 0)

because you have auto-tupling for infix operators.