This question already has answers here:
Map versus FlatMap on String
(5 answers)
Closed 5 years ago.
Can anyone teach me property use cases of map and flatMap?
In Option case, I know these two methods have each signature, def map(A => B): Option[B] and def flatMap(A => Option[B]): Option[B].
So, I can get some value by two ways:
scala> val a = Some(1).map(_ + 2)
a: Option[Int] = Some(3)
scala> val a2 = Some(1).flatMap(n => Some(n + 2))
a2: Option[Int] = Some(3)
When I write a method: def plusTwo(n: Int), is there any difference between
def plusTwo(n: Int): Int = n + 2
Some(1).map(plusTwo)
and
def plusTwo(n: Int): Option[Int] = Some(n + 2)
Some(1).flatMap(plusTwo)
flatMap can convert to for-comprehension, and is it better that almost all methods return value Option wrapped?
Let's say you have a List:
val names = List("Benny", "Danna", "Tal")
names: List[String] = List(Benny, Danna, Tal)
Now let's go with your example. Say we have a function that returns an Option:
def f(name: String) = if (name contains "nn") Some(name) else None
The map function works by applying a function to each element in the list:
names.map(name => f(name))
List[Option[String]] = List(Some(Benny), Some(Danna), None)
In the other hand, flatMap applies a function that returns a sequence for each element in the list, and flattens the results into the original list
names.flatMap(name => f(name))
List[String] = List(Benny, Danna)
As you can see, the flatMap removed the Some/None layer and kept only the original list.
Your function plusTwo returns valid results for all input since you can add 2 to any Int.
There is no need to define that it returns Option[Int] because None value is never returned. That's why for such functions you use Option.map
But not all functions have meaningful result for every input. For example if your function divide some number by function parameter then it makes no sense to pass zero to that function.
Let's say we have a function:
def divideTenBy(a: Int): Double
When you invoke it with zero then ArithmeticException is thrown. Then you have to remember to catch this exception so it's better to make our function less error prone.
def divideTenBy(a: Int): Option[Double] = if (a == 0) None else Some(10 / a)
With such functions you can use flatMap since you can have 'None' value in optional (left operand) or given function can return None.
Now you can safely map this function on any value:
scala> None.flatMap(divideTenBy)
res9: Option[Double] = None
scala> Some(2).flatMap(divideTenBy)
res10: Option[Double] = Some(5.0)
scala> Some(0).flatMap(divideTenBy)
res11: Option[Double] = None
Related
I'm trying to use a partial function for some validations, lets take an example of a string:
def isLengthValid: PartialFunction[String, Option[String]] ={
case s:String if s.length > 5 => Some("Invalid")
}
def isStringValid: PartialFunction[String, Option[String]] ={
case s: String if s == "valid" => Some("Valid")
}
isLengthValid("valid") orElse isStringValid("valid")
expected output => Some("Valid")
But I'm getting a match Error:
scala.MatchError: valid (of class java.lang.String)
Could anyone help that what is going wrong here, because as per my understanding .isDefinedAt is called internally and is should not give matchError.
P.S ignore the inputs, this is just an example.
Your understanding is wrong. The ScalaDocs page clearly states, "It is the responsibility of the caller to call isDefinedAt before calling apply ...".
Your code isn't calling isDefinedAt, which is causing the exception, so you have to explicitly call it or you can employ other methods that hide the isDefinedAt internally.
Seq("valid") collect (isLengthValid orElse isStringValid)
//res0: Seq[Option[String]] = List(Some(Valid))
Seq("vlad") collect (isLengthValid orElse isStringValid)
//res1: Seq[Option[String]] = List()
This works as intended if you write the last line as
(isLengthValid orElse isStringValid)("valid")
I suspect the problem is that your version desugars to
(isLengthValid.apply("valid")).orElse(isStringValid.apply("valid"))
This means the apply is calculated before the orElse takes place, which means the partial function is treated as a total function and a match error is thrown as Valy Dia's answer explains. The orElse is actually being called on the result output, not the partial function.
The error message comes from the first expression - isLengthValid.
It is define only for string with a length stricly greater than 5. Hence when it is applied to a the string "valid" of length 5, it throws a MatchError:
scala>"valid".length
res5: Int = 5
isLengthValid("valid")
scala.MatchError: valid (of class java.lang.String)
If the method isLengthValid defined this way instead (Note the greater than equal sign), it wouldn't throw the MatchError :
def isLengthValid: PartialFunction[String, Option[String]] ={
case s:String if s.length >= 5 => Some("Invalid")
}
scala>isLengthValid("valid")
res8: Option[String] = Some("Invalid")
And the original expression would return an Option:
scala>isLengthValid("valid") orElse isStringValid("valid")
res9: Option[String] = Some("Invalid")
What you could do here as well as explained in this question, is to use this definition instead:
val isLengthValid = new PartialFunction[String, Option[String]] {
def isDefinedAt(x: String) = x.length > 5
def apply(x: String) = Some("Invalid")
}
scala>isLengthValid("valid")
res13: Some[String] = Some("Invalid")
I already understand that I can sum over a list easily using List.sum:
var mylist = List(1,2,3,4,5)
mylist.sum
// res387: Int = 15
However, I have a list that contains elements like None and Some(1). These values were produced after running a left outer join.
Now, when I try to run List.sum, I get an error:
var mylist= List(Some(0), None, Some(0), Some(0), Some(1))
mylist.sum
<console>:27: error: could not find implicit value for parameter num: Numeric[Option[Int]]
mylist.sum
^
How can I fix this problem? Can I somehow convert the None and Some values to integers, perhaps right after the left outer join?
You can use List.collect method with pattern matching:
mylist.collect{ case Some(x) => x }.sum
// res9: Int = 1
This ignores the None element.
Another option is to use getOrElse on the Option to extract the values, here you can choose what value you want to replace None with:
mylist.map(_.getOrElse(0)).sum
// res10: Int = 1
I find the easiest way to deal with a collection of Option[A] is to flatten it:
val myList = List(Some(0), None, Some(0), Some(0), Some(1))
myList.flatten.sum
The call to flatten will remove all None values and turn the remaining Some[Int] into plain old Int--ultimately leaving you with a collection of Int.
And by the way, embrace that immutability is a first-class citizen in Scala and prefer val to var.
If you want to avoid creating extra intermediate collections with flatten or map you should consider using an Iterator, e.g.
mylist.iterator.flatten.sum
or
mylist.iterator.collect({ case Some(x) => x }).sum
or
mylist.iterator.map(_.getOrElse(0)).sum
I think the first and second approaches are a bit better since they avoid unnecessary additions of 0. I'd probably go with the first approach due to it's simplicity.
If you want to get a bit fancy (or needed the extra generality) you could define your own Numeric[Option[Int]] instance. Something like this should work for any type Option[N] where type N itself has a Numeric instance, i.e. Option[Int], Option[Double], Option[BigInt], Option[Option[Int]], etc.
implicit def optionNumeric[N](implicit num: Numeric[N]) = {
new Numeric[Option[N]] {
def compare(x: Option[N], y: Option[N]) = ??? //left as an exercise :-)
def fromInt(x: Int) = if (x != 0) Some(num.fromInt(x)) else None
def minus(x: Option[N], y: Option[N]) = x.map(vx => y.map(num.minus(vx, _)).getOrElse(vx)).orElse(negate(y))
def negate(x: Option[N]) = x.map(num.negate(_))
def plus(x: Option[N], y: Option[N]) = x.map(vx => y.map(num.plus(vx, _)).getOrElse(vx)).orElse(y)
def times(x: Option[N], y: Option[N]) = x.flatMap(vx => y.map(num.times(vx, _)))
def toDouble(x: Option[N]) = x.map(num.toDouble(_)).getOrElse(0d)
def toFloat(x: Option[N]) = x.map(num.toFloat(_)).getOrElse(0f)
def toInt(x: Option[N]) = x.map(num.toInt(_)).getOrElse(0)
def toLong(x: Option[N]) = x.map(num.toLong(_)).getOrElse(0L)
override val zero = None
override val one = Some(num.one)
}
}
Examples:
List(Some(3), None, None, Some(5), Some(1), None).sum
//Some(9)
List[Option[Int]](Some(2), Some(4)).product
//Some(8)
List(Some(2), Some(4), None).product
//None
List(Some(Some(3)), Some(None), Some(Some(5)), None, Some(Some(1)), Some(None)).sum
//Some(Some(9))
List[Option[Option[Int]]](Some(Some(2)), Some(Some(4))).product
//Some(Some(8))
List[Option[Option[Int]]](Some(Some(2)), Some(Some(4)), None).product
//None
List[Option[Option[Int]]](Some(Some(2)), Some(Some(4)), Some(None)).product
//Some(None) !?!?!
Note that there may be multiple ways of representing "zero", e.g. None or Some(0) in the case of Option[Int], though preference is given to None. Also, note this approach contains the basic idea of how one goes about turning a semigroup (without an additive identity) into a monoid.
you can use a .fold or .reduce and implement the sum of 2 Options manually. But I would go by the #Psidom approach
Folding on the list is a more optimized solution. Beware of chaining function calls on collections, as you may be iterating over something like a List multiple times.
A more optimized approach would look something like
val foo = List(Some(1), Some(2), None, Some(3))
foo.foldLeft(0)((acc, optNum) => acc + optNum.getOrElse(0))
I have a function in a context, (in a Maybe / Option) and I want to pass it a value and get back the return value, directly out of the context.
Let's take an example in Scala :
scala> Some((x:Int) => x * x)
res0: Some[Int => Int] = Some(<function1>)
Of course, I can do
res0.map(_(5))
to execute the function, but the result is wrapped in the context.
Ok, I could do :
res0.map(_(5)).getOrElse(...)
but I'm copy/pasting this everywhere in my code (I have a lot of functions wrapped in Option, or worst, in Either...).
I need a better form, something like :
res0.applyOrElse(5, ...)
Does this concept of 'applying a function in a concept to a value and immediatly returning the result out of the context' exists in FP with a specific name (I'm lost in all those Functor, Monad and Applicatives...) ?
You can use andThen to move the default from the place where you call the function to the place where you define it:
val foo: String => Option[Int] = s => Some(s.size)
val bar: String => Int = foo.andThen(_.getOrElse(100))
This only works for Function1, but if you want a more generic version, Scalaz provides functor instances for FunctionN:
import scalaz._, Scalaz._
val foo: (String, Int) => Option[Int] = (s, i) => Some(s.size + i)
val bar: (String, Int) => Int = foo.map(_.getOrElse(100))
This also works for Function1—just replace andThen above with map.
More generally, as I mention above, this looks a little like unliftId on Kleisli, which takes a wrapped function A => F[B] and collapses the F using a comonad instance for F. If you wanted something that worked generically for Option, Either[E, ?], etc., you could write something similar that would take a Optional instance for F and a default value.
You could write something like applyOrElse using Option.fold.
fold[B](ifEmpty: ⇒ B)(f: (A) ⇒ B): B
val squared = Some((x:Int) => x * x)
squared.fold {
// or else = ifEmpty
math.pow(5, 2).toInt
}{
// execute function
_(5)
}
Using Travis Browns recent answer on another question, I was able to puzzle together the following applyOrElse function. It depends on Shapeless and you need to pass the arguments as an HList so it might not be exactly what you want.
def applyOrElse[F, I <: HList, O](
optionFun: Option[F],
input: I,
orElse: => O
)(implicit
ftp: FnToProduct.Aux[F, I => O]
): O = optionFun.fold(orElse)(f => ftp(f)(input))
Which can be used as :
val squared = Some((x:Int) => x * x)
applyOrElse(squared, 2 :: HNil, 10)
// res0: Int = 4
applyOrElse(None, 2 :: HNil, 10)
// res1: Int = 10
val concat = Some((a: String, b: String) => s"$a $b")
applyOrElse(concat, "hello" :: "world" :: HNil, "not" + "executed")
// res2: String = hello world
The getOrElse is most logical way to do it. In regards to copy/pasting it all over the place - you might not be dividing your logic up on the best way. Generally, you want to defer resolving your Options (or Futures/etc) in your code until the point you need to have it unwrapped. In this case, it seems more sensible that your function takes in an an Int and returns an Int, and you map your option where you need the result of that function.
Can someone explain how and when to use the triple caret ^^^ (vs the double caret ^^) when designing scala parser combinators? And also when / how to use the parser.into() method (>>).
I'll begin with an example using Scala's Option type, which is similar in some important ways to Parser, but can be easier to reason about. Suppose we have the following two values:
val fullBox: Option[String] = Some("13")
val emptyBox: Option[String] = None
Option is monadic, which means (in part) that we can map a function over its contents:
scala> fullBox.map(_.length)
res0: Option[Int] = Some(2)
scala> emptyBox.map(_.length)
res1: Option[Int] = None
It's not uncommon to care only about whether the Option is full or not, in which case we can use map with a function that ignores its argument:
scala> fullBox.map(_ => "Has a value!")
res2: Option[String] = Some(Has a value!)
scala> emptyBox.map(_ => "Has a value!")
res3: Option[String] = None
The fact that Option is monadic also means that we can apply to an Option[A] a function that takes an A and returns an Option[B] and get an Option[B]. For this example I'll use a function that attempts to parse a string into an integer:
def parseIntString(s: String): Option[Int] = try Some(s.toInt) catch {
case _: Throwable => None
}
Now we can write the following:
scala> fullBox.flatMap(parseIntString)
res4: Option[Int] = Some(13)
scala> emptyBox.flatMap(parseIntString)
res5: Option[Int] = None
scala> Some("not an integer").flatMap(parseIntString)
res6: Option[Int] = None
This is all relevant to your question because Parser is also monadic, and it has map and flatMap methods that work in very similar ways to the ones on Option. It also has a bunch of confusing operators (which I've ranted about before), including the ones you mention, and these operators are just aliases for map and flatMap:
(parser ^^ transformation) == parser.map(transformation)
(parser ^^^ replacement) == parser.map(_ => replacement)
(parser >> nextStep) == parser.flatMap(nextStep)
So for example you could write the following:
object MyParser extends RegexParsers {
def parseIntString(s: String) = try success(s.toInt) catch {
case t: Throwable => err(t.getMessage)
}
val digits: Parser[String] = """\d+""".r
val numberOfDigits: Parser[Int] = digits ^^ (_.length)
val ifDigitsMessage: Parser[String] = digits ^^^ "Has a value!"
val integer: Parser[Int] = digits >> parseIntString
}
Where each parser behaves in a way that's equivalent to one of the Option examples above.
class DefaultListMap[A, B <: List[B]] extends HashMap[A, B] {
override def default(key: A) = List[B]()
}
I wan't to create map A -> List[B]. In my case it is Long -> List[String] but when I get key from map that doesn't have value I would like to create empty List instead of Exception being thrown. I tried different combinations but I don't know how to make code above pass the compiler.
Thanks in advance.
Why not to use withDefaultValue(value)?
scala> val m = Map[Int, List[String]]().withDefaultValue(List())
m: scala.collection.immutable.Map[Int,List[String]] = Map()
scala> m(123)
res1: List[String] = List()
Rather than using apply to access the map, you could always use get, which returns Option[V] and then getOrElse:
map.get(k) getOrElse Nil
One great feature of the scalaz functional-programming library is the unary operator ~, which means "or zero",as long as the value type has a "zero" defined (which List does, the zero being Nil of course). So the code then becomes:
~map.get(k)
This is doubly useful because the same syntax works where (for example) your values are Int, Double etc (anything for which there is a Zero typeclass).
There has been a great deal of debate on the scala mailing list about using Map.withDefault because of how this then behaves as regards the isDefinedAt method, among others. I tend to steer clear of it for this reason.
There's a method withDefaultValue on Map:
scala> val myMap = Map(1 -> List(10), 2 -> List(20, 200)).withDefaultValue(Nil)
myMap: scala.collection.immutable.Map[Int,List[Int]] = Map((1,List(10)), (2,List(20, 200)))
scala> myMap(2)
res0: List[Int] = List(20, 200)
scala> myMap(3)
res1: List[Int] = List()
Why do you want to manipulate a map when it has already a method for this?
val m = Map(1L->List("a","b"), 3L->List("x","y","z"))
println(m.getOrElse(1L, List("c"))) //--> List(a, b)
println(m.getOrElse(2L, List("y"))) //--> List(y)
withDefault can also be used.
/** The same map with a given default function.
* Note: `get`, `contains`, `iterator`, `keys`, etc are not affected
* by `withDefault`.
*
* Invoking transformer methods (e.g. `map`) will not preserve the default value.
*
* #param d the function mapping keys to values, used for non-present keys
* #return a wrapper of the map with a default value
*/
def withDefault[B1 >: B](d: A => B1): immutable.Map[A, B1]
Example:
scala> def intToString(i: Int) = s"Integer $i"
intToString: (i: Int)String
scala> val x = Map[Int, String]().withDefault(intToString)
x: scala.collection.immutable.Map[Int,String] = Map()
scala> x(1)
res5: String = Integer 1
scala> x(2)
res6: String = Integer 2
Hope this helps.