I am new to scala and I can not understand the following function
val L = List(List(1, 1), 2, List(3, List(5, 8)))
def flatten(l: List[Any]): List[Any] = l flatMap {
case ms:List[_] => flatten(ms)
case l => List(l)
}
flatten(L) // res2: List[Any] = List(1, 1, 2, 3, 5, 8)
In particular I do not understand the combination of flatMap and pattern matching and also the meaning of the first case ms:List[_]
Can someone explain that and maybe provide a simpler example to clarify the concept?
map and flatMap
First of all flatMap is a higher-order function.
map is also a higher order function which will convert a List to a new List by applying a function on all elements of that List. For example if you have
val l = List(1,2,3)
you can map it to a new list by using
val doubled = l.map(_ * 2) // List(2,4,6)
So what is flatMap? flatMap is useful when your function gets an Int but returns a List[Int]. In this case if you pass this function to map what you get will be a List[List[Int]] but sometimes you want to get a List[Int] instead.
What you can do is to use flatMap instead. Mathematically it is equivalent to first map and then flatten the result but in action it could be the flatten function which is defined based on flatMap not the other way around.
Technical details aside, flatten means that if you have a List[List[List...[Int]]], if you flatten it, you will get a List[Int].
When we look at
def flatten(l: List[Any]): List[Any] = l flatMap {
case ms:List[_] => flatten(ms)
case l => List(l)
}
we first need to know what does this mean. We already know that we have to pass a function to flatMap. In this case the function we are passing is
{
case ms:List[_] => flatten(ms)
case l => List(l)
}
which at first does not seem like a function but it is! It is actually a partial function which you can consider as a function with some nuances!
What is a partial function?
We could achieve (almost) the same result with:
def flatten(l: List[Any]): List[Any] = l flatMap { _ match {
case ms:List[_] => flatten(ms)
case l => List(l)
}
}
The difference between an ordinary function and a partial function is that partial functions may be undefined for some specific inputs. So the compiler will automatically generate a partial function from a body which starts with case keyword (It's not that simple but for the sake of simplicity I skip the details here).
Pattern matching by Type
A pattern like ms:List[_] is called a type pattern. It means that the type of ms will be checked in runtime against the List[_]. _ is a wild card and means any type so ms:List[_] literally means a List of any type (Due to type erasure you can not use a pattern like ms:List[Int], refer to this thread for more info).
So the whole pattern match on this code snippets means that
If ms is a list the result will be flatten(ms), other wise the result will be List(l).
The flatten function defined like this is recursive function which unwraps the lists and do this until there is no more list, then it will wrap the result again in a List! This way List[List[List.......[_]]] will be converted to List[_].
An additional example for type-patterns:
def hello(o: Any) = o match {
case _:Int => "Hi, I am an Int and I'm proud of it!"
case _:List[_] => "I have many things to tell you! I am a list after all!"
case b:Boolean => s"I'm simply a flag and my value is $b"
case _ => "I'm everything else you can imagine :D"
}
Disambiguation
By the way partial function is totally different from partially applied function and partial application!
The concept of partial function in Scala is the same as partial function in mathematics: A function which may be undefined for some of the values of its domain.
Related
I'm a little baffled by the error
[error] found : A => B
[error] required: PartialFunction[A,B]
I can fix it by wrapping the function I'm using in Function.unlift(x => Some(...)) but this seems like something I would have expected to be implicit given the doc's definition of "A partial function of type PartialFunction[A, B] is a unary function where the domain does not necessarily include all values of type A".
With the word "necessarily", this definition seems to explicitly include a function A => B being a PartialFunction[A, B]. Am I mis-reading this, or missing something else?
To add to my confusion, while I get this error in my code with Throwable and com.twitter.util.Future[com.twitter.finagle.http.Response], I cannot reproduce it with a simpler example.
PartialFunction does not necessarily include all values of type A this means you can only handle the target value without the other values. like the pattern match.
Example 1:
List(1, 2, 3, 4, 5).collect({
case x if x % 2 == 0 => x + 1
})
In the above code snippet, we only want to handle the even numbers and plus 1. if there is no PartialFunction, we will need to filter even numbers firstly and map again.
Example 2:
List(1, 2, "one", "two").collect({
case x: String => x + 1
})
In the Example 2, we only want to handle the String type values in the list, so PartialFunction also can used to match the type.
So if you want to implicit to convert Function to PartialFunction, I think you can define implicit method like:
implicit def convertFunctionToPartialFunction[A, B](f: A => Option[B]) = {
Function.unlift(f)
}
val a: Int => Option[Int] = (x: Int) => {
if (x % 2 == 0) {
Some(x + 1)
} else None
}
val res = List(1, 2, 3, 4, 5).collect(a)
but seems a Function is ugly...
PartialFunction[A, B] is a subtype of A => B. In particular, it has the method isDefinedAt which A => B doesn't have. So where a PartialFunction is expected, a normal function can't be used.
Your "simpler example" does the opposite: it passes a PartialFunction to something that expects a function. This direction works fine.
Instead of messing around with Function.unlift, you can just use
{ case x => f(x) }
(since PartialFunction is the expected type in your case). There's also PartialFunction(f), but it's deprecated since 2.12.5.
Suppose this function
def func[A](data: List[A], mapper: A => String) = {
data.map(item => mapper(item))
}
Why this code doesn't compile:
val list = List(1, 2, 3)
func(list, a => a.toString)
But this one does:
val list = List(1, 2, 3)
func[Int](list, a => a.toString)
Or
val list = List(1, 2, 3)
func(list, (a: Int) => a.toString)
While a type can be inferred from list which is List of Int. Why doesn't scala infer the type here?
Is there any other way?
There is another way! It also happens to make for some nice syntatic sugar:
def func[A](data: List[A])(mapper: A => String) = data map mapper
which looks like:
func(myList){
case Left(one) => one
case Right(_) => default
}
The reason that you can not get the type information to flow the way you'd expect is that type information in Scala is left to right. In other systems, type information is known and deduced for useage where it is defined. You sometimes have to work around these limitations but at the same time, in this case, you can get to work with something that looks akin to your own defined control structure.
So...
func[Int]( //I've just told the typer what the information is and it can flow to the right.
func(list //the typer has to deduce the type and without a guide can not figure out what a => a.toString should be
This is also an old "issue" you can see here SI-4773.
Response to Q in Comment:
If you want to have a Seq[A => B] then I'd do something similar to
func[A, B](data: List[A])(actions: A => B*) = actions map {
data map
}
which is using varargs (translates to a WrappedArray, hence the map) to accept any list of commands so that you can pass is
func(list)(_.name, _.age, _.sex, _.stalker)
as far as pulling out and matching on what you've passed in:
func[A, B](data: List[A])(actions: (String, A => B)*) = actions map {
case (name, f) => (name, data map f)
}
wherein you're using the case statement to pattern match and extract the tuple.
I'm new to scala and when study the pattern match part, i got confused.
val hd::tail = List(1,2,3,4,5)
After execute this code, hd will be Int = 1 , and tail will be List[Int] = List(2, 3, 4, 5).
And this code equals to:
val ::(hd,tail) = List(1,2,3,4,5)
I learned that this code is pattern match and it calls unapply method actually.
But when I write code in this way, compiled error:
val result = ::.unapply(List(1,2,3,4,5))
It says method parameter type mismatch. The unapply method of "::" need a "::[?]"
Does anyone know the reason?
The type mismatch error is because ::.unapply takes an instance of ::[T] rather than an instance of the more general type List[T].
Scala will automatically add the matching against the actual type.
In other words, my understanding is that when you do this:
val list = List(1,2,3,4,5)
val hd::tail = list
the compiler generates something akin to this:
val list = List(1,2,3,4,5)
val (hd, tail) =
::.unapply(
// First match to test against input type
// (necessary as the static type of `list` is `List[Int]`
// so we don't know until runtime if it is an instance of `::[Int]`
// or an instance of `Nil`)
list match {
case nonEmptyList: ::[Int] => nonEmptyList
case _ => throw new MatchError
}
) match { // Second match to test against result of `::`.unapply
case Some( result ) => result
case _ => throw new MatchError
}
The method signature you have is incorrect. :: is a case class, so unapply takes an instance of ::. Here's something closer to what you might be looking for, though typically I don't call unapply in code as it's done in a pattern matching scenario:
//Note the type returned by unapply
val unappliedOption:Option[(Int, List[Int])] = ::.unapply(::(1, List(2, 3, 4, 5)))
val (hd, tail) = unappliedOption.getOrElse((1, Nil))
In pattern matching unapply is called automatically for you. Also note that :: is a non-empty list though it still returns an option. So for an instance of List we have two options :: or Nil:
List(1, 2, 3, 4, 5) match {
case hd :: tail => println(hd, tail) // calls ::.unapply and returns hd tail if the option is Some
case hd => println(hd) //Default case Nil
}
What would be the best and/or easiest way to extract a value that I've saved in a case class?
take for example the following code:
abstract class Something
case class Foo(input: Int) extends Something
case class Bar(input: Double) extends Something
def someMethod(a: Something, b: Something) {
// code that extracts values goes here
}
someMethod(Foo(10), Foo(20))
someMethod(Bar(2.1), Bar(21.2))
how would I then go about getting the integer or the double itself out of a and b when I call the method like I did under its definition?
Note that both the parameters are used in the same equation
In case classes constructor arguments are vals, so just call:
a.input
b.input
You can also use extractor with the help of unapply method:
val Foo(val1) = a
val Bar(val2) = b
and then use val1 and val2
Update
Then you should use pattern matching on your value:
value match {
case Foo(val1) => val1
case Bar(val1) => val1
}
It works just like val Foo(val1) = a, with using generated unapply method (extractor) in your class, and it is also an expression, so you van assign the result to the variable
If you have multiple arguments just change PatMat construct according to the number of your parameters, in your case:
someMethod(a: Something, b: Something) = (a, b) match {
case (Foo(v1), Foo(v2)) => (v1, v2) // or any other logic with values
case (Foo(v1), Bar(v2)) => // logic for this case
... // logic for other cases
}
The more parameters the more cases you should provide, but you case blank cases if you don't need them
someMethod(a: Something, b: Something) = (a, b) match {
case (Foo(v1), Foo(v2)) => (v1, v2) // or any other logic with values
case _ =>
}
in this case all other cases will be ignored, not the best choice, cause the result type will be incorrect. And you also can black values
someMethod(a: Something, b: Something) = (a, b) match {
case (Foo(v1), _) => v1 // in such case you can work only with v1
... // logic for other cases
}
An alternative to pattern matching could be do redefine your classes like this:
trait Something[T]{
def input:T
}
case class Foo(input: Int) extends Something[Int]
case class Bar(input: Double) extends Something[Double]
Then, any instance of Something will expose the input property. The only potential downside is that it will be of a generic type when you access it.
The alternative approach
In addition to the direct solution of pattern matching in your method, I'll try to show a somewhat more convoluted, general and functional approach to this kind of situations. Still pattern matching is the most direct and simple answer!
If you can explicitly "certify" in your interface the input accessor, you can generalize how you work with the Something class.
In code this translates to
trait Something[T] {
def input: T
}
case class Foo(input: Int) extends Something[Int]
case class Bar(input: Double) extends Something[Double]
from here you can define how to "lift" any function you like to one that works over Somethings
Let's say you have methods that takes two inputs (e.g. Ints or Doubles) and you want to operate on such inputs within one of your case classes (i.e. Foo, Bar)
//this function lift your specific input method to one that takes Somethings
def liftSomething2[T, R](f: (T, T) => R): (Something[T], Something[T]) => R =
(a, b) => f(a.input, b.input)
Let's examine this a bit: it takes a function
(T, T) => R of 2 arguments of type T and a result R
and transforms it in a
(Something[T], Something[T]) => R which takes Somethings as arguments.
Examples
//lifts a function that sums ints
scala> val sumInts = liftSomething2[Int, Int](_ + _)
sumInts: (Something[Int], Something[Int]) => Int = <function2>
//lifts a function that multiplies ints
scala> val multInts = liftSomething2[Int, Int](_ * _)
multInts: (Something[Int], Something[Int]) => Int = <function2>
//lifts a function that divides doubles
scala> val divDbl = liftSomething2[Double, Double](_ / _)
divDbl: (Something[Double], Something[Double]) => Double = <function2>
//Now some test
scala> sumInts(Foo(1), Foo(2))
res2: Int = 3
scala> multInts(Foo(4), Foo(-3))
res3: Int = -12
scala> divDbl(Bar(20.0), Bar(3.0))
res4: Double = 6.666666666666667
//You can even complicate things a bit
scala> val stringApp = liftSomething2[Int, String](_.toString + _)
stringApp: (Something[Int], Something[Int]) => String = <function2>
scala> stringApp(Foo(1), Foo(2))
res5: String = 12
All the above examples lift functions of type (T,T) => R but the "lifting" can be made for all and any argument you need
//This takes three args of different types and returns another type
// the logic doesn't change
def liftSomething3[A,B,C,R](f: (A,B,C) => R): (Something[A], Something[B], Something[C]) => R =
(a,b,c) => f(a.input, b.input, c.input)
//sums to ints and divides by a double
scala> val sumDiv = liftSomething3[Int,Int,Double,Double]((i,j,d) => (i + j) / d)
sumDiv: (Something[Int], Something[Int], Something[Double]) => Double = <function3>
scala> sumDiv(Foo(5), Foo(30), Bar(4.2))
res7: Double = 8.333333333333332
more...
All we've seen so far should be somewhat related to category theory concepts like Applicative Functors and Comonads, but I'm no expert so I encourage you to search for yourself if you feel this sort of abstractions are useful and interesting.
In your example both the a and b have specific types: Foo and Bar respectively. That's why you can simply access their fields like so:
scala> a.input
res4: Int = 10
scala> b.input
res5: Double = 25.1
If however your value has type Something, then you'll need to pattern-match:
val input = somethingOfTypeSomething match {
case Foo(input) => input
case Bar(input) => input
}
The other answers have covered the basic scenario. There are useful variations to consider.
Constructor Pattern
As already answered there is:
value match {
case Foo(x) => x
...
}
Deep Matching
The constructor pattern also supports deep matching. For example, extract x within Bar within Foo which is 3 levels deep:
value match {
case Foo(y, Bar(x)) => x
...
}
Variable Binding
If the value you want to extract is an actual case class inside another case class you can use variable binding. E.g. to extract the whole Bar(x) into b:
value match {
case Foo(y, b # Bar(x)) => b
...
}
Programming in Scala by M. Odersky, Spoon and Venners has a great chapter on case classes and pattern matching which covers many other scenarios. Pattern matching is such a rich part of the language it would be a worthwhile investment.
I've had this situation occur a number of times in the library I'm writing, and I'm not particularly satisfied with the solutions I've come up with so far.
Let's say that I have an expensive function f that takes an item of type T and returns a value of type Option[U]. Now, suppose I have a collection of type T and I want to retrieve the first non-None value returned by f when performed across the elements of T without evaluating f for all elements of T if the value has already been found.
The only way I've come up with to do this is to wrap F into an Extractor Object, and use it with scala's collectFirst method.
For example:
object FMatch { def unapply(t : T) = f(t) }
collection.collectFirst{ case FMatch(result) => result }
This seems a little inelegant, and I'm not certain whether f is evaluated only once or twice for each result (I haven't tested this to find out yet). It seems like it would be useful to have a version of collectFirst that takes a parameter of type T => Option[U] instead of a PartialFunction1[T].
Is there a more elegant way to do this that I'm missing?
Use a view over the collection, to make it lazy and defer invocation of that function until the last possible moment (e.g. it won't be called at all for elements beyond the first match):
xs.view map {f(_)} collectFirst {case Some(x) => x}
or
xs.view map {f(_)} find {_.isDefined}
or in the point-free style, as per Alexey's response:
xs.view map {f} find {_.isDefined}
That should hopefully give you a couple of alternative ways to think about the problem more generally :)
Use this:
collection.toIterator.map(f).find(_.isDefined)
#annotation.tailrec
def first[A, B](as: Traversable[A], f: A => Option[B]): Option[B] =
if (as.isEmpty) None
else f(as.head) match {
case s # Some(_) => s
case _ => first(as.tail, f)
}
Give a partial functions to collectFirst
collectionT
.collectFirst { t =>
f(t) match {
case Some(u) => u
}