Могут ли экстракторы настраиваться с параметрами в теге case-оператора (или где-либо еще, что будет использоваться экстрактором)?
В принципе, я хотел бы иметь возможность создавать пользовательский экстрактор без необходимости хранить его в переменной перед его использованием.
Это не настоящий пример того, как я буду использовать его, скорее всего, он будет использоваться в случае регулярного выражения или какой-либо другой строковой структуры, такой как конструкция, но, надеюсь, он объясняет, что я ищу:
def someExtractorBuilder(arg:Boolean) = new {
def unapply(s:String):Option[String] = if(arg) Some(s) else None
}
//I would like to be able to use something like this
val {someExtractorBuilder(true)}(result) = "test"
"test" match {case {someExtractorBuilder(true)}(result) => result }
//instead I would have to do this:
val customExtractor = someExtractorBuilder(true)
val customExtractor(result) = "test"
"test" match {case customExtractor(result) => result}
Когда вы делаете только один пользовательский экстрактор, это не имеет большого значения, но если вы создаете большой список экстракторов для оператора case, это может усложнить чтение, разделив все экстракторы с их использованием.
Я ожидаю, что ответ не будет, вы не можете этого сделать, но я подумал, что сначала спрошу: D
Ответы
Ответ 1
Неа.
8.1.7 Шаблоны экстрактора
Рисунок экстрактора x (p 1,..., p n), где n ≥ 0 является одинаковым синтаксическая форма как конструктор шаблон. Однако вместо случая класса, устойчивый идентификатор х означает объект, который имеет метод-член названо unapply или unapplySeq, что соответствует шаблону.
Ответ 2
Экстракторы параметрирования будут классными, но у нас нет ресурсов для их реализации прямо сейчас.
Ответ 3
Поздно, но в одной из моих библиотек есть плагин scalac, обеспечивающий синтаксис ~(extractorWith(param), bindings)
:
x match {
case ~(parametrizedExtractor(param)) =>
"no binding"
case ~(parametrizedExtractor(param), (a, b)) =>
s"extracted bindings: $a, $b"
}
https://github.com/cchantep/acolyte/blob/master/scalac-plugin/readme.md
Ответ 4
Можно выделить экстракторы в определенной степени с использованием неявных параметров, например:
object SomeExtractorBuilder {
def unapply(s: String)(implicit arg: Boolean): Option[String] = if (arg) Some(s) else None
}
implicit val arg: Boolean = true
"x" match {
case SomeExtractorBuilder(result) =>
result
}
К сожалению, это невозможно использовать, если вы хотите использовать разные варианты в одном match
, так как все операторы case
находятся в одной области. Тем не менее, это может быть полезно иногда.
Ответ 5
Хотя то, что вы спрашиваете, не представляется возможным,
можно создать экстрактор, возвращающий контроллер
это получает оцененное значение в части if оценки случая. В части if это
Можно предоставить параметры.
object DateExtractor {
def unapply(in: String): Option[DateExtractor] = Some(new DateExtractor(in));
}
class DateExtractor(input:String){
var value:LocalDate=null;
def apply():LocalDate = value;
def apply(format: String):Boolean={
val formater=DateTimeFormatter.ofPattern(format);
try{
val parsed=formater.parse(input, TemporalQueries.localDate());
value=parsed
true;
} catch {
case e:Throwable=>{
false
}
}
}
}
Использование:
object DateExtractorUsage{
def main(args: Array[String]): Unit = {
"2009-12-31" match {
case DateExtractor(ext) if(ext("dd-MM-yyyy"))=>{
println("Found dd-MM-yyyy date:"+ext())
}
case DateExtractor(ext) if(ext("yyyy-MM-dd"))=>{
println("Found yyyy-MM-dd date:"+ext())
}
case _=>{
println("Unable to parse date")
}
}
}
}
Этот шаблон сохраняет природу PartialFunction части кода.
Я нахожу это полезным, так как я большой поклонник методов collect/collectFirst, которые принимают частичную функцию в качестве параметра и обычно не оставляют места для предварительной обработки набора экстракторов.