I am still getting used to the concept of PartialFunction in Scala.
I came across the following statement that I can't wrap my head around:
Update:
def msgsToGet: PartialFunction[Any, Unit]
is defined in a trait as follows:
trait MyActorTrait {
palindrome: String => def msgsToGet: PartialFunction[Any, Unit]
//After the answers I received, I understand that the "def msgsToGet: //PartialFunction[Any, Unit]" represents the LHS of an abstract (as yet) //unimplemented function (no function body yet)
}
Now, what does that mean?
I understand that 'def' denotes a function. In this case, it is a function by name msgsToGet.
Then there is a colon (:). Okay, until now, I had always thought "after a colon, is the type, and this is where I am lost.
Okay, is it the same thing as:
def msgsToGet(): PartialFunction[Any, Unit]
[A function that takes in no parameters and returns something of type PartialFunction[Any, Unit].
PartialFunction[Any, Unit] to me somehow looks to me like a return type. But there is no function body. So what is going on here, please?
is this a syntactic sugar for something longer, but readable?
Help me interpret this, please..
If there's no function body, then it's an abstract method. Is it on a trait or an abstract class? An abstract method, like in Java, says that implementing classes must define the method.
You are correct in your analysis: it is a function called "msgsToGet" that takes no parameters and returns an object of type PartialFunction[Any, Unit].
Here's an example:
trait SomeTrait {
def msgsToGet: PartialFunction[Any, Unit]
}
class SomeClass extends SomeTrait {
def msgsToGet: PartialFunction[Any, Unit] = {
case x => println(x)
} // a case block is a partial function, so we can return this block from the function
}
val c = new SomeClass
val f = c.msgsToGet // takes no parameters, returns a partial function
f("hey") // we can call the partial function, which takes an Any parameter
// prints "hey"
It is almost the same than
def msgsToGet(): PartialFunction[Any, Unit]
Scala allows methods without a parameter list (as opposed to one empty parameter list).
In bytecode, these two are the same, but in idiomatic Scala, no parameter list is preferred for methods that are side effect free and especially accessors. Empty parameter list is preferred, ifbthe method is side effecting.
Related
At a high-level, I'm curious to know how implicits defined inside a class body are resolved? I assumed they would be considered part of the current scope (as per the awesome answer here), but I am wrong.
For a specific example, why doesn't the following work:
trait Convert[T, U] {
final def value(record: T)(implicit f: T => U): U = f(record)
}
case class ConvertMap(key: String)
extends Convert[Map[String, String], Boolean] {
implicit def a2b(m: Map[String, String]): Boolean = m.contains(key)
}
I can instantiate the class ConvertMap, but when I call the value method I get an error stating that the view from Map[String, String] => Boolean can't be found.
scala> val c = ConvertMap("key")
c: ConvertMap = ConvertMap(key)
scala> c.value(Map("key" -> "value"))
<console>:13: error: No implicit view available from Map[String,String] => Boolean.
If you re-read the answer you provided for implicit resolution scope, you see that there are a couple of things which happen here causing the implicit you've defined not to be found.
First, if the implicit isn't found in the local scope of the call-site, we defer to "category 2" lookup for implicits which involves the types underlying the implicit. We're searching for an implicit conversion of type Map[String, String] => Boolean. According to the implicit scoping rules, the following is applicable to our use case:
If T is a parameterized type S[T1, ..., Tn], the union of the parts of S and T1, ..., Tn.
Our S[T1.. Tn] is a Map[String, String] (and it's base classes), so we have both Map and String as a candidate type for implicit lookup, but neither of them hold the conversion. Further, the return type is also considered, meaning Boolean is also in scope, but again, it doesn't hold the implicit and hence why the compiler complains.
The simplest thing that can be done to help the compiler find it is to place the implicit inside the companion object of ConvertMap, but that means we can no longer accept a value key in the constructor, which makes your example a bit contrived.
It needs to be resolvable at the call site (where c.value is called).
At that time, the only thing you have in scope c. I am not sure why you would think it makes sense for something defined inside a class to be considered in scope at that point.
BTW, your example doesn't really seem like a good use for implicits to begin with. Why not just make f a member method in the trait?
I have the following simple test-case:
trait Printable[T] {
val string: String
def print() = println("It works: " + string)
}
def foo[T](x: T)(implicit ev: T => Printable[T]) = {
x.print()
}
implicit def doubleToPrint(x: Double): Printable[Double] = new Printable[Double] {
override val string: String = x.toString
}
foo(2.0) // => It works: 2.0
However, creating a new function bar[T](x: T) which should call foo(x) raises an error that there is no implicit view available from T => Printable[T] :
// this does not work
def bar[T](x: T) = {
println("Some other stuff")
foo(x)
}
However, when adding the same parameter it works ofcourse:
// this does work
def bar[T](x: T)(implicit ev: T => Printable[T]) = {
println("Some other stuff")
foo(x)
}
It seems to me quite cumbersome to keep chaining these implicit parameters, because I was under the assumption that the foo function will start searching for the implicit conversion and not the function bar calling foo. As I understand the implicit def doubleToPrint should be in scope for foo also when it is being called from within foo.
What am I overlooking?
Additional question in response to the answer of dth
So I understand the answer, which is actually very logical.
However, the solution of the context bounds does not work in the situation where foo and bar are both part of another trait, since context bounds are not allowed in traits:
// not allowed to do trait FooBar[T : Printable]
trait FooBar[T] {
def foo(x: T)(implicit ev: T => Printable[T]) = {
println("Running foo...")
x.print()
}
// this is not allowed
def bar(x: T) = {
println("But running bar first...")
foo(x)
}
}
So is it also possible to solve this without using the implicit parameter?
My own, not so nice, solution
I came to the conclusion that I actually don't need a trait in my specific code and can replace the FooBar[T] trait with an abstract class FooBar[T <% Printable[T]].
It is a solution for my problem, but not the additional question I added.
Think about, how implicit parameters work:
When you call a method requiring an implicit parameter somewhere the compiler looks in the context (scope, involved types) for a suitable implicit.
Now look at your definition of bar:
def bar[T](x: T) = {
foo(x)
}
When you call foo the compiler looks for an implicit value of the type T => Printable[T] which it cannot find. It does not matter, that you will call bar later with a type Double as it does not know that.
So the answer is yes, you have to pass implicit parameters around everywhere, where you can not find a suitable value in the context (so usually everywhere, where you do not know the concrete type).
There is however syntactic sugar called context bounds, so you can define bar like this:
def bar[T: Printable](x: T) = foo(x)
You could also define foo like this and use implicitly[Printable[T]] to access the values. So you do not have to concern yourself with implicit parameters at all in simple setting like this.
Traits
Context bounds are just syntactic sugar for an implicit parameter. The implicit value is passed where you define the type bound. I.e. if it is the type parameter of a method it is passed to the method.
A trait may not have any constructor parameters as due to linearisation you do not no where it will end up in the inheritance hierarchy. Thus it may not have any implicit parameters or type bounds either.
So you really have to add an implicit parameter to both methods.
If you are implementing some complex API this is fine, if this appears a lot in user code, maybe you can change your design.
Classes
You can use context bounds for type parameters of classes, however the implicit parameter will not be directly used inside of methods of that class. To achieve that you have to provide a local implicit conversion like this:
class FooBar[T: Printable] {
implicit def conv(x: T) = implicitly[Printable[T]]
def foo(x: T) = {
println("Running foo...")
x.print()
}
def bar(x: T) = {
println("But running bar first...")
foo(x)
}
}
View Bounds
There are also view bounds as an alternative. They have however been deprecated. If you run scalac with -Xfuture it will show you that.
The problem here is the type T.
Means, that without
(implicit ev: T => Printable[T])
the compiler tries to find an implicit that would work for any type of T
which he can not, because there is an implicit only for Double.
But if you add
(implicit ev: T => Printable[T])
the compiler tries to find the implicit at the place you call bar.
And if you call it with a Double parameter he takes doubleToPrint and passes it by.
Assume there are such two traits:
trait Fooer[-T] {
def foo(x: T): Unit
}
trait CanFoo[-T] {
def fooer: Fooer[T]
}
And a function:
def bar[T: CanFoo](x: T) = {
implicitly[CanFoo[T]].fooer.foo(x)
}
Everything works so far. However, I was stuck when trying to make bar work recursively on collection types like Seq[T] (i.e. bar[Seq[T]](seq) recursively calls bar[T] on seq's elements). I can't do implicit object CanFooSeq extends CanFoo[Seq[_]] since that would cause the type information of the elements to be lost. (I also tried to make another function def bar[T: CanFoo](seq: Seq[T]) = ..., but that didn't solve the problem either since Seq[T] still isn't being recognized as a Foo-able type.)
Is there any way to solve this problem?
implicit def CanFooSeq[T]: CanFoo[Seq[T]] = new CanFoo[Seq[T]] { def fooer = ... }
(if you want to have it only in case you have CanFoo[T], add the implicit parameter: implicit def CanFooSeq[T: CanFoo]: CanFoo[Seq[T]] = new CanFoo[Seq[T]] { def fooer = ... }) if I understood the question correctly. Note it has to be a def, because objects and vals can't have type parameters, so a new one will be created on each call (which is very unlikely to matter for performance in practice).
I'm having trouble finding what this is called and what the difference is exactly between defining a method like this:
def method[A](//...//) {}
or
def method(//...//) {}
Also, is def method[A] the same as def method[Any]?
Help would be greatly appreciated.
def method[A] defines a generic type A. Used like this, with no refinement, it is a wildcard that can be satisfied by any type. (You can specify that only some subtypes are allowed with syntax like [A <: Foo], where Foo is a class or trait you've defined.)
Why would you want to do this? Most likely, you want a method that returns the same type that it takes as an argument (or some variation thereof--maybe it takes a list of that type and returns an array of that type):
def method[A](a: A): A = ...
Since you don't know anything about A, it is as generic as Any.
Now, there's nothing special about A. You could put anything there, even Any:
def method[Any](a: Any) ... // Don't do this!
But this would be supremely confusing, because this isn't your standard Any type that is at the top of the inheritance hierarchy--it's a generic type just like A, but with a longer name.
If you don't need to use a generic type, omit the [A]. For example:
def printed[A](a: A): A = { println(a); a } // Generic necessary
def printMe(a: Any) { println(a) } // Not necessary, returns Unit
I have read the answer to my question about scala.math.Integral but I do not understand what happens when Integral[T] is passed as an implicit parameter. (I think I understand the implicit parameters concept in general).
Let's consider this function
import scala.math._
def foo[T](t: T)(implicit integral: Integral[T]) { println(integral) }
Now I call foo in REPL:
scala> foo(0)
scala.math.Numeric$IntIsIntegral$#581ea2
scala> foo(0L)
scala.math.Numeric$LongIsIntegral$#17fe89
How does the integral argument become scala.math.Numeric$IntIsIntegral and scala.math.Numeric$LongIsIntegral ?
The short answer is that Scala finds IntIsIntegral and LongIsIntegral inside the object Numeric, which is the companion object of the class Numeric, which is a super class of Integral.
Read on for the long answer.
Types of Implicits
Implicits in Scala refers to either a value that can be passed "automatically", so to speak, or a conversion from one type to another that is made automatically.
Implicit Conversion
Speaking very briefly about the latter type, if one calls a method m on an object o of a class C, and that class does not support method m, then Scala will look for an implicit conversion from C to something that does support m. A simple example would be the method map on String:
"abc".map(_.toInt)
String does not support the method map, but StringOps does, and there's an implicit conversion from String to StringOps available (see implicit def augmentString on Predef).
Implicit Parameters
The other kind of implicit is the implicit parameter. These are passed to method calls like any other parameter, but the compiler tries to fill them in automatically. If it can't, it will complain. One can pass these parameters explicitly, which is how one uses breakOut, for example (see question about breakOut, on a day you are feeling up for a challenge).
In this case, one has to declare the need for an implicit, such as the foo method declaration:
def foo[T](t: T)(implicit integral: Integral[T]) {println(integral)}
View Bounds
There's one situation where an implicit is both an implicit conversion and an implicit parameter. For example:
def getIndex[T, CC](seq: CC, value: T)(implicit conv: CC => Seq[T]) = seq.indexOf(value)
getIndex("abc", 'a')
The method getIndex can receive any object, as long as there is an implicit conversion available from its class to Seq[T]. Because of that, I can pass a String to getIndex, and it will work.
Behind the scenes, the compile changes seq.IndexOf(value) to conv(seq).indexOf(value).
This is so useful that there is a syntactic sugar to write them. Using this syntactic sugar, getIndex can be defined like this:
def getIndex[T, CC <% Seq[T]](seq: CC, value: T) = seq.indexOf(value)
This syntactic sugar is described as a view bound, akin to an upper bound (CC <: Seq[Int]) or a lower bound (T >: Null).
Please be aware that view bounds are deprecated from 2.11, you should avoid them.
Context Bounds
Another common pattern in implicit parameters is the type class pattern. This pattern enables the provision of common interfaces to classes which did not declare them. It can both serve as a bridge pattern -- gaining separation of concerns -- and as an adapter pattern.
The Integral class you mentioned is a classic example of type class pattern. Another example on Scala's standard library is Ordering. There's a library that makes heavy use of this pattern, called Scalaz.
This is an example of its use:
def sum[T](list: List[T])(implicit integral: Integral[T]): T = {
import integral._ // get the implicits in question into scope
list.foldLeft(integral.zero)(_ + _)
}
There is also a syntactic sugar for it, called a context bound, which is made less useful by the need to refer to the implicit. A straight conversion of that method looks like this:
def sum[T : Integral](list: List[T]): T = {
val integral = implicitly[Integral[T]]
import integral._ // get the implicits in question into scope
list.foldLeft(integral.zero)(_ + _)
}
Context bounds are more useful when you just need to pass them to other methods that use them. For example, the method sorted on Seq needs an implicit Ordering. To create a method reverseSort, one could write:
def reverseSort[T : Ordering](seq: Seq[T]) = seq.reverse.sorted
Because Ordering[T] was implicitly passed to reverseSort, it can then pass it implicitly to sorted.
Where do Implicits Come From?
When the compiler sees the need for an implicit, either because you are calling a method which does not exist on the object's class, or because you are calling a method that requires an implicit parameter, it will search for an implicit that will fit the need.
This search obey certain rules that define which implicits are visible and which are not. The following table showing where the compiler will search for implicits was taken from an excellent presentation about implicits by Josh Suereth, which I heartily recommend to anyone wanting to improve their Scala knowledge.
First look in current scope
Implicits defined in current scope
Explicit imports
wildcard imports
Same scope in other files
Now look at associated types in
Companion objects of a type
Companion objects of type parameters types
Outer objects for nested types
Other dimensions
Let's give examples for them.
Implicits Defined in Current Scope
implicit val n: Int = 5
def add(x: Int)(implicit y: Int) = x + y
add(5) // takes n from the current scope
Explicit Imports
import scala.collection.JavaConversions.mapAsScalaMap
def env = System.getenv() // Java map
val term = env("TERM") // implicit conversion from Java Map to Scala Map
Wildcard Imports
def sum[T : Integral](list: List[T]): T = {
val integral = implicitly[Integral[T]]
import integral._ // get the implicits in question into scope
list.foldLeft(integral.zero)(_ + _)
}
Same Scope in Other Files
This is like the first example, but assuming the implicit definition is in a different file than its usage. See also how package objects might be used in to bring in implicits.
Companion Objects of a Type
There are two object companions of note here. First, the object companion of the "source" type is looked into. For instance, inside the object Option there is an implicit conversion to Iterable, so one can call Iterable methods on Option, or pass Option to something expecting an Iterable. For example:
for {
x <- List(1, 2, 3)
y <- Some('x')
} yield, (x, y)
That expression is translated by the compile into
List(1, 2, 3).flatMap(x => Some('x').map(y => (x, y)))
However, List.flatMap expects a TraversableOnce, which Option is not. The compiler then looks inside Option's object companion and finds the conversion to Iterable, which is a TraversableOnce, making this expression correct.
Second, the companion object of the expected type:
List(1, 2, 3).sorted
The method sorted takes an implicit Ordering. In this case, it looks inside the object Ordering, companion to the class Ordering, and finds an implicit Ordering[Int] there.
Note that companion objects of super classes are also looked into. For example:
class A(val n: Int)
object A {
implicit def str(a: A) = "A: %d" format a.n
}
class B(val x: Int, y: Int) extends A(y)
val b = new B(5, 2)
val s: String = b // s == "A: 2"
This is how Scala found the implicit Numeric[Int] and Numeric[Long] in your question, by the way, as they are found inside Numeric, not Integral.
Companion Objects of Type Parameters Types
This is required to make the type class pattern really work. Consider Ordering, for instance... it comes with some implicits in its companion object, but you can't add stuff to it. So how can you make an Ordering for your own class that is automatically found?
Let's start with the implementation:
class A(val n: Int)
object A {
implicit val ord = new Ordering[A] {
def compare(x: A, y: A) = implicitly[Ordering[Int]].compare(x.n, y.n)
}
}
So, consider what happens when you call
List(new A(5), new A(2)).sorted
As we saw, the method sorted expects an Ordering[A] (actually, it expects an Ordering[B], where B >: A). There isn't any such thing inside Ordering, and there is no "source" type on which to look. Obviously, it is finding it inside A, which is a type parameter of Ordering.
This is also how various collection methods expecting CanBuildFrom work: the implicits are found inside companion objects to the type parameters of CanBuildFrom.
Outer Objects for Nested Types
I haven't actually seen examples of this. I'd be grateful if someone could share one. The principle is simple:
class A(val n: Int) {
class B(val m: Int) { require(m < n) }
}
object A {
implicit def bToString(b: A#B) = "B: %d" format b.m
}
val a = new A(5)
val b = new a.B(3)
val s: String = b // s == "B: 3"
Other Dimensions
I'm pretty sure this was a joke. I hope. :-)
EDIT
Related questions of interest:
Context and view bounds
Chaining implicits
The parameter is implicit, which means that the Scala compiler will look if it can find an implicit object somewhere that it can automatically fill in for the parameter.
When you pass in an Int, it's going to look for an implicit object that is an Integral[Int] and it finds it in scala.math.Numeric. You can look at the source code of scala.math.Numeric, where you will find this:
object Numeric {
// ...
trait IntIsIntegral extends Integral[Int] {
// ...
}
// This is the implicit object that the compiler finds
implicit object IntIsIntegral extends IntIsIntegral with Ordering.IntOrdering
}
Likewise, there is a different implicit object for Long that works the same way.