Let's declare a def and an equivalent function as a val:
scala> def optional(x:Int):Option[String] = None
optional: (x: Int)Option[String]
scala> val optional2:(Int)=>Option[String] = (i:Int) => None
optional2: Int => Option[String] = <function1>
Now why doesn't this work?
scala> List(1).flatMap(optional2)
<console>:9: error: type mismatch;
found : Int => Option[String]
required: Int => scala.collection.GenTraversableOnce[?]
List(1).flatMap(optional2)
^
While both of these do?
scala> List(1).flatMap(optional)
res4: List[String] = List()
scala> List(1).flatMap(optional2(_))
res5: List[String] = List()
Since Option is not a subtype of GenTraversableOnce, I think this must have something to do with implicits, but I can't figure out what exactly it is. I am using Scala 2.9.1.
Difference between Scala Functions & Methods: Function is a object which can be stored in a variable. But a method always belongs to a class which has a name, signature bytecode etc. Basically, you can say a method is a function which is a member of some object.
Implicit parameters are the parameters that are passed to a function with implicit keyword in Scala, which means the values will be taken from the context in which they are called.
A Scala method is a part of a class which has a name, a signature, optionally some annotations, and some bytecode where as a function in Scala is a complete object which can be assigned to a variable. In other words, a function, which is defined as a member of some object, is called a method.
The implicit system in Scala allows the compiler to adjust code using a well-defined lookup mechanism. A programmer in Scala can leave out information that the compiler will attempt to infer at compile time. The Scala compiler can infer one of two situations: A method call or constructor with a missing parameter.
The implicit conversion Option.option2Iterable is what makes List(1).flatMap(optional)
and List(1).flatMap(optional2(_))
work.
Your issue can be boiled down to the implicit conversion not being picked up:
scala> val optional2:(Int)=>Option[String] = (i:Int) => None
optional2: Int => Option[String] = <function1>
scala> (optional2(_)): Function[Int, Iterable[String]]
res0: Int => Iterable[String] = <function1>
scala> (optional2): Function[Int, Iterable[String]]
<console>:9: error: type mismatch;
found : Int => Option[String]
required: Int => Iterable[String]
When you use the underscore, the compiler attempts to type the function and provide the necessary implicit conversion. When you just provide optional2, there is no implicit conversion that applies.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With