If I have Scala tuple Option of the likes:
(Some(1), None)
(None, Some(1))
(None, None)
And I want always to extract always the "Some" value if it exists, and otherwise get the None. The only way with pattern matching?
There is this:
def oneOf[A](tup: (Option[A], Option[A])) = tup._1.orElse(tup._2)
That will return the first option that is defined, or None if neither is.
Edit:
Another way to phrase the same thing is
def oneOf[A](tup: (Option[A], Option[A])) =
tup match { case (first, second) => first.orElse(second) }
It's longer, but perhaps more readable.
This should work:
def f(t: (Option[Int], Option[Int])): Option[Int] = t match {
case (Some(n), _) => Some(n)
case (_, Some(n)) => Some(n)
case _ => None
}
I want always to extract always the Some value if it exists, and otherwise get the None
You can just use orElse
def orOption[T](p: (Option[T], Option[T])): Option[T] = {
val (o1, o2) = p
o1 orElse o2
}
However, this does decide what to do if there exists two Some values:
scala> orOption((Some(1), Some(2)))
res0: Option[Int] = Some(1)
You should probably use pattern matching and then decide what to do if there are two Some values, like throw an exception. Alternatively, consider using a better encoding for the result type than Option.
Related
I am new to Scala and wanted to know how can we convert Future[Option[A]] to Future[A]
Since an Option[A] might be None, if you want to convert it to an A, the most direct way is to use the .getOrElse(value) method, where you need to provide a default value of type A to use if the option itself doesn't have one.
val opt1 = Some(3)
opt1.getOrElse(5) //returns 3
val opt2 = None
opt2.getOrElse(5) //returns 5
Then, if you have a Future[Option[A]], you want to do this in the .map method of the future:
val futureOpt: Future[Option[Int]] = Future{ Some(3) }
val future: Future[Int] = futureOpt.map{opt => opt.getOrElse(5)}
An Option[A] can either be Some[A] or None. The Some[A] case is simple, you can just get A from it. But what about the None case, you can either provide a default value or consider it a failure.
Using a default value,
val aDefault: A = ...
val aFuture1 = aOptionFuture.map({
case Some(a) => a
case None => aDefault
})
// or
val aFuture2 = aOptionFuture.map(_.getOrElse(aDefault))
Consider a failure,
val aFuture3 = aOptionFuture.flatMap({
case Some(a) => Future.successful(a)
case None=> Future.failed(new Exception("computed a None"))
})
val optFuture: Future[Option[Int]] = Future(Some(3))
optFuture.map {
case Some(v) => v
case None => throw new RuntimeException("<some-exception>")
}
Or
optFuture.map(_.getOrElse(throw new RuntimeException("<some-exception>")))
I have to find if an element is inside a list using scala, and I am only allowed to use recursion. Why is the following code not working, as the match statement seems to be correct to me. My IDE gives me an error on all three case statements and it says type, mistmatch, boolean required.
def isInN(x: Int, l: List[Int]): Boolean = (l,l.head) match {
case Nil,_ => false
case _,x => true
case _,_ => isInN (x,l.tail)
}
You're matching a tuple, so you need to use a proper tuple extractor. i.e. just add parenthesis:
def isInN(x: Int, l: List[Int]): Boolean = (l, l.head) match {
case (Nil, _) => false
case (_, x) => true
case (_, _) => isInN (x, l.tail)
}
This compiles, but won't quite work like you want it to. l.head will throw an exception if the list is empty. And x within the match will eagerly match anything, so the last case can never be reached. To match against an identifier, you need to surround it with backticks, otherwise it will just be a placeholder matcher.
To use a similar pattern match without calling l.head, you can pattern match on the List itself:
def isInN(x: Int, l: List[Int]): Boolean = l match {
case Nil => false
case `x` :: _ => true
case head :: tail => isInN (x, tail)
}
Though this is all trumped by contains in the standard collections library:
scala> List(1, 2, 3, 4).contains(2)
res5: Boolean = true
Is there a shorter way to doing this:
val accessControlAllowOrigin = c_dash.getString("access-control-allow-origin") match {
case "" => None
case x => Some(x)
}
This is reading in a Typesafe Config value, where empty string denotes the absence of such a config (in Typesafe Config it's good manners to include all values, not leaving anything out).
Is there something like:
val sopt = Option( s, "magic" )
..which would provide either Some(s) or None if s's value is "magic"?
By looking at the doc I came to:
scala> def f(s: String) = (Some(s) filter( _ != "magic" ))
f: (s: String)Option[String]
scala> f("aaa")
res1: Option[String] = Some(aaa)
scala> f("magic")
res2: Option[String] = None
Is that the simplest?
You can use filter, which works the same for an Option as it would for any other collection:
c_dash.getString("access-control-allow-origin").filter(_.nonEmpty)
Anything not matching the filter predicate will become None.
I may be missing something obvious, but how about:
val sopt = if (s == "magic") None else Some(s)
Or, for your f():
def f(s:String) = if (s == "magic") None else Some(s)
or, more generically:
def noneIfDefault(s:String, default: String) = if (s == default) None else Some(s)
I would like to convert a List[Box[T]] into a Box[List[T]].
I know that I could use foldRight, but I can't find an elegant way into doing so.
EDIT I would like to keep the properties of Box, that is to say, if there is any failure, return a Box with this failure.
If you only want to collect the "Full" values
I'm not sure why you'd want a Box[List[T]], because the empty list should suffice to signal the lack of any values. I'll assume that's good enough for you.
I don't have a copy of Lift handy, but I know that Box is inspired by Option and has a flatMap method, so:
Long form:
for {
box <- list
value <- box
} yield value
Shorter form:
list.flatMap(identity)
Shortest form:
list.flatten
If you want to collect the failures too:
Here's the mapSplit function I use for this kind of problem. You can easily adapt it to use Box instead of Either:
/**
* Splits the input list into a list of B's and a list of C's, depending on which type of value the mapper function returns.
*/
def mapSplit[A,B,C](in: Traversable[A])(mapper: (A) ⇒ Either[B,C]): (Seq[B], Seq[C]) = {
#tailrec
def mapSplit0(in: Traversable[A], bs: Vector[B], cs: Vector[C]): (Seq[B], Seq[C]) = {
in match {
case t if t.nonEmpty ⇒
val a = t.head
val as = t.tail
mapper(a) match {
case Left(b) ⇒ mapSplit0(as, bs :+ b, cs )
case Right(c) ⇒ mapSplit0(as, bs, cs :+ c)
}
case t ⇒
(bs, cs)
}
}
mapSplit0(in, Vector[B](), Vector[C]())
}
And when I just want to split something that's already a Seq[Either[A,B]], I use this:
/**
* Splits a List[Either[A,B]] into a List[A] from the lefts and a List[B] from the rights.
* A degenerate form of {#link #mapSplit}.
*/
def splitEither[A,B](in: Traversable[Either[A,B]]): (Seq[A], Seq[B]) = mapSplit(in)(identity)
It's really easier to do this with a tail-recursive function than with a fold:
final def flip[T](l: List[Option[T]], found: List[T] = Nil): Option[List[T]] = l match {
case Nil => if (found.isEmpty) None else Some(found.reverse)
case None :: rest => None
case Some(x) :: rest => flip(rest, x :: found)
}
This works as expected:
scala> flip(List(Some(3),Some(5),Some(2)))
res3: Option[List[Int]] = Some(List(3, 5, 2))
scala> flip(List(Some(1),None,Some(-1)))
res4: Option[List[Int]] = None
One can also do this with Iterator.iterate, but it's more awkward and slower, so I would avoid that approach in this case.
(See also my answer in the question 4e6 linked to.)
Please point me to correct link if this has been answered before.
I have this code:
def getResult(a:Any):Any = a
def getAnswer[T](i:Int) = {
val result = getResult(i)
result match {
case t:T => Some(t)
case _ => None
}
}
This gives me a unchecked warning and everything matches to T. For instance, when I do getAnswer[Int](2), I get Some(2) (as expected). However, if I do getAnswer[String](2), I also get Some(2) which is not expected (I need None).
Is there any way to work around type erasure and somehow get getAnswer to work correctly (i.e., return Some(result) if and only if the result is of type T)?
Thanks in advance.
def getAnswer[T](i:Any)(implicit m:Manifest[T]) = i match {
case t:Int if m.erasure == classOf[Int] => Some(t)
case t:Double if m.erasure == classOf[Double] => Some(t)
//... other Primitives
case t if m.erasure.isInstance(t) => Some(t) //this matches AnyRefs
case _ => None
}
As Alexey wrote, you have some trouble with primitives. The technique used in the Scala sources in such cases involves always separate matches for every single primitive type, so I guess there is no way around.
This works with some limitations (T must be a class and not a primitive type; if T is generic, parameters are ignored).
def getAnswer[T](i:AnyRef)(implicit m:ClassManifest[T]) = {
val result = getResult(i)
if (result.getClass == m.erasure) Some(result.asInstanceOf[T]) else None
}
> getAnswer[java.lang.Integer](2.asInstanceOf[AnyRef])
res4: Option[java.lang.Integer] = Some(2)
getAnswer[String](2.asInstanceOf[AnyRef])
res1: Option[String] = None