I have the following code:
private def hasRole(role: String): Boolean = {
var hasRole = false;
if(getUserDetails.isDefined){
// getAuthorities returns java.util.Collection<GrantedAuthority>
val authorities: util.Collection[_ <:GrantedAuthority] = getUserDetails.get.getAuthorities
// Wrap the collection is a Scala class
val authoritiesWrapper = JCollectionWrapper.apply(authorities);
for(authority <- authoritiesWrapper.iterator){
if(authority.getAuthority == role){
hasRole = true;
scala.util.control.Breaks.break
}
}
}
hasRole
}
The question is, is scala.util.control.Breaks.break the correct way toreturn when I've found the role? Doesn't look right to me.
If you want to use breakable, you need to do it like so:
import scala.util.control.Breaks._
breakable {
for (i <- 0 to 10000) { if (i>3) break }
}
But if you find yourself doing that often, you're probably not using the collections library to its full extent. Try instead
authoritiesWrapper.iterator.exists(_.getAuthority == role)
Also, in the example you gave, you could also
if (authority.getAuthority == role) return true
When to choose which? In general, you should use the control-flow options in the collections library if you can. They generally are the fastest and clearest. Wait, fastest--why is that? Both break and return (from within a for or other context that requires a closure--basically anything but if and while and match) actually throw a stackless exception which is caught; in the break case it's caught by breakable and in the return case it's caught by the method. Creating a stack trace is really slow, but even stackless exceptions are kind of slow.
So using the correct collections method--exists in this case--is the best solution.
The question is, is scala.util.control.Breaks.break the correct way
toreturn when I've found the role? Doesn't look right to me.
Since your just looking for the first instance of authority.getAuthority == role you can use find which does exactly that and is the idiomatic way to do this.
authoritiesWrapper.iterator.find(authority => authority.getAuthority == role)
or more concisely
authoritiesWrapper.iterator.find(_.getAuthority == role)
These return an Option type which you can get the value of authority from if it exists.
I can only offer you generalities, but I hope it's at least a little helpful...
Unfortunately, your sample code contains free identifiers, so it's not possible for me to understand what it does without guessing and assuming.
You're thinking about the problem wrong. What is it you're doing here? You're finding a element of a collection. Use the library! It has all manner of such things off-the-shelf.
When it comes to dealing with Option[Something] the preferred approach is to map over it. If it's a None, you get a None out. If it's Some(thing) then the function you pass to map will be applied to thing and the result will be Some(what-your-function-returned-for-thing).
Alternatively, and what newcomers to Scala often find more palatable, you can use pattern matching on an Option to effectively distinguish the None case from the Some(thing) case.
When it comes to dealing with Java libraries, it's best to push the conversions from and to the Java collections to the very periphery of your code and keep the bulk of your code idiomatic Scala using native Scala collections.
The same goes for nulls coming from Java. Turn them into Option at the earliest possible time. As a convenience, the Option(thing) factory will turn a thing that is null into a None and wrap a non-null thing in a Some
Addendum
The upshot is that you really should not be using these control flow mechanisms in this code. They're all based on exceptions (other than return) and are rather at odds with Scala's emphasis on using functional programming. The library supports a clean, succinct, efficient implementation of the essetial logic you're trying for. Don't go against the grain like this.
Why not just return true and return false replacing hasRole?
Thanks Everyone, based on #Rex Kerr answer I now have this:
private def hasRole(role: String): Boolean = {
var hasRole: Boolean = false;
if(getUserDetails.isDefined){
val authorities: util.Collection[_ <:GrantedAuthority] = getUserDetails.get.getAuthorities
val authoritiesWrapper = JCollectionWrapper.apply(authorities);
hasRole = authoritiesWrapper.iterator.exists(_.getAuthority == role)
}
hasRole
}
which seems to look and feel right. I'm using exists to see of the role exists in the collection and then returning that result. By default false is returned if the user is not defined (not logged in).
Please comment if this is still not perfect.
Related
First of all, I'm very new to Scala and don't have any experience writing production code with it, so I lack understanding of what is considered a good/best practice among community. I stumbled upon these resources:
https://github.com/alexandru/scala-best-practices
https://nrinaudo.github.io/scala-best-practices/
It is mentioned there that throwing exceptions is not very good practice, which made me think what would be a good way to define preconditions for function then, because
A function that throws is a bit of a lie: its type implies it’s total function when it’s not.
After a bit of research, it seems that using Option/Either/Try/Or(scalactic) is a better approach, since you can use something like T Or IllegalArgumentException as return type to clearly indicate that function is actually partial, using exception as a way to store message that can be wrapped in other exceptions.
However lacking Scala experience I don't quite understand if this is actually viable approach for a real project or using Predef.require is a way to go. I would appreciate if someone explained how things are usually done in Scala community and why.
I've also seen Functional assertion in Scala, but while the idea itself looks interesting, I think PartialFunction is not very suitable for the purpose as it is, because often more than one argument is passed and tuples look like a hack in this case.
Option or Either is definitely the way to go for functional programming.
With Option it is important to document why None might be returned.
With Either, the left side is the unsuccessful value (the "error"), while the right side is the successful value. The left side does not necessarily have to be an Exception (or a subtype of it), it can be a simple error message String (type aliases are your friend here) or a custom data type that is suitable for you application.
As an example, I usually use the following pattern when error handling with Either:
// Somewhere in a package.scala
type Error = String // Or choose something more advanced
type EitherE[T] = Either[Error, T]
// Somewhere in the program
def fooMaybe(...): EitherE[Foo] = ...
Try should only be used for wrapping unsafe (most of the time, plain Java) code, giving you the ability to pattern-match on the result:
Try(fooDangerous()) match {
case Success(value) => ...
case Failure(value) => ...
}
But I would suggest only using Try locally and then go with the above mentioned data types from there.
Some advanced datatypes like cats.effect.IO or monix.reactive.Observable contain error handling natively.
I would also suggest looking into cats.data.EitherT for typeclass-based error handling. Read the documentation, it's definitely worth it.
As a sidenote, for everyone coming from Java, Scala treats all Exceptions as Java treats RuntimeExceptions. That means, even when an unsafe piece of code from one of your dependencies throws a (checked) IOException, Scala will never require you to catch or otherwise handle the exception. So as a rule of thumb, when using Java - dependencies, almost always wrap them in a Try (or an IO if they execute side effects or block the thread).
I think your reasoning is correct. If you have a simple total (opposite of partial) function with arguments that can have invalid types then the most common and simple solution is to return some optional result like Option, etc.
It's usually not advisable to throw exceptions as they break FP laws. You can use any library that can return a more advanced type than Option like Scalaz Validation if you need to compose results in ways that are awkward with Option.
Another two alternatives I could offer is to use:
Type constrained arguments that enforce preconditions. Example: val i: Int Refined Positive = 5 based on https://github.com/fthomas/refined. You can also write your own types which wrap primitive types and assert some properties. The problem here is if you have arguments that have multiple interdependent valid values which are mutually exclusive per argument. For instance x > 1 and y < 1 or x < 1 and y > 1. In such case you can return an optional value instead of using this approach.
Partial functions, which in the essence resemble optional return types: case i: Int if i > 0 => .... Docs: https://www.scala-lang.org/api/2.12.1/scala/PartialFunction.html.
For example:
PF's def lift: (A) ⇒ Option[B] converts PF to your regular function.
Turns this partial function into a plain function returning an Option
result.
Which is similar to returning an option. The problem with partial functions that they are a bit awkward to use and not fully FP friendly.
I think Predef.require belongs to very rare cases where you don't want to allow any invalid data to be constructed and is more of a stop-everything-if-this-happens kind of measure. Example would be that you get arguments you never supposed to get.
You use the return type of the function to indicate the type of the result.
If you want to describe a function that can fail for whatever reason, of the types you mentioned you would probably return Try or Either: I am going to "try" to give your a result, or I am going to return "either" a success or an failure.
Now you can specify a custom exception
case class ConditionException(message: String) extends RuntimeException(message)
that you would return if your condition is not satisfied, e.g
import scala.util._
def myfunction(a: String, minLength: Int): Try[String] = {
if(a.size < minLength) {
Failure(ConditionException(s"string $a is too short")
} else {
Success(a)
}
}
and with Either you would get
import scala.util._
def myfunction(a: String, minLength: Int): Either[ConditionException,String] = {
if(a.size < minLength) {
Left(ConditionException(s"string $a is too short")
} else {
Right(a)
}
}
Not that the Either solution clearly indicates the error your function might return
I'm currently working on my functional programming - I am fairly new to it. Am i using Options correctly here? I feel pretty insecure on my skills currently. I want my code to be as safe as possible - Can any one point out what am I doing wrong here or is it not that bad? My code is pretty straight forward here:
def main(args: Array[String]): Unit =
{
val file = "myFile.txt"
val myGame = Game(file) //I have my game that returns an Option here
if(myGame.isDefined) //Check if I indeed past a .txt file
{
val solutions = myGame.get.getAllSolutions() //This returns options as well
if(solutions.isDefined) //Is it possible to solve the puzzle(crossword)
{
for(i <- solutions.get){ //print all solutions to the crossword
i.solvedCrossword foreach println
}
}
}
}
-Thanks!! ^^
When using Option, it is recommended to use match case instead of calling 'isDefined' and 'get'
Instead of the java style for loop, use higher-order function:
myGame match {
case Some(allSolutions) =>
val solutions = allSolutions.getAllSolutions
solutions.foreach(_.solvedCrossword.foreach(println))
case None =>
}
As a rule of thumb, you can think of Option as a replacement for Java's null pointer. That is, in cases where you might want to use null in Java, it often makes sense to use Option in Scala.
Your Game() function uses None to represent errors. So you're not really using it as a replacement for null (at least I'd consider it poor practice for an equivalent Java method to return null there instead of throwing an exception), but as a replacement for exceptions. That's not a good use of Option because it loses error information: you can no longer differentiate between the file not existing, the file being in the wrong format or other types of errors.
Instead you should use Either. Either consists of the cases Left and Right where Right is like Option's Some, but Left differs from None in that it also takes an argument. Here that argument can be used to store information about the error. So you can create a case class containing the possible types of errors and use that as an argument to Left. Or, if you never need to handle the errors differently, but just present them to the user, you can use a string with the error message as the argument to Left instead of case classes.
In getAllSolutions you're just using None as a replacement for the empty list. That's unnecessary because the empty list needs no replacement. It's perfectly fine to just return an empty list when there are no solutions.
When it comes to interacting with the Options, you're using isDefined + get, which is a bit of an anti pattern. get can be used as a shortcut if you know that the option you have is never None, but should generally be avoided. isDefined should generally only be used in situations where you need to know whether an option contains a value, but don't need to know the value.
In cases where you need to know both whether there is a value and what that value is, you should either use pattern matching or one of Option's higher-order functions, such as map, flatMap, getOrElse (which is kind of a higher-order function if you squint a bit and consider by-name arguments as kind-of like functions). For cases where you want to do something with the value if there is one and do nothing otherwise, you can use foreach (or equivalently a for loop), but note that you really shouldn't do nothing in the error case here. You should tell the user about the error instead.
If all you need here is to print it in case all is good, you can use for-comprehension which is considered quite idiomatic Scala way
for {
myGame <- Game("mFile.txt")
solutions <- myGame.getAllSolutions()
solution <- solutions
crossword <- solution.solvedCrossword
} println(crossword)
I'm a fairly new Scala developer. I am an experienced Java developer and so far I've been enjoying Scala's simplicity. I really like the functional constructs and quite often they force you to write cleaner code. However recently I noticed due to comfort and simplicity I end up using constructs I wouldn't necessarily use in Java and would actually be considered a bad practice e.g.
private def convertStringToSourceIds(value: String) : Seq[Integer] = {
Try(value.split(",").toSeq.map(convertToSourceId(_))).getOrElse(Seq())
}
The same code snippet can be written as
private def convertStringToSourceIds(value: String) : Seq[Integer] = {
if(value!=null) value.split(",").toSeq.map(convertToSourceId(_)) else Seq()
}
A part of me realizes that the Try/getOrElse block is designed with Options in mind but quite often it makes code more readable and handles cases you might have missed (which of course isn't always a good thing).
I would be interested to know what is the opinion of an experienced Scala developer on the matter.
I am not claiming any "experience" title but I much prefer your second construct for a few reasons
Throwing an exception (an NPE in this case) is expensive and best avoided; it should remain just that, exceptional
if are expressions in Scala, which avoids declaring "dangling" variables to hold the result of the test (just like ternary operators). Alternatively the match..case construct provides for very readable code.
I would personally return an Option[Seq[Integer]] to "pass back" the information that the values was null and facilitate further chaining of your function.
Something like
private def convertStringToSourceIds(value: String) : Option[Seq[Integer]] = value match {
case null => None
case _ => Some(value.split(",").map(convertToSourceId(_)))
}
note 1: not sure you need the toSeq
note 2: for good or bad, looks a bit Haskellish
The combination of Scala + FP makes it almost doubly certain you will get different opinions :)
Edit
Please read comments below for additional reasons and alternatives, i.e,
def convertStringToSourceIds(value: String): Option[Array[String]] = Option(value).map(_.split(",").map(convertToSourceId(_)))
If you can, use Options instead of null to show when a value is missing.
Assuming that you can't use Options, a more readable way to handle this could be
private def convertStringToSourceIds(value: String) : Seq[Integer] = value match {
case null => Seq();
case s => s.split(",").toSeq.map(convertToSourceId(_));
}
This is purely a coding-style question.
A function I'm calling returns an Option, and I want to take a specific action if it's equal to None.
Say, for example, that I'm trying to create a default user at boot time if it doesn't already exist. I'd call a function that attempts to find a user that matches the default one, and returns an Option[User].
If that return value is None, I'd like to run some user creation code. If not, I'm done.
I'm wondering what's the most idiomatic Scala syntax for this. What I have so far is:
def getUser(name: String): Option[User] = ...
getUser("admin") getOrElse createUser("admin", "ChangeThisNow!")
getUser("admin") match {
case None => createUser("admin", "ChangeThisNow!")
case _ =>
}
if(getUser("admin") == None) createUser("admin", "ChangeThisNow!")
The first solution seems like the most functional one, but I can't help but feel that there might be better ones - possibly by using partially applied functions, which I admit I'm still a bit fuzzy about.
Since in your case the goal is to cause a side effect, I'd use a conditional to stress that, instead of using getOrElse.
if (getUser("admin").isEmpty)
createUser("admin", "ChangeThisNow!")
Remember that scala is a multi-paradigm language.
In addition to syntax, you want to consider concepts such as cohesion (single responsibility) and so you can consider the composition of your objects in addition to the actual idioms you use in the syntax.
The OO way might be to decorate the object/class that getUser belongs to in to put that concern of creating the user in a wrapper so that other code that calls the getUser function never has to deal with that concern. This fits nicely with open/closed principle and single responsibility. This is a bit of an anemic domain model anti-pattern here but may show how OO can be used to extend the conversation into actual design.
Either pattern matching or getOrElse are reasonable solutions. Generally if statements aren't used against Monads like the option - at least not that I see.
Either way, I beleive the expression should return the result even if there are side effects (user creation).
case class User(name: String)
class UserService {
def getUser(name: String): Option[User] = ???
def createUser(name: String): User = ???
}
class UserServiceDecorator extends UserService {
override def getUser(name: String): Option[User] =
Some(super.getUser(name).getOrElse(super.createUser(name)))
}
Really the best way to do this is to assign the result to a meaningful variable name so your future code doesn't need to know if createUser was called or not.
val user = getUser("admin").getOrElse(createUser("admin", "ChangeThisNow!"))
This way you can use the user variable regardless of if you've created a new user or not.
I see this type of pattern (found this example here) quite often in Scala:
class UserActor extends Actor {
def receive = {
case GetUser(id) =>
// load the user, reply with None or Some(user)
val user: Option[User] = ...
sender ! user
case FindAll() =>
// find all users
val users: List[User] = ...
sender ! users
case Save(user) =>
// persist the user
sender ! Right(user)
}
}
So depending on the call you get: Option[User], List[User], Right[User]. This approach is fine! I'm just asking out of interest if this is optimal? For example (and this may be a bad one): Will it make API's better or worse to try and generalise by always returning List[User]? So when a user is not found or if a save fails, then the list will simply be empty. I'm just curious.... any other suggestions on how the above 'pattern' may be improved?
I'm just trying to identify a perfect pattern for this style of API where you sometimes get one entity and sometimes none and sometimes a list of them. Is there a 'best' way to do this, or does everyone role their own?
The return types should help clarify your API's intended behavior.
If GetUser returned a List, developers might get confused and wonder if multiple users could possibly be returned. When they see that an Option is returned, they will immediately understand the intended behavior.
I once had to work with a fairly complex API which provided CRUD operations that had been generalized in the manner you describe. I found it to be difficult to understand, vaguely defined, and hard to work with.
In my opinion it is a very good pattern for API design.
I use very often Option as return type of my functions, if I want to return a single element, obviously because I don't need to deal with null. Returning a Seq is naturally for multiple elements and Either is optimal if you want to return a failure-description, I use it often while parsing I/O. Sometimes I even combine the Seq with one of the others. You likely don't know the preferences and goals of an user of your API, so it makes sence to provide all of these return-types to make the user feel as comfortable as possible.