Scala странная неявная ошибка преобразования бокса

Может кто-нибудь сказать мне, почему следующее не работает?

object TestObject {
    def map(f: (Double, Double) => Double, x2: Array[Double]) = {
        val y = x2.zip( x2 )
        val z = y.map(f)
        z
    }
}

Выдает эту ошибку:

type mismatch; found : (Double, Double) => Double required: ((Double, Double)) => ?

person OutNSpace    schedule 14.06.2013    source источник


Ответы (3)


В этом фрагменте f — это функция, принимающая два параметра Double и возвращающая Double. Вы пытаетесь вызвать f, передав один аргумент типа Tuple2[Double,Double]. Вы можете исправить это, в первую очередь изменив тип f:

object TestObject {
    def map(f: ((Double, Double)) => Double, x2: Array[Double]) = {
        val y = x2.zip( x2 )
        val z = y.map(f)
        z
    }
}

Вы также можете объявить его как f: Tuple2[Double, Double] => Double, чтобы было понятнее (это полностью эквивалентно).

И наоборот, вы можете изменить свой вызов следующим образом:

object TestObject {
    def map(f: (Double, Double) => Double, x2: Array[Double]) = {
        val y = x2.zip( x2 )
        val z = y.map(f.tupled)
        z
    }
}

tupled автоматически преобразует вашу функцию (Double, Double) => Double в функцию Tuple2[Double, Double] => Double. Однако имейте в виду, что преобразование будет выполняться при каждом вызове TestObject.map.

person Régis Jean-Gilles    schedule 14.06.2013
comment
Или оставьте подпись и используйте val z = y.map(f.tupled) - person 0__; 14.06.2013
comment
также вместо val z = y.map(f.tupled); z; просто используйте y.map(f.tupled). Выглядит намного чище - person Martijn; 14.06.2013

Существует тонкая разница между

f: (Double, Double) => Double // two Double arguments -> Double

а также

f: ((Double, Double)) => Double // one Tuple2[Double, Double] argument -> Double

y является Array[(Double, Double)], поэтому он ожидает метод, который принимает кортеж и возвращает что-то, но первый f, определенный выше, не соответствует этому.

Вы можете сделать y.map(f.tupled), чтобы перейти от первого ко второму, или изменить подпись f.

person gourlaysama    schedule 14.06.2013

Я думаю, ваша проблема в том, что f ожидает два аргумента Double, но вы пытаетесь передать ему один кортеж: f((1, 2)) отличается от f(1, 2).

Измените тип f на ((Double, Double) => Double), и он должен работать.

person Nicolas Rinaudo    schedule 14.06.2013