How to do implicit conversion during pattern matching

I have an enumeration for keywords and operators (and some others), for example. (all similar):

object Keywords extends Enumeration { val AND, ARRAY, BEGIN, ...= Value case class Keyword(keyword: Value) extends Token[Value] { def this(keyword: String) = this(Keywords.fromString(keyword)) def value = keyword } implicit def valueToKeyword(keyword: Value) = new Keyword(keyword) } 

this implicit conversion allows me to pass enum values ​​where Token is expected, for example.

 def testFunction[T](t: Token[T]) = ... testFunction(Keywords.ARRAY) // gets converted testFunction(Operators.PLUS) // gets converted too 

it also seems that the same implicit conversion does not apply during ie matching

 val token = new Keyword("ARRAY") token match { case Keywords.ARRAY => ... // not selected but SHOULD be case Operators.PLUS => ... // completely different Enum ... } 

Why? How to overcome this?

+6
source share
1 answer

This does not work because:

 token match { case Keywords.ARRAY => println("Array") case _ => println("Something else") } 

essentially a PartialFunction with the following type signature: PartialFunction[Keywords.Value, Unit] . This means that the implied will not be applied because it isDefinedAt or not for this input.

If it is not defined than case _ => ... , it will catch everything in my code example. If it is not defined at all and nothing matches it, you will get a MatchError .

In your case, a token type Token[Value] not defined in the Partial function that the match will compile, since only Keywords.Value types are defined.

Three decisions

If you really want implicits, then you can explicitly request implicit (yes, this sentence is ridiculous :))

 implicitly[Keywords.Value](token) match { case Keywords.ARRAY => println("Array") case _ => println("Something else") } 

Or you can explicitly specify the token type to trigger implicit magic:

 val token: Keywords.Value = new Keyword("ARRAY") token match { case Keywords.ARRAY => println("Array") case _ => println("Something else") } 

Or the simplest solution if you can live without implication:

 token.value match { case Keywords.ARRAY => println("Array") case _ => println("Something else") } 

I know that this is not the answer you are looking for, but I hope you understand what match {...} means and what partial functions.

+4
source

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


All Articles