Можно ли получить функцию Char => Boolean из класса символов Regex, не компилируя каждый раз шаблон?
Это проверяет тип, но каждый раз перекомпилирует шаблон, что неэффективно:
val f: Char => Boolean = c => c.toString.matches("[bgjkqtz]")





Вы можете использовать сопоставление с образцом.
val myChars = "[bgjkqtz]".r //compiled once
def predicate(c :Char) :Boolean = c match {
case myChars() => true
case _ => false
}
Но я не знаю, насколько это будет производительно, поскольку это также потребует основных вызовов unapplySeq() и isEmpty().
Как насчет этого?
// compiles a regular expression `rgx` into a predicate on characters.
def toPred(rgx: String): Char => Boolean = {
val p = rgx.r.pattern
c => p.matcher(c.toString).matches
}
Он компилирует шаблон p один раз, а затем сохраняет его в замыкании. Примеры:
scala> val f = toPred("[abcdef]")
scala> f('a')
res5: Boolean = true
scala> f('x')
res6: Boolean = false
Как насчет "[fkadjd]".replaceAll("[\[\]]").toSet?
Set[Char]являетсяChar => Boolean, вам действительно не нужно регулярное выражение для соответствия символу ...
Вероятно, не тот ответ, который ищет OP, но для нескольких одиночных символов это забавное решение.
Конкретный пример, который вы даете, не требует регулярного выражения, потому что он просто проверяет, находится ли c в наборе символов. Это можно сделать с помощью contains:
val f: Char => Boolean = c => "bgjkqtz".contains(c)
Фактически, этот пример был добавлен к вопросу в редакции @AndreyTyukin (скопирован из моего примера кода). См. Также его комментарий к @Dima. Более реалистичным примером может быть что-то вроде [\w-[aeiou]].
@jwvh Я думаю, что и вы, и Дима использовали его в качестве примера, поэтому я решил добавить его в вопрос. На "bgjkqtz".contains: во-первых, вы могли бы опустить c => и (c), во-вторых, это O(n) по количеству символов ... Это определенно плохо масштабируется для [^a] и т. д.
@AndreyTyukin Я согласен, что это не общее решение и не масштабируется. Но ваше предложение об исключении c => и (c) неверно: contains на String принимает CharSequence, поэтому вам нужно принудительно выполнить неявное преобразование в SeqLike, чтобы получить версию, которая принимает Char.
@ Тим О, ты прав. Вот еще одна альтернатива, которая использует синтаксис подчеркивания: val f: Char => Boolean = "abcdef".contains(_: Char) (на этот раз он компилируется, по крайней мере, в> 2.16)
На самом деле это довольно интересный пример: val f: Char => Boolean = "abcdef".contains[Char] также не компилируется, хотя есть только один метод, который принимает параметры типа. Интересный угловой случай.
Для
[\\d]или просто\\dэто будет раздражать. Для более сложных классов символов, таких как\\p{L}, он будет занимать много места, будет крайне неэффективным и на самом деле довольно сложным для эмуляции явно перечисляемым набором (как бы вы перечислили все смайлы с этим? Я не знаю ...) .