Can extractors be customized with parameters in the body of a case statement (or anywhere else that an extractor would be used)?

前端 未结 5 1220
情书的邮戳
情书的邮戳 2020-12-06 10:15

Basically, I would like to be able to build a custom extractor without having to store it in a variable prior to using it.

This isn\'t a real example of how I would

相关标签:
5条回答
  • 2020-12-06 10:49

    Parameterising extractors would be cool, but we don't have the resources to implement them right now.

    0 讨论(0)
  • 2020-12-06 10:52

    Though what you are asking isn't directly possible,
    it is possible to create an extractor returning a contaner
    that gets evaluated value in the if-part of the case evaluation. In the if part it
    is possible to provide parameters.

    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
          }
        }
      }
    }
    

    Usage:

    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")
          }
        }
      }
    }
    

    This pattern preserves the PartialFunction nature of the piece of code.
    I find this useful since I am quite a fan of the collect/collectFirst methods, which take a partial function as a parameter and typically does not leave room for precreating a set of extractors.

    0 讨论(0)
  • 2020-12-06 10:54

    One can customize extractors to certain extent using implicit parameters, like this:

    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
    }
    

    Unfortunately this cannot be used when you want to use different variants in one match, as all case statements are in the same scope. Still, it can be useful sometimes.

    0 讨论(0)
  • 2020-12-06 11:07

    Late but there is a scalac plugin in one of my lib providing syntax ~(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

    0 讨论(0)
  • 2020-12-06 11:10

    Nope.

    8.1.7 Extractor Patterns

    An extractor pattern x (p 1 , . . . , p n ) where n ≥ 0 is of the same syntactic form as a constructor pattern. However, instead of a case class, the stable identifier x denotes an object which has a member method named unapply or unapplySeq that matches the pattern.

    0 讨论(0)
提交回复
热议问题