Scala: Как избежать обратного удара в буквальном смысле? - PullRequest
7 голосов
/ 05 апреля 2019

Литералы в Scala позволяют определить идентификатор, как описывает этот ответ . Есть ли способ избежать обратной черты `внутри литерала? Чтобы сделать что-то вроде:

 val `hello `world` = "hello world"

Обновление
Одним из вариантов использования этого является использование уточненной библиотеки для некоторых уточненных типов, которые соответствуют регулярному выражению, содержащему обратную косую черту, например:

  import eu.timepit.refined._
  import eu.timepit.refined.api.Refined

  type MatchesRegexWithBacktick = String Refined MatchesRegex[W.`(a|`)`.T]

1 Ответ

7 голосов
/ 06 апреля 2019

Это не может быть сделано с компилятором Scala как есть, но возможно это было бы возможно с плагином компилятора, который изменил способ синтаксического анализа идентификаторов (возможно, если функция обратного тика была каким-то образом заменено каким-то неясным символом юникода).

В Scala SLS 1.1 существует лексический синтаксис для идентификаторов:

op       ::=  opchar {opchar}
varid    ::=  lower idrest
boundvarid ::=  varid
             | ‘`’ varid ‘`’
plainid  ::=  upper idrest
           |  varid
           |  op
id       ::=  plainid
           |  ‘`’ { charNoBackQuoteOrNewline | UnicodeEscape | charEscapeSeq } ‘`’
idrest   ::=  {letter | digit} [‘_’ op]

Проблема в том, что единственное правило, разрешающее использовать любой символ, кроме букв, цифр или _, - это то, которое требует, чтобы идентификатор был заключен в кавычки:

‘`’ { charNoBackQuoteOrNewline | UnicodeEscape | charEscapeSeq } ‘`’

Однако, он явно не допускает обратных тиков с charNoBackQuoteOrNewline, и, если вы думаете, что можете обойти это с UnicodeEscape, это тоже не сработает:

scala> val `hello \u0060world` = "hello world"
<console>:1: error: unclosed quoted identifier
val `hello \u0060world` = "hello world"
                      ^
...