(данные: любые) => println (данные) против данных: любые => println (данные) - PullRequest
0 голосов
/ 24 сентября 2018

Я наткнулся на следующий код scala:

val x = 10 match {
  case _: Int => data: Any => println(data) // no issue
}

val y = data: Any => println(data) //compiling error

В предложении о совпадении мне не нужно писать data: Any => println(data) как (data: Any) => println(data)

Но в val y = data: Any => println(data), Я должен написать как val y = (data: Any) => println(data).Почему?

Ответы [ 2 ]

0 голосов
/ 24 сентября 2018

Соответствующее правило:

Если в качестве выражения результата блока отображается анонимная функция (x: T) => e с одним типизированным параметром, ее можно сократить до x: T => e.

Первый случай (case _: Int => data: Any => println(data)) удовлетворяет этому условию, второй - нет.Но вы можете переписать его на

val y = { data: Any => println(data) }
0 голосов
/ 24 сентября 2018

Разница в одном - это оператор case, а шаблон соответствует другому - оператор присваивания.В первом случае мы, по существу, возвращаем значение (результат) правой части => в виде блока операторов, как показано ниже.

scala> {data: Any => println(data)}
res0: Any => Unit = $$Lambda$1141/1699449247@71468613

scala> data: Any => println(data)
<console>:1: error: ';' expected but '=>' found.
       data: Any => println(data)
scala> val x = 10 match {
     |   case _: Int => val y = 56;data: Any => println(data) // no issue
     | }
x: Any => Unit = $$Lambda$1171/115016870@8f374de

Приведенные выше операторы учитывают все, что после => будет рассматриваться как оператор statement block в case, но во втором случае (присваивание, т. Е. Присвоение значения функции) это не,Следовательно, скобки вокруг объявления параметров необходимы.

РЕДАКТИРОВАТЬ:

Хотя я дал вышеупомянутый ответ в соответствии с моим наблюдением в scala REPL, я также думал, что он не будетчетко ответить на вопрос почему?часть вопроса задала.Кроме того, я провел еще несколько исследований о том, как ведет себя компилятор scala после исследования точного сообщения об ошибке, которое мы получаем, когда набираем

val y = data:Int => println(data)

scala> val y = data:Int => println(data)
<console>:1: error: ';' expected but '(' found.
       val y = data:Int => println(data)

Это, вероятно, связано с особенностью вывода типа scala в val y.

В Scala type может быть указан как явно, где это требуется, так и компилятор Scala может неявно infer type, где это возможно.Здесь type of y должен быть выведен компилятором scala в первом случае, потому что он не был явно объявлен здесь.Именно из-за этой попытки компилятора появилось указанное выше сообщение об ошибке.

Теперь, если мы хотим явно объявить type, в scala есть two ways:

Firstway : val y : Int = 5

Второй путь : val y = 5:Int

Оба вышеприведенных оператора присваивания имеют valid в шкале.

Поскольку в нашем конкретном операторе присваивания, т. Е.

val y = data:Any => println(data)

, мы заставляем scala вывести type of y в Второй способ , показанный выше.

Чтобы вывести type of y, компилятор scala пытается, как объяснено ниже:

Здесь компилятор предполагает, что data является функцией, определенной где-то перед этой строкой кода, и функция имеетвведите Int=>println(data).Затем он проверяет правильность этого типа.Компилятор определил, что Int является допустимым типом, а println(data) - нет, поскольку допустимые имена типов не могут содержать скобок ('(' char), и именно поэтому error message, как указано выше.

Если мывставьте правую часть вышеупомянутого оператора присваивания в блоке т.е.между фигурными скобками или помещением объявления параметра в круглые скобки, не будет проблем с выводом type of y.

или использованием First way , мы можем сделатьэто для компиляции без фигурных скобок,

val y : Any => Unit = data =>println(data)


scala> val y : Any => Unit = data =>println(data)
y: Any => Unit = $$Lambda$1059/1854873748@799c8758

Надеюсь, это объясняет, почему часть вопроса.

...