Могут ли экстракторы настраиваться с параметрами в теге 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, которые принимают частичную функцию в качестве параметра и обычно не оставляют места для предварительной обработки набора экстракторов.