Scala синтаксис метода карты
Ниже приведен код http://www.scalaclass.com/book/export/html/1, чтобы сделать матричный точечный продукт.
Я не могу понять синтаксис между фигурными скобками.
- Почему используются фигурные скобки, а не круглые скобки метода?
- Это анонимный метод?
- Что такое._1 и._2?
Спасибо.
type Row = List[Double]
type Matrix = List[Row]
def dotProd(v1:Row, v2:Row) =
v1.zip(v2).map{ t:(Double, Double) => t._1 * t._2 }.reduceLeft(_ + _)
Ответы
Ответ 1
- Почему используются фигурные скобки, а не круглые скобки метода?
Некоторые люди предпочитают использовать фигурные скобки, когда параметр является анонимной функцией. С одной стороны, фигурные скобки позволяют сопоставлять анонимные функции, а в скобках - нет. В этом конкретном примере нет необходимости в фигурных скобках.
Вот пример, где требуются фигурные скобки (из-за соответствия шаблона case
):
def dotProd(v1:Row, v2:Row) =
v1.zip(v2).map{ case (a, b) => a * b }.reduceLeft(_ + _)
Обратите внимание, что вышеприведенная функция выполняет то же самое, что и вопрос в вопросе, несколько иначе.
- Есть ли
t
анонимный метод?
Нет, это параметр. Точно так же, как v1
и v2
являются параметрами для dotProd
, t
является параметром для анонимной функции, передаваемой в map
.
Методы на t
. Параметр t
был определен как кортеж (в частности, Tuple2[Double, Double]
, который может быть записан как (Double, Double)
), а кортежи позволяют извлекать каждый член кортежа с помощью таких методов: _1
, _2
, _3
и т.д.
A Tuple2
имеет только _1
и _2
, конечно. Обратите внимание, что первый параметр _1
, а не _0
, из-за влияния других функциональных языков.
В любом случае метод zip
преобразует Row
(List[Double]
) в List[(Double, Double)]
. Метод map
принимает функцию, которая преобразует элементы списка (которые являются (Double, Double)
кортежами) во что-то другое.
Ответ 2
В этом конкретном случае фигурные скобки не имеют преимущества по сравнению с простым старым синтаксисом, но в целом сладкая вещь об использовании фигурных скобок заключается в том, что они позволяют писать выражения, соответствующие шаблону внутри map ...
:
поэтому я могу переписать этот
.map{ t:(Double, Double) => t._1 * t._2 }
в этот
.map{ case(a: Double, b: Double) => a*b }
но это не скомпилируется:
.map( case(a: Double, b: Double) => a*b )
._ 1,._2 предоставляет доступ к первому, второму,... N-элементу N-кортежа, как сказал Ли.
Ответ 3
Вы можете найти очень хороший ответ на различия между фигурными скобками {} и круглыми скобками() в этом вопросе: Какая формальная разница в Scala между фигурными скобками и скобками и когда они должны использоваться?
Для _1, _2 см. Значение знака _2 в Scala языке.
И да, t:(Double, Double) => t._1 * t._2
- анонимная функция (фактически не метод). Разница между методом и функцией в Scala
Ответ 4
Кудрявые скобки обозначают анонимную функцию с типом Tuple2[Double,Double] => Double
. Аргументу дается локальное имя t
, поэтому t
является кортежем из двух двухлокальных. t._1
относится к первому элементу и t._2
второй.
Следовательно, map
дает список элементарных произведений компонентов двух векторов, а reduceLeft
суммирует эти произведения для вычисления точечного произведения.