Protobuf to scala conversion - scala

I have in protobuf
message ResultsPb{
repeated int32 Result = 1;
}
and the corresponding in scala
Results: List[Int]
I’m new to this and I’m having a hard time finding the proper way to convert from one to the other. Here is what I've come up with so far but not sure at all of that. First def doesn't build, second def do build.
def toResults(resultsPb: Option[ResultsPb]): List[Int] ={
List[Int](resultsPb.Result)
}
def fromResults(results: List[Int]): Option[ResultsPb] ={
Some(ResultsPb (results.toSeq))
}
Any help would be greatly appreciated.
Thanks

def toResults(resultsPb: Option[ResultsPb]): List[Int] ={
resultsPb.toList.flatMap(_.Result)
}
def fromResults(results: List[Int]): Option[ResultsPb] ={
Some(results).filter(_.nonEmpty).map(t => ResultPb(t))
}
Update
So, to convert optional proto class to its argument you need
to check that option is not empty
extract data from class
this could be done as Bob proposed (with pattern matching), or simplier with flatMap (but before you need to convert Option to Seq/List to satisfy type check)
In second method, again you can do it with if statement (checking if List is empty), with matching (checking the same with "case _ :: Nil => ... case Nil =>") or as I proposed with filtering empty result and getting None automatically in this case.

Related

Establishing quine type in scala

I have to parse a string with syntax
lazy val expr: Parser[Term ~ Option[<recursion>]] = term ~ opt(expr)
You see, it uses itself to parse subexpressions. But what does this type result in? In order to reproduce the problem, I created a somewhat similar problem
def quine(depth: Int, result: (Any, Option[Any])): (Any, Option[Any]) =
if (depth == 0) result else {quine(depth - 1, (depth, Some(result)))}
quine(5, (true, None))
As you see, I used Any since I do not know how to give exact type.
The lists somehow define proto type List[A], extended by Cons[A](head: A, tail: List[A]) and some magic Nil. This allows the list to recur somehow. But, what should I do in my case?
I am not sure what you are trying to do here, because your result type is different between the function definition and invocation (the first element is Int in the former and Boolean in the latter, that can't work).
But, provided that was just a typo, something like this should do the trick:
case class Quine(n: Int, q: Option[Quine])
def quine(depth: Int, result: Quine): Quine =
if (depth == 0) result else
quine(depth - 1, Quine(depth, Some(result)))
quine(5, Quine(6, None))

scalaz: how to handle different error types in a Validation?

If I have multiple operations that return a Validation[E, _] of something with a fixed error type I can use them in a for-comprehension. For example:
val things: Validation[E, (Int, Double)] = for {
i <- getValidationOfInt
d <- getValidationOfDouble
} yield (i, d)
What about if the error types are different? Suppose I read from HTTP and want to convert the string response into an Int.
import scalaz._; import Scalaz._
object ValidationMixing {
class HttpError
def getFromHttp: Validation[HttpError, String] = ???
def parseInt(json: String): Validation[Throwable, Int] =
Validation.fromTryCatchNonFatal(Integer.parseInt(json))
val intParsedFromHttp: Validation[Any, Int] = for {
s <- getFromHttp
i <- parseInt(s)
} yield i
}
This compiles, but only because the error type of the Validation is Any, being a supertype of Throwable and HttpError. This isn't very helpful.
I can think of various ways of representing such a combined error type that are more useful than Any (e.g. Validation[Error1 \/ Error2, Result] to store either, Validation[String, Result] translating to an error message, etc) but they all have drawbacks.
Is there an idiomatic way to do this?
Since nobody has had a better idea I'll leave my answer for future reference.
As said in the comment the best way is to create a error hierarchy:
trait GenericError { /* some commond fields */}
case class MyNumericError(/* fields */)
and then use leftMap on a validation to generate appropriate errors:
Validation.fromTryCatchNonFatal(...).leftMap(t => MyNumericError(...))
This approach has two advantages
First you will always have a Validation[GenericError, T] so not having different types on the left part of that validation
The second is that this helps generate meaningful errors for both developers and service user, also note that generating an error where you have many context informations helps in this process.

iterative lookup from within rdd.map in scala

def retrieveindex (stringlist: List[String], lookuplist: List[String]) =
stringlist.foreach(y => lookuplist.indexOf(y))
is my function.
I am trying to use this within an rdd like this:
val libsvm = libsvmlabel.map(x =>
Array(x._2._2,retrieveindex(x._2._1.toList,featureSet.toList)))
However, I am getting an output that is empty. There is no error, but the output from retrieveindex is empty. When I use println to see if I am retrieving correctly, I do see the indices printed. Is there any way to do this? Should I first 'distribute' the function to all the workers? I am a newbie.
retrieveindex has a return type of type Unit (because of foreach which just applies a function (String) ⇒ Unit on each element). Therefore it does not map to anything.
You probably want it to return the list of indices, like:
def retrieveindex(stringlist: List[String], lookuplist: List[String]): List[Int] =
stringlist.map(y => lookuplist.indexOf(y))

Scala Syntactic Sugar for converting to `Option`

When working in Scala, I often want to parse a field of type [A] and convert it to a Option[A], with a single case (for example, "NA" or "") being converted to None, and the other cases being wrapped in some.
Right now, I'm using the following matching syntax.
match {
case "" => None
case s: String => Some(s)
}
// converts an empty String to None, and otherwise wraps it in a Some.
Is there any more concise / idiomatic way to write this?
There are a more concise ways. One of:
Option(x).filter(_ != "")
Option(x).filterNot(_ == "")
will do the trick, though it's a bit less efficient since it creates an Option and then may throw it away.
If you do this a lot, you probably want to create an extension method (or just a method, if you don't mind having the method name first):
implicit class ToOptionWithDefault[A](private val underlying: A) extends AnyVal {
def optNot(not: A) = if (underlying == not) None else Some(underlying)
}
Now you can
scala> 47.toString optNot ""
res1: Option[String] = Some(47)
(And, of course, you can always create a method whose body is your match solution, or an equivalent one with if, so you can reuse it for that particular case.)
I'd probably use filterNot here:
scala> Option("hey").filterNot(_ == "NA")
res0: Option[String] = Some(hey)
scala> Option("NA").filterNot(_ == "NA")
res1: Option[String] = None
It requires you to think of Option as a collection with one or zero elements, but if you get into that habit it's reasonably clear.
A simple and intuitive approach includes this expression,
if (s.isEmpty) None else Some(s)
This assumes s labels the value to be otherwise matched (thanks to #RexKerr for the note).

Choosing a proper return type for a function returning a map of errors

I have a function which either should return Map[String, Seq[String]] as sequence of the errors with the keys (in case there are errors) or return success (probably, Unit). I wonder, what's the best return type for it?
def foo1(a: Int): Map[String, Seq[String]]
def foo2(a: Int): Option[Map[String, Seq[String]]]
def foo3(a: Int): Either[Map[String, Seq[String]], ???]
//def foo4(a: Int): something else?
If the first case, it would have to return Map["", Seq()] if there are no errors and, to my mind, it doesn't look elegant. In the second case, it would return None and that's ok but it seems redundant. The same for the third case, but there is one more issue - what would I return as Right?
What do you think?
The only problem with the first option is that it's easy to forget to check isEmpty on the return result. If most clients would naturally do the right thing with an empty map (e.g. because they just iterate on it, or get number of errors), this is the best one. Option 2 is acceptable if you name method something like getErrors (as #senia says), option 3 is as well (with Either[Map[String, Seq[String]], Unit]).