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.