#scala #string-interpolation
#scala #строка-интерполяция
Вопрос:
Почему в REPL это выражение завершается ошибкой:
List("a", "b").foreach { System.out.println(s"Valor=$_") }
с этой ошибкой:
<console>:1: error: unclosed string literal
в то время как этот другой выполняется успешно:
List("a", "b").foreach { x => System.out.println(s"Valor=$x") }
Я подозреваю, что переменная «_» не поддерживается.
Это ошибка или так задумано?
Ответ №1:
Сообщение об ошибке, которое вы показываете, отличается от того, что я получаю с Scala 2.11.1:
scala> List("a", "b").foreach { System.out.println(s"Valor=$_") }
<console>:1: error: error in interpolated string: identifier or block expected
List("a", "b").foreach { System.out.println(s"Valor=$_") }
^
<console>:1: error: ')' expected but '}' found.
List("a", "b").foreach { System.out.println(s"Valor=$_") }
^
Чтобы ответить на ваш вопрос сейчас. SIP-11, который определил интерполяцию строк для Scala, запрещает идентификаторы, начинающиеся с чего-либо еще, кроме буквы. Это может быть немного чересчур ограничительным, но это имеет смысл для специального _
идентификатора, если учесть десугаринг интерполированных строк.
Ваш пример:
List("a", "b").foreach { System.out.println(s"Valor=$_") }
Было бы отменено это:
List("a", "b").foreach { System.out.println(StringContext("Valor=", "").s(_)) }
Что ясно показывает, что это _
не может быть связано с параметром функции, переданной foreach
. Вот сообщение об ошибке, полученное при попытке выполнить десугаринг:
scala> List("a", "b").foreach { System.out.println(StringContext("Valor=", "").s(_)) }
<console>:8: error: type mismatch;
found : Unit
required: String => ?
List("a", "b").foreach { System.out.println(StringContext("Valor=", "").s(_)) }
Короче говоря, это происходит из-за способа десугаринга.
Комментарии:
1. Спасибо, теперь я понимаю. Сообщение об ошибке, которое я показал, относится к Scala 2.10.
Ответ №2:
Ошибка вводит в заблуждение, но основная проблема здесь заключается в том, что вы передаете анонимную функцию в println:
Список («a», «b»).foreach { System.out.println(s»Valor=$_») }
эквивалентно
Список («a», «b»).foreach { System.out.println(x => s»Valor=$ x») }
У вас уже есть одна рабочая версия, другая версия, которая показывает, что _ определенно поддерживается:
Список («a», «b»).foreach (System.out println «Valor=» _)
Вышеуказанный порядок вычислений приводит к тому, что он эквивалентен:
Список («a», «b»).foreach (x => System.out печатает «Valor=» x)