Я вижу, что все, кажется, зацепились за второй фрагмент, поэтому я отвечу на первый:
val upperLeftX = poly.points.reduceLeft(Math.min(_.x, _.x))
Вы предполагали, что это означает:
val upperLeftX = poly.points.reduceLeft((a, b) => Math.min(a.x, b.x))
Однако это не так, как подчеркивание. Есть много значений, чтобы подчеркнуть, но два из них имеют отношение здесь.
Во-первых, это может означать частичное применение функции. Например, Math.min(_, 0)
будет частично применять параметры к min
и возвратит функцию, которая применяет остальные. Другими словами, это эквивалентно x => Math.min(x, 0)
, игнорируя аннотации типов. В любом случае, это значение только применяется, если подчеркивание само по себе находится вместо одного (или нескольких) параметров.
Однако в вашем примере это не так, потому что вы добавили .x
после подчеркивания. Если подчеркивание появляется в каком-либо выражении, таком как вызов метода в вашем примере, тогда это подчеркивание является заполнителем для параметра в анонимной функции.
В этом втором значении особенно важно понимать границы анонимной функции. В частности, анонимная функция будет разделяться самой внутренней скобкой или фигурными скобками, которые ее заключают, или любой запятой.
Теперь применение этого правила к выражению в первом фрагменте означает, что компилятор видит snipper следующим образом:
val upperLeftX = poly.points.reduceLeft(Math.min(a => a.x, b => b.x))
Итак, здесь есть две проблемы. Во-первых, вы передаете две функции в min
вместо двух двойных. Во-вторых, поскольку min
не ожидает получения функций, компилятор не может определить тип этих функций. Поскольку вы не предоставили никакой информации о типах a
и b
выше, она жалуется на это.
Если вы предоставили такие типы, сообщение об ошибке будет выглядеть примерно так:
<console>:6: error: type mismatch;
found : Int
required: ?{val x: ?}