I have a parameter
case class Envelope(subject: Option[String]) {
}
and I want to apply a require function only if subject is non null.
Something like below:
require(StringUtils.isNotBlank(subject))
You can try this also:
case class Envelope(subject: Option[String])
def check(en: Envelope): Boolean = {
require(en.subject.isDefined)
true
}
It will be finer and you don't have any need to import StringUtils.
For fetching the value from Option you should go for the getorElse. Here we can define the default value for the variable. Ex:
def check(str: Option[String]): String = {
str.getOrElse("")
}
scala> check(None)
res1: String = ""
scala> check(Some("Test"))
res2: String = Test
Only get will throw the exception when it will get None. Ex:
def check(str: Option[String]): String = {
str.get
}
scala> check(Some("Test"))
res2: String = Test
scala> check(None)
java.util.NoSuchElementException: None.get
at scala.None$.get(Option.scala:347)
at scala.None$.get(Option.scala:345)
at check(<console>:24)
... 48 elided
I think you can go that way:
subject.map(s => if(StringUtils.isNotBlank(s)) require(s) else s)
Options should, from a practical perspective, almost never be null in Scala (I'd argue never, but there are all sorts of compromises and exceptions, especially when working with Java dependencies where null checks are more common-place).
With some pre-processing and pattern-matching, you may find this approach acceptable:
// When working with `Option`s, naming convention usually is "[name_of_var]Opt"
case class Envelope( subjectOpt: Option[String] ) {
// Utility to check whether or not this `Envelope` has a subject
def hasSubject: Boolean = subjectOpt.isDefined
// Get the subject or throw an exception if it does not have one (None)
def getSubject: String = {
subjectOpt match {
case None => throw Exception( "Envelope has no subject!" )
case Some( subject ) => subject
}
}
}
object Envelope {
// Utility to create an `Envelope` with no subject
def apply(): Envelope = Envelope(None)
// Utility to do a bit of pre-processing, checking for `null` or empty strings
def apply( subject: String ): Envelope = {
if ( subject == null || subject.isEmpty ) Envelope()
else Envelope( Some( subject ) )
}
}
val nullString: String = null
// Example usages (will have no subject):
val envelopeWithNoSubject: Envelope = Envelope()
val envelopeWithEmptySubject: Envelope = Envelope( "" )
val envelopeWithNullSubject: Envelope = Envelope( nullString )
// envelopeWithNoSubject, ...EmptySubject, and ...NullSubject all return:
... .hasSubject // False
... .getSubject // Exception: Envelope has no subject!
// Example use with subject
val envelopeWithSubject: Envelope = Envelope( "Scala" )
envelopeWithSubject.hasSubject// True
envelopeWithSubject.getSubject // "Scala"
You should be changing the require function call to the following
require(StringUtils.isBlank(subject.get))
.get method returns the string that the subject Option carries.
Related
I am a student who studies Scala in korea. I am learning about pattern matching and unapply methods. The thing I am confused about is that Emergency object has a parameter in unapply method. I can't know the reason when I don't put the parameter in the match block.
object Solution {
def main(args: Array[String]) {
val number1 = "010-123-1234"
val number2 = "119"
val number3 = "포도먹은 돼지"
val numberList = List(number1, number2, number3)
for (number <- numberList) {
number match {
case Emergency() => println("긴급전화다")
case Normal(number) => println("일반 전화다" + number)
case _ => println("판단할 수 없습니다.")
}
}
}
}
object Emergency {
def unapply(number: String): Boolean = {
if (number.length == 3 && number.forall(_.isDigit)) true
else false
}
}
object Normal {
def unapply(number: String): Option[Int] = {
try {
Some(number.replaceAll("-", "").toInt)
} catch {
case _: Throwable => None
}
}
}
Notice that return types of to unapply methods are different.
Normal.unapply returns an Option. When you do case Normal(foo), unapply is called, and, if it returns Some(number), the match is successful, and the number is assigned to local variable foo, and if it returns None, match fails.
Emergency.unapply returns a Boolean, so case Emergency() succeeds if it returns true, and fails otherwise, but there is no result to assign in case of success, thus, no "parameter".
The parameter in unapply is the object on which you are matching.
In this case the number String variable is passed to Emergency.unapply, Normal.unapply etc.
This link explains things nicely:
https://danielwestheide.com/blog/2012/11/21/the-neophytes-guide-to-scala-part-1-extractors.html
I have the following POST body examples:
{ "Id": "123abxy"}
{ "customUrl": "http://www.whiskey.com","Id": "123abxy"}
{ "size": "88", "customUrl": "http://www.whiskey.com","Id": "123abxy"}
And the following endpoint:
case class aType(
customUrl: Option[String],
Id:Option[String],
size:Option[String]
)
#ResponseBody
def addCompany(
#RequestBody a: aType,
#ModelAttribute("action-context") actionContext: ActionContext
): DeferredResult[Created] = Action[Created]
{
val customUrl = {
a.customUrl
}
val size = {
if (a.size == None) {None}
else Option(a.size.get.toLong)
}
val Id = {
a.Id
}
val handle = register(
customUrl,
Id,
size
).run()
}.runForSpring[Nothing](executors, actionContext)
Also:
def register(
customUrl: Option[String],
Id: Option[String],
size: Option[Long]
)
Given the above, I would like to know the correct way to handle the case where size and customUrl are not passed into the POST Body.
In this case, since size can be either a value (Long) or null and customUrl can be either a String or null, I would assume the proper data type to handle this would be Option[String] and Option[Long] for customUrl and size, respectively.
My question is how should I change the if-else clauses to handle the aforementioned scenarios for null or String/Long, so that I can pass valid variables into the register(..) function ?
Cheers,
If the register function receives size and customURL as Options, what's the problem?
I would do something like this:
#ResponseBody
def addCompany(
#RequestBody a: aType,
#ModelAttribute("action-context") actionContext: ActionContext
): DeferredResult[Created] = Action[Created]
{
val handle = register(a.customUrl,a.id,a.size).run()
}.runForSpring[Nothing](executors, actionContext)
If there is a requirement to return None if size is not defined then:
#ResponseBody
def addCompany(
#RequestBody a: aType,
#ModelAttribute("action-context") actionContext: ActionContext
): DeferredResult[Created] = Action[Created]
{
val sizeOpt = a.size
val handle =sizeOpt.map { size =>
register(a.customUrl,a.id,Some(size)).run()
}
}.runForSpring[Nothing](executors, actionContext)
But even better, would be your register function not to expect Options, and deal only with the primitive types. Then you would only need to map the 3 optional values (I recommend to use for comprehension):
for {
size <- a.size
url <- a.customUrl
id <- a.id
} yield register(url, id, size).run()
with register defined as:
def register(
customUrl:String,
Id: String,
size: Long
)
I'm new to the concept of using the Option type but I've tried to use it multiple places in this class to avoid these errors.
The following class is used to store data.
class InTags(val tag35: Option[String], val tag11: Option[String], val tag_109: Option[String], val tag_58: Option[String])
This following code takes a string and converts it into a Int -> String map by seperating on an equals sign.
val message= FIXMessage("8=FIX.4.29=25435=D49=REDACTED56=REDACTED115=REDACTED::::::::::CENTRAL34=296952=20151112-17:11:1111=Order7203109=CENTRAL1=TestAccount63=021=155=CSCO48=CSCO.O22=5207=OQ54=160=20151112-17:11:1338=5000040=244=2815=USD59=047=A13201=CSCO.O13202=510=127
")
val tag58 = message.fields(Some(58)).getOrElse("???")
val in_messages= new InTags(message.fields(Some(35)), message.fields(Some(11)), message.fields(Some(109)), Some(tag58))
println(in_messages.tag_109.getOrElse("???"))
where the FIXMessage object is defined as follows:
class FIXMessage (flds: Map[Option[Int], Option[String]]) {
val fields = flds
def this(fixString: String) = this(FIXMessage.parseFixString(Some(fixString)))
override def toString: String = {
fields.toString
}
}
object FIXMessage{
def apply(flds: Map[Option[Int], Option[String]]) = {
new FIXMessage(flds)
}
def apply(flds: String) = {
new FIXMessage(flds)
}
def parseFixString(fixString: Option[String]): Map[Option[Int], Option[String]] = {
val str = fixString.getOrElse("str=???")
val parts = str.split(1.toChar)
(for {
part <- parts
p = part.split('=')
} yield Some(p(0).toInt) -> Some(p(1))).toMap
}
}
The error I'm getting is ERROR key not found: Some(58) but doesnt the option class handle this? Which basically means that the string passed into the FIXMessage object doesnt contain a substring of the format 58=something(which is true) What is the best way to proceed?
You are using the apply method in Map, which returns the value or throw NoSuchElementException if key is not present.
Instead you could use getOrElse like
message.fields.getOrElse(Some(58), Some("str"))
I have a function which takes optional parameters. However, these are not Option[?] but can be either set or null:
private def div(id: String = null, cssClass: String = null): JQuery = {
val optId = Option(id)
val optCssClass = Option(cssClass)
...
// deal with optId and optCssClass using the Scala-way™
...
}
I am using "null", which I know should be avoided like the plague. However, it allows me to write code like this:
div(id = "someId") // no cssClass
div(id = "otherId", cssClass = "someClass")
which to my eyes looks nicer than:
div(id = Some("someId")) // no cssClass
div(id = Some("otherId"), cssClass = Some("someClass"))
Is this a known / acceptable Scala pattern? (using null as default parameter values and converting to Option)
Or is it still heressy / bad-practice? If so, why?
why not replace null with empty string ?
private def div(id: String = "", cssClass: String = ""): JQuery = {
val optId = if(id.isEmpty) None else Some(id)
val optCssClass = if(cssClass.isEmpty) None else Some(cssClass)
...
// deal with optId and optCssClass using the Scala-way™
...
}
then you can do:
div(id = "someId") // no cssClass
div(id = "otherId", cssClass = "someClass")
One more approach I can suggest is a Builder Pattern
trait ElementBuilder {
def identified(id: String): ElementBuilder
def build: JQuery
}
case class DivElement(identifier: Option[String] = None)
extends ElementBuilder {
def identified(id: String) = this.copy(identifier = Option(id))
def build: JQuery = ??? // Smth like <div id={identifier}></div>
}
val builder = DivElement()
builder.identified("foo")
val element = builder.build
This approach allows you explicitly set parameters and then build you element by them
Most of the answers here are proposing some variant of the "null object" pattern, by denoting an empty String to mean "undefined" (as in val optId = if(id.isEmpty) None else Some(id))
The catch here is that an empty string might be a valid value! This is true of any String, though you can mitigate the problem by using something really outrageous, possibly involving non-printable characters. e.g:
val UndefinedString = "THIS-IS-A-REALLY-UNLIKELY-VALID-VALUE"
private def div(
id: String = UndefinedString,
cssClass: String = UndefinedString
): JQuery = {
val optId = Option(id) filter (_ != UndefinedString )
val optCssClass = Option(cssClass) filter (_ != UndefinedString )
...
// deal with optId and optCssClass using the Scala-way™
...
}
Better still, you could use a different type to denote your null object. As you can't subclass String you'll have to bump your params up the type hierarchy and make them CharSequences
object NullCharSeq extends CharSequence {
def charAt(idx: Int): Char = ???
def length(): Int = 0
def subSequence(start: Int, end: Int): CharSequence = this
def toString(): String = ???
}
def charSeqToOptStr(cs: CharSequence): Option[String] = cs match {
case NullCharSeq => None
case x => Option(x) map (_.toString)
}
private def div(
id: CharSequence = NullCharSeq,
cssClass: CharSequence = NullCharSeq
): JQuery = {
val optId = charSeqToOptStr(id)
val optCssClass = charSeqToOptStr(cssClass)
...
// deal with optId and optCssClass using the Scala-way™
...
}
It's a heavyweight pattern for one-shot usage, but the cost is quickly amortized if you use it a lot (NullCharSeq and charSeqToOptStr only need to be defined once in the codebase).
There's also zero risk of mistakenly passing your "undefined" String as though it were a valid value. Plus, you gain the ability to directly accept CharBuffer/StringBuffer/StringBuilder as your arguments.
I would also go for a special string like the empty string in #Jiafeng's answer, if this is a sensible value. You could also define a string, like
val NoId = "?"
def div(id: String = NoId) = id match {
case NoId => None
case x => Some(x)
}
Another approach would be to use another type which can be implicitly created from string or absence.
sealed trait MaybeId
implicit class Id(val name: String) extends MaybeId
case object NoId extends MaybeId
def div(id: MaybeId = NoId) = id match {
case NoId => None
case x: Id => Some(x.name)
}
Here is a general type that behaves like Option[A] with implicit conversion A => Some[A].
I have the below requirement where I am checking whether a value is greater than 10 or not and based on that I will break, otherwise I will return a String. Below is my code:
import scala.util.control.Breaks._
class BreakInScala {
val breakException = new RuntimeException("Break happened")
def break = throw breakException
def callMyFunc(x: Int): String = breakable(myFunc(x))
def myFunc(x: Int): String = {
if (x > 10) {
"I am fine"
} else {
break
}
}
}
Now what is the happening is that I am getting the error message saying "type mismatch; found : Unit required: String" The reason is :
def breakable(op: => Unit)
But then how I will write a function which can return value as well as break if required?
The Scala compiler can evaluate that a branch throws an exception and not use it to form a minimum bound for the return type, but not if you move the throwing code out in a method: since it can be overridden, the compiler cannot be sure it will actually never return.
Your usage of the Break constructs seems confused: it already provides a break method, there is no need to provide your own, unless you want to throw your exception instead, which would make using Break unnecessary.
You are left with a couple of options then, since I believe usage of Break is unnecessary in your case.
1) Simply throw an exception on failure
def myFunc(x: Int): String = {
if (x > 10) {
"I am fine"
} else {
throw new RuntimeException("Break happened")
}
}
def usemyFunc(): Unit = {
try {
println("myFunc(11) is " + myFunc(11))
println("myFunc(5) is " + myFunc(5))
} catch {
case e: Throwable => println("myFunc failed with " + e)
}
}
2) Use the Try class (available from Scala 2.10) to return either a value or an exception. This differs from the previous suggestion because it forces the caller to inspect the result and check whether a value is available or not, but makes using the result a bit more cumbersome
import scala.util.Try
def myFunc(x: Int): Try[String] = {
Try {
if (x > 10) {
"I am fine"
} else {
throw new RuntimeException("Break happened")
}
}
}
def useMyFunc(): Unit = {
myFunc match {
case Try.Success(s) => println("myFunc succeded with " + s)
case Try.Failure(e) => println("myFunc failed with " + e)
}
}
3) If the thrown exception isn't relevant, you can use the Option class instead.
You can see how the multiple ways of working with Options relate to each other in
this great cheat sheet.
def myFunc(x: Int): Option[String] = {
if (x > 10) {
Some("I am fine") /* Some(value) creates an Option containing value */
} else {
None /* None represents an Option that has no value */
}
}
/* There are multiple ways to work with Option instances.
One of them is using pattern matching. */
def useMyFunc(): Unit = {
myFunc(10) match {
case Some(s) => println("myFunc succeded with " + s)
case None => println("myFunc failed")
}
}
/* Another one is using the map, flatMap, getOrElse, etc methods.
They usually take a function as a parameter, which is only executed
if some condition is met.
map only runs the received function if the Option contains a value,
and passes said value as a parameter to it. It then takes the result
of the function application, and creates a new Option containing it.
getOrElse checks if the Option contains a value. If it does, it is returned
directly. If it does not, then the result of the function passed to it
is returned instead.
Chaining map and getOrElse is a common idiom meaning roughly 'transform the value
contained in this Option using this code, but if there is no value, return whatever
this other piece of code returns instead'.
*/
def useMyFunc2(): Unit = {
val toPrint = myFunc(10).map{ s =>
"myFunc(10) succeded with " + s
}.getOrElse{
"myFunc(10) failed"
}
/* toPrint now contains a message to be printed, depending on whether myFunc
returned a value or not. The Scala compiler is smart enough to infer that
both code paths return String, and make toPrint a String as well. */
println(toPrint)
}
This is a slightly odd way of doing things (throwing an exception), an alternative way of doing this might be to define a "partial function" (a function which is only defined only a specific subset of it's domain a bit like this:
scala> val partial = new PartialFunction[Int, String] {
| def apply(i : Int) = "some string"
| def isDefinedAt(i : Int) = i < 10
}
partial: PartialFunction[Int, String] = <function1>
Once you've defined the function, you can then "lift" it into an Option of type Int, by doing the following:
scala> val partialLifted = partial.lift
partialOpt: Int => Option[String] = <function1>
Then, if you call the function with a value outside your range, you'll get a "None" as a return value, otherwise you'll get your string return value. This makes it much easier to apply flatMaps/ getOrElse logic to the function without having to throw exceptions all over the place...
scala> partialLifted(45)
res7: Option[String] = None
scala> partialLifted(10)
res8: Option[String] = Some(return string)
IMO, this is a slightly more functional way of doing things...hope it helps