2015-04-10 6 views
2

Я довольно новичок в Scala и функциональном программировании в целом, поэтому у меня есть немного проблем, обертывающих мою голову вокруг концепции частично прикладных функций и функций currying. Есть также довольно высокий шанс, что я собираюсь перепутать какую-то терминологию, поэтому все исправления приветствуются.Scala - частично и частично прикладные функции

Примечание: Я использую платформу Scala Play, но это скорее проблема Scala, чем проблема с Play.

Учитывая функцию как этот

def create(id: Long, userId: Long, label: String) 

Я получаю userId и label как (Int, String) кортеж и id как Long. В основном то, что я пытаюсь сделать, это передать id и кортеж функции одновременно.

Теперь, я прочитал, что прохождение кортежа функции можно сделать что-то вроде этого

scala> def f(a: Int, b: String) = 0 
f: (a: Int, b: String)Int 

scala> (f _).tupled((2, "Hello")) 
res0: Int = 0 

и что также можно частично применить функцию, как это

scala> def f(a: Int, b: String) = 0 
f: (a: Int, b: String)Int 

scala> val ff = f(_: Int, "Hello") 
ff: Int => Int = <function1> 

scala> ff(2) 
res1: Int = 0 

Поэтому моя первоначальная идея состояла в том, чтобы объединить эти две концепции примерно так:

это приводит к ошибке

<console>:10: error: _ must follow method; cannot follow h.type 
       (h _).tupled((1, "Hello")) 
      ^

Так что мой вопрос в первую очередь, почему это не работает, потому что для меня это имеет смысл. И во-вторых, как бы я мог добиться этого?

Благодарим за помощь!

ответ

3

Только не абстрагировать дважды: не делать redundand подчерк в h, как это уже функция после частичного применения:

scala> def create(a: Long, b: Int, c: String) = 0 
create: (a: Long, b: Int, c: String)Int 

scala> val h = create(1, _: Int, _: String) 
h: (Int, String) => Int = <function2> 

scala> h.tupled((1, "Hello")) 
res0: Int = 0 

Более глубоко, tupled определяется на функциях (означает object из Function, как и Int => String), а не на методах (например, def f(i: Int): String) - поэтому иногда вам нужно преобразовать метод в функцию - это называется eta-expand (или эта-абстракция в целом). Когда вы выполняете частичное применение - эта-расширение выполняется автоматически (у вас уже есть (Int, String) => Int), поэтому вам не нужно делать это дважды.

См. The differences between underscore usage in these scala's methods, Difference between method and function in Scala для получения дополнительной информации.

+0

Спасибо, это работает! Похоже, мне еще многое предстоит узнать о Scala. – gry

+0

Добро пожаловать! В Scala всегда есть чему поучиться :) – dk14