#scala
Вопрос:
У меня есть следующий код
object Test {
def bar: String => Double = {
foo[String](_.toDouble)
}
def baz: (Double, Double) => Double = {
foo[(Double, Double)] {
case (d1, d2) => d1 d2
}
}
def foo[T](f: T => Double): T => Double = {
f
}
}
бар работает без проблем, как и ожидалось. Я пытаюсь добиться аналогичной работы с функцией параметра mutli в качестве одного из входных данных, но это не работает, потому что scala рассматривает foo[(Double, Double)]
его как тип кортежа, а не как параметр функции. Есть ли какой-нибудь способ сообщить scala, что это параметр функции, а не кортеж?
Комментарии:
1. Ну, есть простое исправление
baz
типа:((Double, Double)) => Double
это функция одного аргумента (который является кортежем) . — Другой путь невозможен, АФАИК.2. Это просто очень упрощенный пример в данном случае, ради самого вопроса. На самом деле в foo будет куча логики, которая дополнит исходную функцию
Ответ №1:
Я думаю, что причина, по которой это не сработало для вас, заключается в том, что у вас нет доступа к двум отдельным аргументам baz
метода, которые необходимо упаковать в кортеж перед вызовом foo
. (Я думаю, что есть некоторые дискуссии о возможности преобразования списков параметров в/из кортежей, но в настоящее время это невозможно.) Попробуйте вместо этого использовать это определение:
object Test {
def bar: String => Double = {
foo[String](_.toDouble)
}
def baz: (Double, Double) => Double = {(p1, p2) =>
foo[(Double, Double)] {
case(d1, d2) => d1 d2
}((p1, p2))
}
def foo[T](f: T => Double): T => Double = f
}
Если я правильно понимаю ваши намерения, это будет использоваться так (в Scala REPL):
scala> Test.bar("5.0")
val res0: Double = 5.0
scala> Test.baz(3.0, 5.0)
val res1: Double = 8.0
Однако это кажется немного запутанным. Если bar
и baz
хранить ссылки на методы, то они должны быть объявлены val
, а не def
:
object Test {
val bar: String => Double = {
foo[String](_.toDouble)
}
val baz: (Double, Double) => Double = {(p1, p2) =>
foo[(Double, Double)] {
case(d1, d2) => d1 d2
}((p1, p2))
}
def foo[T](f: T => Double): T => Double = f
}
Который имеет тот же синтаксис использования и выдает тот же результат:
scala> Test.bar("5.0")
val res2: Double = 5.0
scala> Test.baz(3.0, 5.0)
val res3: Double = 8.0
Но даже это все равно довольно неуклюже. bar
является ссылкой на функцию , которая принимает a String
и возвращает a Double
, в то время baz
как является ссылкой на функцию, которая принимает два Double
s и возвращает a Double
. Так почему бы просто не создавать bar
и baz
методы сами по себе, а не ссылки на методы? Это привело бы к:
object Test {
def bar(s: String): Double = foo[String](_.toDouble)(s)
def baz(p1: Double, p2: Double): Double = {
foo[(Double, Double)] {
case(d1, d2) => d1 d2
}((p1, p2))
}
def foo[T](f: T => Double): T => Double = f
}
который опять же используется таким же образом:
scala> Test.bar("5.0")
val res4: Double = 5.0
scala> Test.baz(3.0, 5.0)
val res5: Double = 8.0
И, конечно, foo
само по себе излишне, поскольку оно идентично его аргументу. Так что все это можно было бы написать гораздо проще, как просто:
object Test {
def bar(s: String): Double = s.toDouble
def baz(p1: Double, p2: Double): Double = p1 p2
}