Интерполяция строк и переменная-заполнитель

#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)