Существует специальный класс Scala под названием StringContext
.Он используется для реализации различных методов интерполяции строк, таких как
s"foo ${42}"
(что приводит к String
"foo 42"
) или
f"foo ${42}%04x"
(что приводит к String
сшестнадцатеричные отформатированные целые числа "foo 002a"
).
Механизм на самом деле довольно общий и позволяет определять все виды различных механизмов интерполяции строк путем неявного приведения StringContext
в ваши собственные классы-обертки.То есть, если вы хотите, вы можете определить механизм интерполяции строк, который выглядит следующим образом:
myStringInterpolator"foo ${42}"
Так как $
- это просто обычный идентификатор, вы можете реализовать StringContext
-обёртку, которая имеет методс подписью
def $(args: Any*): YourResultType
и когда эта оболочка находится в неявной области, вы можете использовать $
для интерполяции строк следующим образом:
$"some string literal ${arg1} more text ${arg2} end"
, и это создаст оболочку с StringContext
удерживая ["some string literal ", " more text ", " end"]
, а затем вызовите $
-метод с помощью arg1
и arg2
.
Например, вы можете определить интерполяцию строки $
, которая преобразует все аргументы в целые числа исуммирует их:
implicit class MyDollarContext(s: StringContext) {
def $(args: Any*): Int = args.map(_.toString.toInt).sum
}
println($"I bought a coffee for ${30} and a snack for ${12}.")
Это выведет 42
, который является суммой всех чисел внутри ${...}
-брейсов.
Аналогично, Apache Spark использует неявный StringToColumn
класс для преобразования Strings
в Spark ColumnName
с.Я не уверен, почему это было реализовано таким образом, я думаю, что они хотели сделать имена столбцов немного похожими на Perl или Bash-переменные, и использовали для этого довольно много синтаксических хитростей.