Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to annotate a parameter as implicit in pattern match while extracting values

I have a class like

case class A(a: Int, b: String)

and a function

def f(a: Int)(implicit b: String) =???

Is it possible to do something like this?

val a = A(11, "hello")
a match {
  case A(a, implicit b) => f(a)
}

How can I make the parameter b implicit without explicitly declaring it after extraction.

like image 391
curious Avatar asked Oct 16 '22 21:10

curious


1 Answers

I wouldn't worry about passing the argument implicitly, since you can easily provide it explicitly in this particular case:

case class A(a: Int, b: String)

def f(a: Int)(implicit b: String) =???

val a = A(11, "hello")
a match {
  case A(a, b) => f(a)(b)
}

If you must pass the value implicitly, it needs to be declared in scope. For example:

a match {
  case A(a, b) => {
    implicit val s = b
    f(a)
  }
}

Also, as has been pointed out, don't use implicit with a common type. It's better if you wrap it in another class:

case class A(a: Int, b: String)

case class SomeCustomString(s: String)

def f(a: Int)(implicit b: SomeCustomString) =???

val a = A(11, "hello")
a match {
  case A(a, b) => {
    implicit val s = SomeCustomString(b)
    f(a)
  }
}

If you could explain the use case for the implicit argument, I could provide a better example.

Update: There is a kind of way to do what you want:

case class SomeCustomString(s: String)

case class A(a: Int, b: String) {
  implicit val s = SomeCustomString(b)
}

def f(a: Int)(implicit s: SomeCustomString) =???

val a = A(11, "hello")
import a._
f(a.a)

Or, if you must have it within a pattern match, that last bit would be:

a match {
  case x: A => {
    import x._
    f(x.a)
  }
}

Update 2: Or, as yet another approach (again, with implicit largely redundant):

case class SomeCustomString(s: String)

case class A(a: Int, b: String) {
  implicit val s = SomeCustomString(b)
  def invokeF = f(a)
}

def f(a: Int)(implicit s: SomeCustomString) =???

val a = A(11, "hello")
a.invokeF

or

a match {
  case x: A => x.invokeF
}

Does that help?

like image 57
Mike Allen Avatar answered Nov 15 '22 10:11

Mike Allen