How to indiciate a failure for a function with a void result - scala

I have a function in scala which has no return-value (so unit). This function can sometimes fail (if the user provided parameters are not valid). If I were on java, I would simply throw an exception. But on scala (although the same thing is possible), it is suggested to not use exceptions.
I perfectly know how to use Option or Try, but they all only make sense if you have something valid to return.
For example, think of a (imaginary) addPrintJob(printJob: printJob): Unit command which adds a print job to a printer. The job definition could now be invalid and the user should be notified of this.
I see the following two alternatives:
Use exceptions anyway
Return something from the method (like a "print job identifier") and then return a Option/Either/Try of that type. But this means adding a return value just for the sake of error handling.
What are the best practices here?

You are too deep into FP :-)
You want to know whether the method is successful or not - return a Boolean!

According to this Throwing exceptions in Scala, what is the "official rule" Throwing exceptions in scala is not advised as because it breaks the control flow. In my opinion you should throw an exception in scala only when something significant has gone wrong and normal flow should not be continued.
For all other cases it generally better to return the status/result of the operation that was performed. scala Option and Either serve this purpose. imho A function which does not return any value is a bad practice.
For the given example of the addPrintJob I would return an job identifier (as suggested by #marstran in comments), if this is not possible the status of addPrintJob.

The problem is that usually when you have to model things for a specific method it is not about having success or failure ( true or false ) or ( 0 or 1 - Unit exit codes wise ) or ( 0 or 1 - true or false interpolation wise ) , but about returning status info and a msg , thus the most simplest technique I use ( whenever code review naysayers/dickheads/besserwissers are not around ) is that
val msg = "unknown error has occurred during ..."
val ret = 1 // defined in the beginning of the method, means "unknown error"
.... // action
ret = 0 // when you finally succeeded to implement FULLY what THIS method was supposed to to
msg = "" // you could say something like ok , but usually end-users are not interested in your ok msgs , they want the stuff to work ...
at the end always return a tuple
return ( ret , msg )
or if you have a data as well ( lets say a spark data frame )
return ( ret , msg , Some(df))
Using return is more obvious, although not required ( for the purists ) ...
Now because ret is just a stupid int, you could quickly turn more complex status codes into more complex Enums , objects or whatnot , but the point is that you should not introduce more complexity than it is needed into your code in the beginning , let it grow organically ...
and of course the caller would call like
( ret , msg , mayBeDf ) = myFancyFunc(someparam, etc)
Thus exceptions would mean truly error situations and you will avoid messy try catch jungles ...
I know this answer WILL GET down-voted , because well there are too much guys from universities with however bright resumes writing whatever brilliant algos and stuff ending-up into the spagetti code we all are sick of and not something as simple as possible but not simpler and of course something that WORKS.
BUT, if you need only ok/nok control flow and chaining, here is bit more elaborated ok,nok example, which does really throw exception, which of course you would have to trap on an upper level , which works for spark:
/**
* a not so fancy way of failing asap, on first failing link in the control chain
* #return true if valid, false if not
*/
def isValid(): Boolean = {
val lst = List(
isValidForEmptyDF() _,
isValidForFoo() _,
isValidForBar() _
)
!lst.exists(!_()) // and fail asap ...
}
def isValidForEmptyDF()(): Boolean = {
val specsAreMatched: Boolean = true
try {
if (df.rdd.isEmpty) {
msg = "the file: " + uri + " is empty"
!specsAreMatched
} else {
specsAreMatched
}
} catch {
case jle: java.lang.UnsupportedOperationException => {
msg = msg + jle.getMessage
return false
}
case e: Exception => {
msg = msg + e.getMessage()
return false
}
}
}
Disclaimer: my colleague helped me with the fancy functions syntax ...

Related

Creating Seq after waiting for all results from map/foreach in Scala

I am trying to loop over inputs and process them to produce scores.
Just for the first input, I want to do some processing that takes a while.
The function ends up returning just the values from the 'else' part. The 'if' part is done executing after the function returns the value.
I am new to Scala and understand the behavior but not sure how to fix it.
I've tried inputs.zipWithIndex.map instead of foreach but the result is the same.
def getscores(
inputs: inputs
): Future[Seq[scoreInfo]] = {
var scores: Seq[scoreInfo] = Seq()
inputs.zipWithIndex.foreach {
case (f, i) => {
if (i == 0) {
// long operation that returns Future[Option[scoreInfo]]
getgeoscore(f).foreach(gso => {
gso.foreach(score => {
scores = scores.:+(score)
})
})
} else {
scores = scores.:+(
scoreInfo(
id = "",
score = 5
)
)
}
}
}
Future {
scores
}
}
For what you need, I would drop the mutable variable and replace foreach with map to obtain an immutable list of Futures and recover to handle exceptions, followed by a sequence like below:
def getScores(inputs: Inputs): Future[List[ScoreInfo]] = Future.sequence(
inputs.zipWithIndex.map{ case (input, idx) =>
if (idx == 0)
getGeoScore(input).map(_.getOrElse(defaultScore)).recover{ case e => errorHandling(e) }
else
Future.successful(ScoreInfo("", 5))
})
To capture/print the result, one way is to use onComplete:
getScores(inputs).onComplete(println)
The part your missing is understanding a tricky element of concurrency, and that is that the order of execution when using multiple futures is not guaranteed.
If your block here is long running, it will take a while before appending the score to scores
// long operation that returns Future[Option[scoreInfo]]
getgeoscore(f).foreach(gso => {
gso.foreach(score => {
// stick a println("here") in here to see what happens, for demonstration purposes only
scores = scores.:+(score)
})
})
Since that executes concurrently, your getscores function will also simultaneously continue its work iterating over the rest of inputs in your zipWithindex. This iteration, especially since it's trivial work, likely finishes well before the long-running getgeoscore(f) completes the execution of the Future it scheduled, and the code will exit the function, moving on to whatever code is next after you called getscores
val futureScores: Future[Seq[scoreInfo]] = getScores(inputs)
futureScores.onComplete{
case Success(scoreInfoSeq) => println(s"Here's the scores: ${scoreInfoSeq.mkString(",")}"
}
//a this point the call to getgeoscore(f) could still be running and finish later, but you will never know
doSomeOtherWork()
Now to clean this up, since you can run a zipWithIndex on your inputs parameter, I assume you mean it's something like a inputs:Seq[Input]. If all you want to do is operate on the first input, then use the head function to only retrieve the first option, so getgeoscores(inputs.head) , you don't need the rest of the code you have there.
Also, as a note, if using Scala, get out of the habit of using mutable vars, especially if you're working with concurrency. Scala is built around supporting immutability, so if you find yourself wanting to use a var , try using a val and look up how to work with the Scala's collection library to make it work.
In general, that is when you have several concurrent futures, I would say Leo's answer describes the right way to do it. However, you want only the first element transformed by a long running operation. So you can use the future return by the respective function and append the other elements when the long running call returns by mapping the future result:
def getscores(inputs: Inputs): Future[Seq[ScoreInfo]] =
getgeoscore(inputs.head)
.map { optInfo =>
optInfo ++ inputs.tail.map(_ => scoreInfo(id = "", score = 5))
}
So you neither need zipWithIndex nor do you need an additional future or join the results of several futures with sequence. Mapping the future just gives you a new future with the result transformed by the function passed to .map().

Should 'require' go inside or outside of the Future?

How do I replace my first conditional with the require function in the context of a Future? Should I wrap the entire inRange method in a Future, and if I do that, how do I handle the last Future so that it doesn't return a Future[Future[List[UserId]], or is there a better way?
I have a block of code that looks something like this:
class RetrieveHomeownersDefault(depA: DependencyA, depB: DependencyB) extends RetrieveHomeowners {
def inRange(range: GpsRange): Future[List[UserId]] = {
// I would like to replace this conditional with `require(count >= 0, "The offset…`
if (count < 0) {
Future.failed(new IllegalArgumentException("The offset must be a positive integer.")
} else {
val retrieveUsers: Future[List[UserId]] = depA.inRange(range)
for (
userIds <- retrieveUsers
homes <- depB.homesForUsers(userIds)
) yield FilterUsers.withoutHomes(userIds, homes)
}
}
}
I started using the require function in other areas of my code, but when I tried to use it in the context of Futures I ran into some hiccups.
class RetrieveHomeownersDefault(depA: DependencyA, depB: DependencyB) extends RetrieveHomeowners {
// Wrapped the entire method with Future, but is that the correct approach?
def inRange(range: GpsRange): Future[List[UserId]] = Future {
require(count >= 0, "The offset must be a positive integer.")
val retrieveUsers: Future[List[UserId]] = depA.inRange(range)
// Now I get Future[Future[List[UserId]]] error in the compiler.
for (
userIds <- retrieveUsers
homes <- depB.homesForUsers(userIds)
) yield FilterUsers.withoutHomes(userIds, homes)
}
}
Any tips, feedback, or suggestions would be greatly appreciated. I'm just getting started with Futures and still having a tough time wrapping my head around many concepts.
Thanks a bunch!
Just remove the outer Future {...} wrapper. It's not necessary. There's no good reason for the require call to go inside the Future. It's actually better outside since then it will report immediately (in the same thread) to the caller that the argument is invalid.
By the way, the original code is wrong too. The Future.failed(...) is created but not returned. So essentially it didn't do anything.

How to stop the execution or throw an error in scala play framework

I'm developing a scala application with play framework, but i got something strange.
i can't stop the execution nor throwing an error in order to send a response for the client, it always continue the code and it always returning okay, however i made a dummy function that it should return a bad request but unfortunately it is returning OK here is what i wrote. any help will be appreciated
def foo(locale: String, orderId: Int) = Action { implicit request => {
val x=4+7;
if(x==11){
BadRequest(JsonHelper.convertToJson("Bad bad it is really bad "))
}
OK(JsonHelper.convertToJson("Well Done"))
}
}
the above code returning OK Well done.
To make your code return a BadRequest, add an else:
def foo(locale: String, orderId: Int) = Action { implicit request => {
val x = 4 + 7;
if (x == 11)
BadRequest(JsonHelper.convertToJson("Bad bad it is really bad "))
else // <---
OK(JsonHelper.convertToJson("Well Done"))
}}
Your problem is your if without curly braces.
refered to this link :https://docs.scala-lang.org/style/control-structures.html#curly-braces
if - Omit braces if you have an else clause. Otherwise, surround the
contents with curly braces even if the contents are only a single
line.
so you can just suuround the BadRequest with curly braces or add an else statement between your Bad and OK instruction. Be careful, don't forget the indentation !
edit 20/12/2017 >> un scala the last instruction is implicitly returned. Your last instruction is OK, so it returns OK.
Add explicit return statement in your if block or add an else statement.

how to compare expected value to be in the list [duplicate]

One of my test expects an error message text to be one of multiple values. Since getText() returns a promise I cannot use toContain() jasmine matcher. The following would not work since protractor (jasminewd under-the-hood) would not resolve a promise in the second part of the matcher, toContain() in this case:
expect(["Unknown Error", "Connection Error"]).toContain(page.errorMessage.getText());
Question: Is there a way to check if an element is in an array with jasmine+protractor where an element is a promise?
In other words, I'm looking for inverse of toContain() so that the expect() would implicitly resolve the promise passed in.
As a workaround, I can explicitly resolve the promise with then():
page.errorMessage.getText().then(function (text) {
expect(["Unknown Error", "Connection Error"]).toContain(text);
});
I'm not sure if this is the best option. I would also be okay with a solution based on third-parties like jasmine-matchers.
As an example, this kind of assertion exists in Python:
self.assertIn(1, [1, 2, 3, 4])
Looks like you need a custom matcher. Depending on the version of Jasmine you are using:
With Jasmine 1:
this.addMatchers({
toBeIn: function(expected) {
var possibilities = Array.isArray(expected) ? expected : [expected];
return possibilities.indexOf(this.actual) > -1;
}
});
With Jasmine 2:
this.addMatchers({
toBeIn: function(util, customEqualityTesters) {
return {
compare: function(actual, expected) {
var possibilities = Array.isArray(expected) ? expected : [expected];
var passed = possibilities.indexOf(actual) > -1;
return {
pass: passed,
message: 'Expected [' + possibilities.join(', ') + ']' + (passed ? ' not' : '') + ' to contain ' + actual
};
}
};
}
});
You'll have to execute this in the beforeEach section on each of your describe blocks it's going to be used in.
Your expect would look like:
expect(page.errorMessage.getText()).toBeIn(["Unknown Error", "Connection Error"]);
The alternative solution is to use .toMatch() matcher with Regular Expressions and specifically a special character | (called "or"), which allows to match only one entry to succeed:
expect(page.errorMessage.getText()).toMatch(/Unknown Error|Connection Error/);
To me, the work-around that you identified is the best solution. However, we should not forget that this is an asynchronous execution and you might want to consider Jasmine's asynchronous support.
Then, your test will look like the following one:
it('should check item is in array', function(done){ //Note the argument for callback
// do your stuff/prerequisites for the spec here
page.errorMessage.getText().then(function (text) {
expect(["Unknown Error", "Connection Error"]).toContain(text);
done(); // Spec is done!
});
});
Note: If you don't pass this done argument to the spec callback, it is going to run to completion without failures, but no assertions are going to be reported in the execution results for that spec (in other words, that spec will have 0 assertions) and it might lead to confusions.

Go: C like macros for writing test code

When writing test code, I do a lot of this
if (!cond) {
t.Fatal("error message")
}
It's a bit tedious. So I'd like to achieve the following
CHECK(cond, "error message")
So I attempted this
func CHECK(t *testing.T, cond bool, fmt string, a ...interface{}) {
if !cond {
t.Fatal(fmt, a)
}
}
If it were a C macro it would've worked perfectly. But in Go, the line number where the failure is is wrong.
Is there a fix for this?
Sadly you can't do that.
A workaround would be to get the line / function yourself, something like the trace function from https://stackoverflow.com/a/25954534/145587.
You could possibly make use of runtime.Callers()&plus;runtime.Caller(): the first one gives you the call stack while the second allows to extract the debug info about any arbitrary stack frame (obtained from that list).
Your CHECK() function is always one function call down the place the check should have happened at if it was a macro, so you can inspect the stack frame just above.
Update: the only functon which is really needed is runtime.Caller(). Here's your case, simplified:
package main
import (
"runtime"
"testing"
)
func CHECK(t *testing.T, cond bool) {
if !cond {
_, fname, lineno, ok := runtime.Caller(1)
if !ok {
fname, lineno = "<UNKNOWN>", -1
}
t.Fatalf("FAIL: %s:%d", fname, lineno)
}
}
func TestFoo(t *testing.T) {
CHECK(t, 12 == 13)
}
When saved as check_test.go and run via go test, it produces:
$ go test
--- FAIL: TestFoo (0.00 seconds)
check_test.go:14: FAIL: /home/kostix/devel/go/src/check/check_test.go:19
FAIL
exit status 1
FAIL check 0.001s
where line 19 is the line a call to CHECK() is located inside TestFoo().
While the above answer to use CHECK() function will work, I think that the actual answer is code readibility. Much of Go has been designed as a compromise to increase readibility among the community as a whole. See gofmt for example. Most people will agree that it's format is not best for every case. But having a convention agreed to by all is a huge plus for Go. The same answer is to your question. Go is for writing code for your peers, not for yourself. So don't think "I prefer this." Think "what will people reading my code understand."
Your original code should be like this, without parenthesis.
if !cond {
t.Fatal("error message")
}
This is idiomatic and every Go coder will recognize it instantly. That is the point.