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.
Related
I'm admittedly very new to Scala, and I'm having trouble with the syntactical sugar I see in many Scala examples.
It often results in a very concise statement, but honestly so far (for me) a bit unreadable.
So I wish to take a typical use of the Option class, safe-dereferencing, as a good place to start for understanding, for example, the use of the underscore in a particular example I've seen.
I found a really nice article showing examples of the use of Option to avoid the case of null.
https://medium.com/#sinisalouc/demystifying-the-monad-in-scala-cc716bb6f534#.fhrljf7nl
He describes a use as so:
trait User {
val child: Option[User]
}
By the way, you can also write those functions as in-place lambda
functions instead of defining them a priori. Then the code becomes
this:
val result = UserService.loadUser("mike")
.flatMap(user => user.child)
.flatMap(user => user.child)
That looks great! Maybe not as concise as one can do in groovy, but not bad.
So I thought I'd try to apply it to a case I am trying to solve.
I have a type Person where the existence of a Person is optional, but if we have a person, his attributes are guaranteed. For that reason, there are no use of the Option type within the Person type itself.
The Person has an PID which is of type Id. The Id type consists of two String types; the Id-Type and the Id-Value.
I've used the Scala console to test the following:
class Id(val idCode : String, val idVal : String)
class Person(val pid : Id, val name : String)
val anId: Id = new Id("Passport_number", "12345")
val person: Person = new Person(anId, "Sean")
val operson : Option[Person] = Some(person)
OK. That setup my person and it's optional instance.
I learned from the above linked article that I could get the Persons Id-Val by using flatMap; Like this:
val result = operson.flatMap(person => Some(person.pid)).flatMap(pid => Some(pid.idVal)).getOrElse("NoValue")
Great! That works. And if I infact have no person, my result is "NoValue".
I used flatMap (and not Map) because, unless I misunderstand (and my tests with Map were incorrect) if I use Map I have to provide an alternate or default Person instance. That I didn't want to have to do.
OK, so, flatMap is the way to go.
However, that is really not a very concise statement.
If I were writing that in more of a groovy style, I guess i'd be able to do something like this:
val result = person?.pid.idVal
Wow, that's a bit nicer!
Surely Scala has a means to provide something at least nearly as nice as Groovy?
In the above linked example, he was able to make his statement more concise using some of that syntactical sugar I mentioned before. The underscore:
or even more concise:
val result = UserService.loadUser("mike")
.flatMap(_.child)
.flatMap(_.child)
So, it seems in this case the underscore character allows you to skip specifying the type (as the type is inferred) and replace it with underscore.
However, when I try the same thing with my example:
val result = operson.flatMap(Some(_.pid)).flatMap(Some(_.idVal)).getOrElse("NoValue")
Scala complains.
<console>:15: error: missing parameter type for expanded function ((x$2) => x$2.idVal)
val result = operson.flatMap(Some(_.pid)).flatMap(Some(_.idVal)).getOrElse("NoValue")
Can someone help me along here?
How am I misunderstanding this?
Is there a short-hand method of writing my above lengthy statement?
Is flatMap the best way to achieve what I am after? Or is there a better more concise and/or readable way to do it ?
thanks in advance!
Why do you insist on using flatMap? I'd just use map for your example instead:
val result = operson.map(_.pid).map(_.idVal).getOrElse("NoValue")
or even shorter:
val result = operson.map(_.pid.idVal).getOrElse("NoValue")
You should only use flatMap with functions that return Options. Your pid and idVals are not Options, so just map them instead.
You said
I have a type Person where the existence of a Person is optional, but if we have a person, his attributes are guaranteed. For that reason, there are no use of the Option type within the Person type itself.
This is the essential difference between your example and the User example. In the User example, both the existence of a User instance, and its child field are options. This is why, to get a child, you need to flatMap. However, since in your example, only the existence of a Person is not guaranteed, after you've retrieved an Option[Person], you can safely map to any of its fields.
Think of flatMap as a map, followed by a flatten (hence its name). If I mapped on child:
val ouser = Some(new User())
val child: Option[Option[User]] = ouser.map(_.child)
I would end up with an Option[Option[User]]. I need to flatten that to a single Option level, that's why I use flatMap in the first place.
If you looking for the most concise solution, consider this:
val result = operson.fold("NoValue")(_.pid.idVal)
Though one could find it not clear or confusing
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(_));
}
Reading Martin's book, chapter about equality Object equality chapter one may notice that properly implementing equals in scala (as actually in any other language) is not very straightforward. However scala is extremely powerful and agile, and I cannot believe it could not simplify things a bit. I know that scala generates proper equals for case classes, so I wonder why couldn't it generate simplifications for normal classes?
To show my point, I wrote an example of how would I see this should look like. It probably has flaws, and I had to use ClassTag which I know is very wrong for such basic thing as equals due to performance (any tip how could I do it without ClassTag?), but thinking that scala can generate proper equals for case classes, I'd say it should be able to generate proper code for normal classes, giving that developer provides the Key which should be used to compare objects.
trait Equality[T] extends Equals {
val ttag: ClassTag[T]
def Key: Seq[Any]
def canEqual(other: Any): Boolean = other match {
case that: Equality[_] if that.ttag == ttag => true
case _ => false
}
override def equals(other: Any): Boolean =
other match {
case that: Equality[T] => canEqual(that) && Key == that.Key
case _ => false
}
override def hashCode = Key.foldLeft(1)((x, y) => 41 * x + y.hashCode)
}
Then you can use it like this:
class Point(val x: Int, val y: Int)(implicit val ttag: ClassTag[Point]) extends Equality[Point]{
override def Key: Seq[Any] = Seq(x, y)
}
I'm not very much into ClassTags, so I might have made it wrong, but it seems to be working. Still that's not what I am asking - I want to know is there any serious reasons, why scala itself do not simplify implementing equality checks?
It is an interesting idea, and I can see from a comment that scalaz has something like this. I'm not sure I have a complete answer, but some factors to consider are:
Case classes are a bit unique in that you're not supposed to inherit from them. Assuming they're not sub-classed, canEqual isn't even required.
There's something elegant about the idea that even '+' in scala is a function not a 'language feature.' It's not necessarily better to have this as a language feature instead of a library (and there are a number of utilities even in Java to help with implementing hashcode/equals). The existing "equals" method isn't a language feature, it's just a method on the parent class Object, inherited from Java.
Scala does still need to play-nice with Java, and that could be one barrier to radically changing how equals works. Interface requirements can't be imposed on existing Java classes that scala might want to inherit from.
When you do consider what the syntax might look like if it were a language feature, I'm not sure what could actually be eliminated or changed.
For example, the developer still has to specify the Key you suggest. Also, to be able to support, for example, anonymous subclasses and trait mix-ins where canEqual won't change, with a language feature you'd still need to explicitly define your class tag.
Maybe the analysis could be more interesting if you provide what, syntactically, it might look like if it were a language feature instead of a helper library. I might be missing some aspects of how this would work.
There is no such thing "proper equals" since it depends on the use cases.
For simple cases what you suggest may work, but in such case, using case class with also work. The problem is that while for simple Data classes it works, the same isn't true for other cases. For example, when there are inheritance - what is the right thing to do? if class have private members - does it should be part of the equals?? does public getters should be ? What will happen when when there are cyclic dependencies ?
One of the main reasons for the case classes cannot be inherit by other case class is the equality.
AFAIK, Iterator.map is lazy while Vector.map is eager, basically because they are different types of monads.
I would like to know if there is any chance of having a EagerTry and LazyTry that behave just like the current Try, but with the latter (LazyTry) delaying the execution of the closure passed until the result is needed (if it is needed).
Please note that declaring stuff as lazy doesn't work quite well in Scala, in particular it works for a given scope. An alternative exists when passing parameters (parameters by name). The question is how to achieve lazy behaviour when returning (lazy) values to an outer scope. Option is basically a collection of length 0 or 1, this would be an equivalent case for lazy collections (Iterator, Sequence) but limited to length 0 or 1 (like Option and Either). I'm particularly interested in Try, i.e. using LazyTry exactly as Try would be used. I guess this should be analogous in other cases (Option and Either).
Please note that we already have EagerTry, as the current standard Try is eager. Unfortunately, the class is sealed, therefore, to have eager and lazy versions of the same class we would need to define the three of them and implement two of them (as opposed to defining and implementing one). The point is returning a Try without other software layers worrying about the time of execution of that code, i.e. abstraction.
Yes, it wouldn't be hard to write LazyTry. One possible approach:
sealed class LazyTry[A](block: => A) {
// the only place block is used
private lazy val underlying: Try[A] = Try(block)
def get = underlying.get
def isSuccess = underlying.isSuccess
...
}
object LazyTry {
def apply[A](block: => A): LazyTry[A] = new LazyTry[A](block)
...
}
Note that you don't have LazySuccess and LazyFailure, since you don't know which class to use before running block.
I made codes using play framework in scala which look like the following:
object Application extends Controller {
def hoge = Action( implicit request =>
val username = MyCookie.getName.get
Ok("hello " + username)
}
}
object MyCookie {
def getName( implicit request: RequestHeader ) = {
request.cookies.get("name").map(_.value)
}
}
I got a code review from my coworker. He said this code is not readable because of implicit parameter. I couldn't reply to his opinion. So could you tell me what is the best way to use implicit parameters? When should I use implicit parameters?
You should use implicit parameters when there is almost always a "right" way to do things, and you want to ignore those details almost all the time; or when there often is no way to do things, and the implicits provide the functionality for those things that work.
For an example of the first case, in scala.concurrent.Future, almost every method takes an implicit ExecutionContext. You almost never care what your ExecutionContext is from call to call; you just want it to work. But when you need to change the execution context you can supply it as an explicit parameter.
For an example of the second case, look at the CanBuildFroms in the collections library. You cannot build anything from anything; certain capabilities are supplied, and the lack of an implicit that, say, lets you package up a bunch of Vector[Option[String]]s into a HashSet[Char] is one major way to keep the library powerful and flexible yet sane.
You are doing neither: apparently you're just using it to save a little typing in one spot at the expense of the other spot. And, in this case, in doing so you've made it less obvious how things work, as you have to look all over the place to figure out where that implicit request actually gets used. If you want to save typing, you're much better off using short variable names but being explicit about it:
Action{ req => val name = MyCookie.getName(req).get; Ok("hello "+name) }