Pattern matching during matching

For example, imagine that you have the following:

import play.api.data._ import play.api.data.Forms._ case class TestDomainClass(text: String, number: Int, date: DateTime, long: Long, boolean: Boolean) val testForm = Form( mapping( "textField" -> text, "numberField" -> number, "dateField" -> jodaDate, "longField" -> longNumber, "booleanField" -> boolean )(TestDomainClass.apply)(TestDomainClass.unapply) ) 

My goal is to match patterns by type of parameters for each of the fields. For example: for textField the parameter type will be String , and for dateField will be org.joda.time.DateTime .


First attempt to solve

 def typeOfMappingUsingTypeTag[T: TypeTag](m: Mapping[T]) = typeOf[T] match { case t if t =:= typeOf[String] => println("type is String") case t if t =:= typeOf[Int] => println("type is Int") case t if t =:= typeOf[org.joda.time.DateTime] => println("type is DateTime") case t if t =:= typeOf[Long] => println("type is Long") case t if t =:= typeOf[Boolean] => println("type is boolean") case _ => println("type is something else") } for(m <- testForm.mapping.mappings if m.key.nonEmpty) { print(m.key) typeOfMappingUsingTypeTag(m) } 

With the following output:

 textFieldtype is something else numberFieldtype is something else dateFieldtype is something else longFieldtype is something else booleanFieldtype is something else 

So no luck, which was somewhat expected, since the source Mapping does not have a binding to TypeTag.


Second attempt to solve

 def typeOfMappingUsingPatternMatch[T](m: Mapping[T]) = m match { case text => println("type is String") case number => println("type is Int") case jodaTime => println("type is DateTime") case longNumber => println("type is Long") case boolean => println("type is Boolean") case _ => println("type is something else") } for(m <- testForm.mapping.mappings if m.key.nonEmpty) { print(m.key) typeOfMappingUsingPatternMatch(m) } 

With the following output:

 textFieldtype is String numberFieldtype is String dateFieldtype is String longFieldtype is String booleanFieldtype is String 

And the following compilation warning:

 [warn] /aFolder/aProject/app/controllers/IPBlocks.scala:58: patterns after a variable pattern cannot match (SLS 8.1.1) [warn] case text => println("type is String") [warn] ^ [warn] /aFolder/aProject/app/controllers/IPBlocks.scala:59: unreachable code due to variable pattern 'text' on line 58 [warn] case number => println("type is Int") [warn] ^ 

And the same warning as for the remaining cases.

If I change the order of affairs, then whichever case ends first, this is the one that is printed (for example, if case boolean is the first case, then the output will be is Boolean for each of the fields)


Third Attempt

Given the conclusion:

 val t = text println("t == number " + (t == number)) println("t == text " + (t == text)) println("t eq number " + (t eq number)) println("t eq text " + (t eq text)) 

is an

 t == number true t == text true t eq number false t eq text true 

Using ifs and eq seems to solve the problem, so I tried:

 def typeOfMappingUsingIfAndEq[T](m: Mapping[T]) = { if (m eq text) { println("type is String") } else if (m eq number) { println("type is Int") } else if (m eq jodaDate) { println("type is DateTime") } else if (m eq longNumber) { println("type is Long") } else if (m eq boolean) { println("type is Boolean") } else { println("type is something else") } } for(m <- testeForm.mapping.mappings if m.key.nonEmpty) { print(m.key) typeOfMappingUsingIfAndEq(m) } 

With the next exit

 textFieldtype is something else numberFieldtype is something else dateFieldtype is something else longFieldtype is something else booleanFieldtype is something else 

So is there a solution to the problem? If so, what is it? Also, why is the third solution not working in hell?

+6
source share
1 answer

I'm not sure if I understood what you need, but if you want to do things based on the type of object, you can use a template that matches this method:

 value match { case stringValue : String => // value es a String! You can use the stringValue variable which type is String but reference the same object case intValue : Int => // value is an Int. Do stuff. ... case _ => // any other case } 

As for your third implementation, beware of using equiv. Eq verifies identity, which is not the same idea as equalty. (You can check this post for more information). Also, since your code is taken out of context, I'm not sure how some of these variables are defined, but if, for example, we take these lines:

 def typeOfMappingUsingIfAndEq[T](m: Mapping[T]) = { if (m eq text) { ... 

If the variable type is Text String (as shown in TestDomainClass ), then it will not be equal to / identical to m, which is of type Display [T] ).

Hope this helps!

Good luck

0
source

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


All Articles