Scala Language
Интерполяция строк
Поиск…
замечания
Эта функция существует в Scala 2.10.0 и выше.
Интерпретация Hello String
Интерполятор s позволяет использовать переменные в строке.
val name = "Brian"
println(s"Hello $name")
печатает «Hello Brian» на консоль при запуске.
Форматированная интерполяция строк с помощью интерполятора f
val num = 42d
Распечатайте два десятичных знака для num
используя f
println(f"$num%2.2f")
42.00
Печать num
использованием научной нотации с помощью электронной
println(f"$num%e")
4.200000e+01
Печать num
в шестнадцатеричном с
println(f"$num%a")
0x1.5p5
Другие строки формата можно найти на странице https://docs.oracle.com/javase/6/docs/api/java/util/Formatter.html#detail
Использование выражения в строковых литералах
Вы можете использовать фигурные скобки для интерполяции выражений в строковые литералы:
def f(x: String) = x + x
val a = "A"
s"${a}" // "A"
s"${f(a)}" // "AA"
Без фигурных скобок scala будет только интерполировать идентификатор после $
(в этом случае f
). Поскольку нет никакого неявного преобразования из f
в String
это исключение в этом примере:
s"$f(a)" // compile-time error (missing argument list for method f)
Пользовательские строковые интерполяторы
В дополнение к встроенным можно определить пользовательские строковые интерполяторы.
my"foo${bar}baz"
Распространяется компилятором на:
new scala.StringContext("foo", "baz").my(bar)
scala.StringContext
не имеет my
метода, поэтому он может быть обеспечен неявным преобразованием. Обычай Интерполятор с таким же поведением , как и встроенный s
интерпол затем будет осуществляться следующим образом :
implicit class MyInterpolator(sc: StringContext) {
def my(subs: Any*): String = {
val pit = sc.parts.iterator
val sit = subs.iterator
// Note parts.length == subs.length + 1
val sb = new java.lang.StringBuilder(pit.next())
while(sit.hasNext) {
sb.append(sit.next().toString)
sb.append(pit.next())
}
sb.toString
}
}
И интерполяция my"foo${bar}baz"
будет обессоливать:
new MyInterpolation(new StringContext("foo", "baz")).my(bar)
Обратите внимание, что нет никаких ограничений на аргументы или возвращаемый тип функции интерполяции. Это приводит нас к темному пути, где синтаксис интерполяции может быть использован творчески для создания произвольных объектов, как показано в следующем примере:
case class Let(name: Char, value: Int)
implicit class LetInterpolator(sc: StringContext) {
def let(value: Int): Let = Let(sc.parts(0).charAt(0), value)
}
let"a=${4}" // Let(a, 4)
let"b=${"foo"}" // error: type mismatch
let"c=" // error: not enough arguments for method let: (value: Int)Let
Строковые интерполяторы как экстракторы
Также возможно использовать функцию интерполяции строк Scala для создания сложных экстракторов (шаблонов шаблонов), которые, возможно, наиболее широко используются в API квазикодов макросов Scala.
Учитывая, что n"p0${i0}p1"
desugars для new StringContext("p0", "p1").n(i0)
, возможно, неудивительно, что функция экстрактора включена, обеспечивая неявное преобразование из StringContext
в класс с свойство n
типа, определяющего метод unapply
или unapplySeq
.
В качестве примера рассмотрим следующий экстрактор, который извлекает сегменты пути, создавая регулярное выражение из частей StringContext
. Затем мы можем делегировать большую часть тяжелого подъема методу unapplySeq
предоставленному результатом scala.util.matching.Regex :
implicit class PathExtractor(sc: StringContext) {
object path {
def unapplySeq(str: String): Option[Seq[String]] =
sc.parts.map(Regex.quote).mkString("^", "([^/]+)", "$").r.unapplySeq(str)
}
}
"/documentation/scala/1629/string-interpolation" match {
case path"/documentation/${topic}/${id}/${_}" => println(s"$topic, $id")
case _ => ???
}
Обратите внимание, что объект path
также может определить метод apply
, чтобы вести себя как обычный интерполятор.
Интерполяция сырой строки
Вы можете использовать необработанный интерполятор, если вы хотите, чтобы строка была напечатана как есть и без какого-либо выхода из литералов.
println(raw"Hello World In English And French\nEnglish:\tHello World\nFrench:\t\tBonjour Le Monde")
С использованием исходного интерполятора вы должны увидеть следующее, напечатанное на консоли:
Hello World In English And French\nEnglish:\tHello World\nFrench:\t\tBonjour Le Monde
Без необработанного интерполятора \n
и \t
были бы экранированы.
println("Hello World In English And French\nEnglish:\tHello World\nFrench:\t\tBonjour Le Monde")
Печать:
Hello World In English And French
English: Hello World
French: Bonjour Le Monde