I am writing an implicit reads returning JsResult[Seq[T]] based on a condition:
some_condition match{
case Some(value) => // JsResult[Seq[T]]
case _ => // returning an empty JsResult here of similar type?
}
What would be the way for return such JsResult?
You will need to use the method validate, which returns JsResult. There are 2 case classes that inherits JsResult:
JsSuccess
JsError
Therefore you can consider the following example:
case class T()
implicit val reads = Json.reads[T]
val jsValue: JsValue = ...
jsValue.validate[Seq[T]] match {
case JsSuccess(t, path) =>
println(t)
case JsError(errors) =>
println(errors)
}
Related
I have enum like this.
object SortCountryField extends Enumeration {
type SortCountryField = Value
val countryName = Value("country_name")
val countryStatus = Value("country_status")
}
I'm using this SortCountryField enum in match-case.
Here I need to convert toString every time.
To make it convenient I'm trying to implicit converter to extract String from SortCountryField.{Value}
However, I end up having a compiler error when I use the implicit function in following match case.
'myString' match{
case SortCountryField.countryName.toString => //Some operations
case SortCountryField.countryStatus.toString => //another operation
}
Error Log:-
found : mypackage.ConstantUtils.SortCountryField.Value
[error] required: String
[error] case SortCountryField.countryStatus => //my-operations
I think you'd be better off using the enum in your match like:
SortCountryField withName <your_string> match {
case SortCountryField.countryName => //Some operations
case SortCountryField.countryStatus => //another operation
}
If your string sometimes doesn't match any field then you can easily wrap this in a Try like in the following code:
Try(SortCountryField withName <your_string>) match {
case Success(SortCountryField.countryName) => //Some operations
case Success(SortCountryField.countryStatus) => //another operation
case _ => //another operation
}
You can also do:
'myString' match{
case x if x == SortCountryField.countryName.toString => //Some operations
case x if x == SortCountryField.countryStatus.toString => //another operation
}
How does your implicit converter looks like?
My guess is that you have converter SortCountryField => String, but you need SortCountryField.Value => String converter.
Add below function in your enum:
implicit def toString(value: Value): String = value.toString
Use below in matching:
val countryStaus:String = SortCountryField.countryStatus
'myString' match {
case `countryStatus` => //Some operations
case _ => // Another operation
}
I'm trying to match an enum value converted to a string held in a collection. Here's the code:
object Foo extends Enumeration {
val ONE = Value("ONE")
val TWO = Value("TWO")
}
def check(seq: Seq[String]): Unit = seq match {
case Seq(Foo.ONE.toString) => println("match")
case _ => println("no match")
}
This results in a compilation error:
error: stable identifier required, but Foo.ONE.toString found.
case Seq(Foo.ONE.toString) => println("match")
What is the proper way to use my Foo enumerated values as elements of my pattern matching case statements?
Map it back to the enum first:
import scala.util.Try
val enumSeq = seq map (x => Try(Foo.withName(x)))
Then you can either filter out the Failures or match on Seq(Success(ONE)), Seq(Success(ONE)), ..., Seq(Failure), etc.
def check(seq: Seq[String]): Unit = seq match {
case Seq(s # _) if s == Foo.ONE.toString => println("match")
case _ => println("no match")
}
I like the response from #cchantep, which was to avoid calling .toString inside the pattern match and implement the check method like so:
def check(seq: Seq[Foo.Value]): Unit = seq match {
case Seq(Foo.ONE) => println("match")
case _ => println("no match")
}
I have an enum for keywords and operators (and some other too), e.g. (all are 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 Tokens are expected e.g.
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 is not applied during matching i.e.
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?
This doesn't work because:
token match {
case Keywords.ARRAY => println("Array")
case _ => println("Something else")
}
is essentially a PartialFunction with the following type signature: PartialFunction[Keywords.Value, Unit]. Which means an implicit won't be applied, because it's either isDefinedAt or it isn't for that input.
If it isn't defined than case _ => ... will catch everything in my example code. If it's not defined at all and nothing will match it then you will get a MatchError thrown.
In your case token of type Token[Value] isn't defined in the Partial Function that the match will compile to, because only types of Keywords.Value are defined.
Three solutions
If you really want implicits then you could explicitly ask for an implicit (yes, that sentence is funny :))
implicitly[Keywords.Value](token) match {
case Keywords.ARRAY => println("Array")
case _ => println("Something else")
}
Or you can explicitly state the type of token, to invoke the 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 implicits:
token.value match {
case Keywords.ARRAY => println("Array")
case _ => println("Something else")
}
I know it's not the answer you're looking for, but I hope that you understood what match {...} really means and what Partial Functions are.
We have a multithreaded RPC server that parses input strings. We've run into an issue where Scala's parser combinator library is not multithreaded safe: the var lastNoSuccess in Parsers.scala is used by any parsing. We get a NullPointerException in this line
if (!(lastNoSuccess != null && next.pos < lastNoSuccess.next.pos))
The default way to implement the parser by making an object that extends one of the Parsers, but I want to construct a parser on demand so each has its own internal state, so I'm using a class instead of an object. However, I can't get it to compile since I need to pattern match on the result:
import scala.util.parsing.combinator.RegexParsers
class SqlParserImpl
extends RegexParsers
{
val term: Parser[String] = """(?i)term\b""".r
}
object Test
{
def main(args: Array[String]): Unit =
{
val parser = new SqlParserImpl
parser.parseAll(parser.term, "term") match {
// How do I match?
case SqlParserImpl#Success(result, _) => true
case SqlParserImpl#NoSuccess => false
}
}
}
Fails with
t.scala:16: error: '=>' expected but '#' found.
case SqlParserImpl#Success(result, _) => true
^
t.scala:17: error: '=>' expected but '#' found.
case SqlParserImpl#NoSuccess => false
^
two errors found
Use this:
val parser = new SqlParserImpl
parser.parseAll(parser.term, "term") match {
case parser.Success(result, _) => true
case parser.NoSuccess(_, _) => false
}
The # sign is used to designate a type member. In your case it's using a constructor or an extractor pattern which needs to reference to an object or something that looks like a constructor.
Hmm. I don't have a 2.7 handy. Try this:
parser.parseAll(parser.term, "term") match {
case parser.Success(result, _) => true
case parser.Failure(_, _) => false
case parser.Error(_, _) => false
}
I was able to compile the following:
object Test {
def main(args: Array[String]): Unit = {
val parser = new SqlParserImpl
println(parser.parseAll(parser.term, "term") match {
case x: parser.Success[_] => true
case x: parser.NoSuccess => false
})
}
}
The NoSuccess object (with extractor) was added back in 2009, at a time when no code was being backported to 2.7 anymore It's implementation, however, is pretty simple:
object NoSuccess {
def unapply[T](x: ParseResult[T]) = x match {
case Failure(msg, next) => Some(msg, next)
case Error(msg, next) => Some(msg, next)
case _ => None
}
}
So you can replace the parser.NoSuccess(_, _) match with one parser.Failure(_, _) and one parser.Error(_, _) match. But if you are not interested in what is being returned, then it's simpler to match against the type:
case _: parser.Success[_] => true
case _: parser.NoSuccess => false
Like suggested by Eugene.
How would you implement class that parses some input via regex and transforms founded string to some other type? My approach is:
class ARegex[T](regex:Regex, reform:Option[String => T]){
def findFirst(input:String):Option[T] = {
(regex.findFirstIn(input), reform) match{
case (None, _) => None
case (Some(s), None) => Some(s) // this won't compile because of type mismatch
case (Some(s), Some(fun)) => Some(fun(s))
}
}
}
class BRegex[T](regex:Regex, reform:Option[String => T]) {
def findFirst(input:String) = { //returns Option[Any] - erasure
(regex.findFirstIn(input), reform) match{
case (None, _) => None
case (Some(s), None) => Some(s)
case (Some(s), Some(fun)) => Some(fun(s))
}
}
}
We can solve this problem by eliminating the Option part of the reform's type, and using a different mechanism to indicate that we don't want to change the match in any way. This mechanism is to use identity as a default parameter or pass identity when you don't want the type to change.
class ARegex[T](regex:Regex, reform:String => T = identity[String](_)){
def findFirst(input:String):Option[T] = {
regex.findFirstIn(input) match{
case None => None
case Some(s) => Some(reform(s))
}
}
}
new ARegex("something".r).findFirst("something else") //returns Option[String]
new ARegex("3".r, {x=>x.toInt}).findFirst("number 3") //returns Option[Int]
Well, the problem is the type mismatch, because you are returning either a String or a T, which, of course, are unified at Any. You can't say you are going to return Option[T] and then return Option[String].
Other than that, a simplified version of that code is this:
class ARegex[T](regex: Regex, reform: Option[String => T]) {
def findFirst(input: String): Option[Any] =
regex findFirstIn input map { s => reform map (_(s)) getOrElse s }
}
You could return an Option[Either[String, T]], though. The code would look like this:
class ARegex[T](regex: Regex, reform: Option[String => T]) {
def findFirst(input: String): Option[Either[String, T]] =
regex findFirstIn input map { s => reform map (_(s)) toRight s }
}
Why is reform Option[String => T] instead of just String => T? If you don't pass in a mechanism for creating an instance of your desired type, there's no mechanism for the runtime system to actually create the appropriate object. If you really need to pass in an Option[String => T] then your second case should simply return None.
Also, flatMap is your friend, and will give you the correct behavior (i.e. if reform is None, the method returns None.
class RegexExtractor[T](regex: Regex, reform: Option[String => T]) {
def findFirst(input: String): Option[T] = reform.flatMap(f => regex.findFirstIn(input).map(f))
}