Dynamic Extractors in Scala

One of the things that I don't like about extractors is that they cannot have parameters. Therefore, I cannot have type extractors Paramin:

req match { case Param("foo")(foo) => … }

Dynamic extractors?

This is unfortunate, and I hope that it will change someday, but this morning I decided that I could fix it using a dynamic symptom.

object Params extends Dynamic {
  def selectDynamic(name: String) = new {
    def unapply(params: Map[String, String]): Option[String] = params.get(name)
  }
}

... hoping this will allow me to use Params in the pattern matching statement as follows:

req match { case Params.Foo(value) => 
  // matching Map("Foo" -> "Bar"), extracting "Bar" in value

He does not work

... but it does not work. The compiler seems to be still confused.

scala> Map("Foo" -> "bar") match { case Params.Foo(value) => value }
<console>:10: error: value applyDynamic is not a member of object Params
error after rewriting to Params.<applyDynamic: error>("Foo")
possible cause: maybe a wrong Dynamic method signature?
              Map("Foo" -> "bar") match { case Params.Foo(value) => value }
                                               ^
<console>:10: error: not found: value value
              Map("Foo" -> "bar") match { case Params.Foo(value) => value }
                                                                    ^

What I find amazing since

object Params {
  object Foo {
    def unapply{params: Map[String, String]): Option[String] = … 
  }
}

will work fine. Also, if I assign the Params.Foovariable first , everything will be fine:

scala> val Foo = Params.Foo
Foo: AnyRef{def unapply(params: Map[String,String]): Option[String]} = Params$$anon$1@f2106d8

scala> Map("Foo" -> "bar") match { case Foo(value) => value }
warning: there were 1 feature warning(s); re-run with -feature for details
res2: String = bar

Should this be considered a mistake?

+4
1

case ( - , )?

, .

$ scala
Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_60).
Type in expressions for evaluation. Or try :help.

scala> class X(pattern: String) { val RegExp = new { def unapplySeq(s: String) = pattern.r.unapplySeq(s) } }
defined class X

scala> import language._
import language._

scala> case object p extends Dynamic { def selectDynamic(pattern: String) = new X(pattern) }
defined object p

scala> "abcdef" match { case p.`.*(b.*d).*`.RegExp(s) => s }
res0: String = bcd

- 2.11, 2.10, :

scala> class RegExp(pattern: String) { def unapplySeq(s: String) = pattern.r.unapplySeq(s) }
defined class RegExp

scala> case object p extends Dynamic { def selectDynamic(pattern: String) = new RegExp(pattern) }
defined object p

scala> "abcdef" match { case p.`.*(b.*d).*`(s) => s }
java.lang.NullPointerException
    at scala.tools.nsc.typechecker.PatternTypers$PatternTyper$class.inPlaceAdHocOverloadingResolution(PatternTypers.scala:68)

2.10:

$ scala210 -language:_
Welcome to Scala version 2.10.5 (OpenJDK 64-Bit Server VM, Java 1.7.0_95).
Type in expressions to have them evaluated.
Type :help for more information.

scala> :pa
// Entering paste mode (ctrl-D to finish)

class X(key: String) { val get = new { def unapply(params: Map[String, String]): Option[String] = params.get(key) }}
object Params extends Dynamic {
  def selectDynamic(name: String) = new X(name)
}

// Exiting paste mode, now interpreting.

defined class X
defined module Params

scala> Map("Foo" -> "bar") match { case Params.Foo.get(value) => value }
res0: String = bar

, , , .

0

Source: https://habr.com/ru/post/1546298/


All Articles