Ошибка использования составной функции в дальнейшей композиции функций - PullRequest
0 голосов
/ 13 мая 2019

Мне трудно понять, почему я не могу использовать составную функцию и написать новую.Например: у меня есть две функции f и g, и я создаю составную функцию composed1 из них.Я попытался скомбинировать составную с четвертой функцией lastOne, и это не удалось.

Я хочу создать две составные функции, а для второй - есть ли способ повторно использовать первую составную функцию?

scala> def f(x: Int)(y: Int) = {
     | x + y
     | }
f: (x: Int)(y: Int)Int

scala> def g(a: Int)(b: Int) = {
     | a + b
     | }
g: (a: Int)(b: Int)Int

scala> def composed1(a: Int, b: Int) = {
     | f(a) _ andThen g(b)
     | }
composed1: (a: Int, b: Int)Int => Int

scala> composed1(2, 2)(5)
res1: Int = 9

scala> def lastOne(l: Int)(x: Int) = {
     | l + x
     | }
lastOne: (l: Int)(x: Int)Int

scala> def composed2(a: Int, b: Int, c: Int) = {
     | composed1(a, b) _ andThen lastOne(c)
     | }
<console>:14: error: _ must follow method; cannot follow Int => Int
       composed1(a, b) _ andThen lastOne(c)
                ^
<console>:14: error: missing argument list for method lastOne
Unapplied methods are only converted to functions when a function type is expected.
You can make this conversion explicit by writing `lastOne _` or `lastOne(_)(_)` instead of `lastOne`.
       composed1(a, b) _ andThen lastOne(c)

Когда я использую их все вместе, это работает

scala> def test(x: Int, y: Int, z: Int) = {
     | f(x) _ andThen g(y) _ andThen lastOne(z)
     | }
test: (x: Int, y: Int, z: Int)Int => Int

scala> test(2, 2, 4)(5)
res9: Int = 13

1 Ответ

3 голосов
/ 13 мая 2019

f()() и g()(), как вы их определяете, являются методами. Методы не являются функциями , но методы могут быть преобразованы в функции через " eta extension ". Один из способов сделать это - использовать подчеркивание вместо переданного параметра.

andThen() - это метод Function trait , который принимает функцию в качестве аргумента и возвращает новую функцию. Выглядит так, как будто вы также можете использовать метод в качестве переданного аргумента, но он молча переводится в состояние Function.

Так что composed1() выглядит как метод, но на самом деле это Function, потому что это то, что возвращает andThen(), и вы не можете применить расширение eta подчеркивания к Function. Работает только на методах.

В качестве эксперимента превратите f()() в Function, который делает то же самое ...

def f :Int => Int => Int = (x: Int) => (y: Int) => x + y

... сейчас composed1() не скомпилируется.

Итак, теперь, когда мы знаем, что composed1() - это Function, как мы можем получить то, что мы хотим от composed2()? Просто. Пропустить подчеркивание.

def composed2(a: Int, b: Int, c: Int) =
  composed1(a, b) andThen lastOne(c)

composed2(2, 2, 4)(5)   //res0: Int = 13
...