How to use function in Scala for loop - scala

I have code like this:
case class State(state:Long=0,time:Long=0)
def funtionA(int a):Either[error, State]
var a = 123
val inloop = new Breaks
for (s <- funtionA(a) ) {
if (s.state == 1) {
println(s.state )
println("ok")
inloop.break()
}
else {
println( s.state )
println("not ok")
}
}
How to resolve functionA just run one time? I need to run funtionA(a) continue to know s.state ok.

The way to do this loop in a functional language is with a recursive function:
def loop(a: Int): Unit =
funtionA(a) match {
case Right(s) =>
println(s.state)
if (s.state == 1) {
println("ok")
} else {
println("not ok")
loop(a)
}
case Left(e) =>
println(s"error $e")
}
loop(123)
However it looks like this is polling another thread which is not a good idea. Look at using something like Future or Akka Actors to manage the multi-threading.

Related

How to test a Try[T] in ScalaTest correctly?

I've checked the answers specified in the post
How to test a Try[T] with ScalaTest correctly?
But if I had to do any assertions after the function call or if I have to check the assertions within a for { } yield { } block then I'm following the below given approach:
def test(a: Int, b: Int): Try[Int] = Try {
a / b
}
it.should("succeed").in {
(for {
res <- test(0, 1)
} yield {
assert(res === 0)
// assume more assertions are to be made
}) match {
case Success(value) => value
case Failure(exception) => fail(exception)
}
}
it.should("fail").in {
test(1, 0).failure.exception.getClass.mustBe(classOf[java.lang.ArithmeticException])
}
The problem with above approach is that, for the success case if any issue happens in the unit test logic then it'll show the error pointing to the line case Failure(exception) => fail(exception) and not on the line where the actual error occurred. If the test case is huge then it'll be difficult for the user to find where exactly the error occurred.
So is there a better way to unit test the functions which returns a Try[T] without moving the assertions outside the for { } yield { } block?
The TryValues trait (documented here) is designed to help with this:
class MyTestSpec extends FlatSpec with Matchers with TryValues {
"tryTest" should "succeed" in {
// Normal tests
test(0, 1).isSuccess shouldBe true
test(1, 1).isFailure shouldBe true
// Use TryValues conversions
test(0, 1).success.value shouldBe 0
test(1, 1).failure.exception should have message "should be zero"
}
}

How not to lose the asynchronous call?

How not to lose the asynchronous call anotherService.doSomething(res) ? Otherwise I'm not sure the piece of code will execute.
myDAO.update(param).map { // update() returns Future[Option[Object]]
case Some(row) =>
if (row.active) {
myDAO.selectUser(size).map { //selectUser() returns Future[Option[User]]
case Some(res) =>
anotherService.doSomething(res) //doSomething() returns Future[StandaloneWSResponse] but this line might not run without being able to keep track. This is my problem
case _ => Left(Wrong)
}
}
Right(...)
case None => Left(Wrong)
}
}
My idea is to store the result of the if and doing something like this:
val v = if (row.active) {
myDAO.selectUser(size).map { //selectUser() returns Future[Option[User]]
case Some(res) =>
anotherService.doSomething(res) //doSomething() returns Future[StandaloneWSResponse]
case _ => Left(Wrong)
}
Future.successful(v)
You can use scalaz and for-comprehension to make sure what is that did not work there.
import scalaz._
val result = for {
updateObjResultOpt <- myDAO.update(param).toRightDisjunction("error when Update")
if(updateObjReesurtOpt.filter(_.active).nonEmpty)
userOptional <- myDAO.selectUser(size).toRightDisjunction("error when select user")
if(userOptional.nonEmpty)
otherResult <- anotherService.doSomething(res).toRightDisjunction("error when execute doSomething")
} yield otherResult
// if you want return Future[ValidationNel[String, StandaloneWSResponse]]
val validationNelResult = result.fold(error => Failure(NonEmptyList(error)), otherResult => Success(otherResult))
// if you want to return the Future[result], you can use pattern matching
val futureResult = validationNelResult.match {
case Success(data) => Ok("success")
case Failure(error) => BadRequest(error)
case _ => BadRequest("other error")
}
I have not compiled it yet but I think it will working...
Using a for-comprehension is more idiomatic, you just need to provide a value for each None:
for {
rowOpt <- myDAO.selectUser(size)
userOpt <- rowOpt.filter(_.active).fold(Future.successful(Option.empty[...])) {row =>
myDAO.selectUser(size)
}
resultOpt <- userOpt.fold(Future.succesful(Option.empty[...])) {user =>
anotherService.doSomething(res)
}
} yield resultOpt.toEither(Wrong)
Something like that.

closing file pointer in Scala in Finally

In the following code, I am reading no. of lines from a file. If something goes wrong, I'll like to close the file pointer. But how can I find out if f contains valid pointer or not?
def countLines(filename:String):Option[Int] = {
try{
val f = Source.fromFile(filename)
println(s"no. of lines ${f.getLines().size}")
Some(f.getLines.size)
} catch {
case ex: FileNotFoundException => {
println(s"file ${filename} not found")
None
}
} finally {
//f might not be a valid pointer depending on when the error occured
}
}
The book I am reading uses var to maintain state (if f is valid or not) but I am trying to avoid it for sake of using only immutable variables.
def countLines(filename:String):Option[Int] = {
var f:Option[Source] = None
try{
f = Some(Source.fromFile(filename))
println(s"no. of lines ${f.get.getLines().size}")
Some(f.get.getLines.size)
} catch {
case ex: FileNotFoundException => {
println(s"file ${filename} not found")
None
}
} finally {
for(i<-f){
println("closing file")
i.close()
}
}
}
A double Try(). This closes the io resource even if the getLines() fails, but only if the fromFile() succeeds.
import scala.util.Try
def countLines(filename: String): Option[Int] =
Try(io.Source.fromFile(filename)).fold(_ => None, {f =>
val count = Try(f.getLines().length)
f.close()
count.toOption
})
What do you think about this?
If you want Scala-way - i think it's good example for your task:
def countLines(filename: String): Try[Int] = Try(Source.fromFile(filename).getLines.toList.size)
def test() = {
val filename = "/etc/passwd"
countLines(filename) match {
case Success(n) => println(n)
case Failure(f) => println(f)
}
}
When n - is a number of our lines, and f - is a Throwable.
How about this:
def countLines(filename: String): Option[Int] = {
val file = Try(Source.fromFile(filename))
val count = file.map(_.getLines().size)
(for {
_ <- count.recoverWith { case _ => file.map(_.close()) }
lineCount <- count
} yield lineCount).toOption
}
Let's analyze it:
If file does not exist we will have failed Try instance and method returns None. In this case you do not need to clear any resources as no actual stream was created.
If getLines fails for any reason or anything else during processing goes south we will close created stream in first line of for comprehension
Hope it helps
Simply, how about this:
def numLines(fileName:String):Option[Int] = {
try {
val f = scala.io.Source.fromFile(fileName)
try { Some(f.getLines.size) }
catch { case ex: IOException =>
Console.err.println("i/o excetion")
None
}
finally { f.close() }
}
catch {
case ex: FileNotFoundException =>
Console.err.println("file not found")
None
}
}

Primitive Try/match handling in scala

I wrote the following piece of code
def info(): MyCaseClass = {
Try {
val fileSys = new File("somePath")
MyCaseClass(fileSys.getTotalSpace, fileSys.getUsableSpace)
} match {
case Failure(f) => {
logger.error(s"Could not read information:${f.getStackTrace}")
MyCaseClass(0, 0)
}
case Success(s) => s
}
}
Is there an even shorter way to deal with the fact that the file system operation could result in an exception so I handle it as above. Like can I not just somehow have to deal with failure case only. Like in case of Future exceptions, the future just does what it has to but for exceptions only we define recover and recoverWith. Something analogous is possible here?
Simply use try instead of Try:
def info(): MyCaseClass = {
try {
val fileSys = new File("somePath")
MyCaseClass(fileSys.getTotalSpace, fileSys.getUsableSpace)
} catch {
case f: Throwable => {
logger.error(s"Could not read information:${f.getStackTrace}")
MyCaseClass(0, 0)
}
}
}
Try has recover as well:
def info(): MyCaseClass = {
(Try {
val fileSys = new File("somePath")
MyCaseClass(fileSys.getTotalSpace, fileSys.getUsableSpace)
} recover {
case f =>
logger.error(s"Could not read information:${f.getStackTrace}")
MyCaseClass(0, 0)
}).get
}
.getOrElse seems to be what you are looking for:
def info(): MyCaseClass = {
Try {
val fileSys = new File("somePath")
MyCaseClass(fileSys.getTotalSpace, fileSys.getUsableSpace)
}.getOrElse({
logger.error(s"Could not read information:${f.getStackTrace}")
MyCaseClass(0, 0)
})
}

Executing a code block even after catching an exception in Scala

In my current method, I am trying to make a series of calls and if any of them fail, I want to be able to continue running the remainder (while capturing the Exception that was thrown). I am having a hard time figuring this out in Scala.
So in this example, I want to kick off each of these calls - RunA, RunB and RunC but if RunB throws an exception, I want to print that and continue kicking off RunC after that.
var result = Try {
new RunA()
new RunB()
new RunC()
} catch {
case e: Throwable => e.printStackTrace()
false
}
Outside of having them all individually wrapped in a Try/Catch, I am sure there are better ways to do this which is why I am hoping someone can help with this.
I looked at the 'Ignoring' exception but it appears to completely ignore the exception which I want to atleast log.
Thanks!
First, don't mix try { ... } catch { ... } up with scala.util.Try{ ... }.
You can
import scala.util._
val runA = Try{ new RunA }
val runB = Try{ new RunB }
val runC = Try{ new RunC }
and then deal with the exceptions as you see fit. For instance, if you want to print and continue, you could deal with the try statements right there:
def getOrPrint[A](f: => A): Option[A] = Try{ f } match {
case Success(x) => Some(x)
case Failure(e) => e.printStackTrace; None
}
getOrPrint{ new RunA }
...
There can be more elegant ways for such things with scalaz (e.g. read an article here for some inspiration: http://johnkurkowski.com/posts/accumulating-multiple-failures-in-a-ValidationNEL/), but with "only" Scala you can do something like this:
import scala.reflect.ClassTag
import scala.util.{Try, Success, Failure}
def tryAndLog[T: ClassTag] = Try {
implicitly[ClassTag[T]].runtimeClass.newInstance.asInstanceOf[T] // new instance
} match {
case Success(_) => true
case Failure(ex) => ex.printStackTrace ; false
}
def tryRunAll = {
val A = tryAndLog[RunA]
val B = tryAndLog[RunB]
val C = tryAndLog[RunC]
A && B && C // returns true if all invocations succeeded, false otherwise
}
You are mixing scala.util.Try with try {} catch {} which are different concepts. Try wraps function into Success(result) or Failure(error) class, and try-catch is like Java try-catch. I suggest you something like this:
class RunA
class RunB
class RunC
class Result(a: RunA, b: RunB, c: RunC)
implicit class LogFailure[T](t: Try[T]) {
def logFailure: Try[T] = t match {
case scala.util.Failure(err) => err.printStackTrace(); t
case _ => t
}
}
val tryA= Try(new RunA())
val tryB= Try(new RunB())
val tryC = Try(new RunC())
val result: Try[Result] = for {
a <- tryA.logFailure
b <- tryB.logFailure
c <- tryC.logFailure
} yield {
// do smth with a, b, c
new Result(a, b, c)
}
If A, B, C will be successful you'll get Success(Result) if one of them failure you'll get Failure with first exception, however all of them will be logged (printed stack trace)