In the Scala Odersky book, he has an example explaining partial functions of page 295. It starts with this function:
val second: List[Int] => Int = {
case x :: y :: _ => y
}
So the above function will succeed if you pass it a three element list but not an empty list.
second(List(5,6,7))
works but not
second(List())
The above will throw a MatchError: List
Here is the part that is confusing to me. Odersky writes:
If you want to check whether a partial function is defined, you must first tell the compiler that you know you are working with partial functions.
Why would I want to check whether a partial function is defined. What is a partial function? Is it a function that only applies to some values?
The type List[Int] => Int includes all functions from lists of integers to integers, whether or not the functions are partial. The type that only includes partial functions from lists of integers to integers is written PartialFunction[List[Int], Int].
So the above function returns a function of type List[Int] => Int, I see that, but why do we need to change this function to type PartialFunction[List[Int], Int]?
Here is the function redefined:
val second: PartialFunction[List [Int], Int] = {
case x :: y :: _ => y
}
I don't really get it. What is the benefit? Why do we want to check whether a partial function is defined? What does that even mean?
A partial function is any function, which takes only a single argument, that is defined (i.e. valid) only for a certain range of its argument's values. For example, Math.asin is defined only for argument values in the range [-1.0, 1.0] and is undefined for values outside of that range - so it is a partial function. For example, if we call Math.asin(5.0), we get NaN returned, meaning that the function is not defined for that argument.
Note that a partial function doesn't necessarily have to throw an exception; it just needs to do something other than return a valid value.
A key principle of functional programming is referential transparency (RT), meaning that we should be able to replace an expression (such as a function call) with the value of that expression, without changing the meaning of the program. (For more on this topic, I highly recommend that you read Functional Programming in Scala by Chiusano and Bjarnason.) Clearly, that breaks down if an exception is thrown or if an invalid value is returned. For calls to partial functions to be referentially transparent, we can only call them with argument values for which they are defined, or we need to elegantly handle the undefined values. So how can we tell if a partial function is defined for some arbitrary argument value?
In Scala we can express partial functions as a subclass of scala.PartialFunction that allows us to answer this question.
Let's look at your example in a Scala REPL session...
$ scala
Welcome to Scala 2.12.6 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_171).
Type in expressions for evaluation. Or try :help.
scala> val second: List[Int] => Int = {
| case x :: y :: _ => y
| }
<console>:11: warning: match may not be exhaustive.
It would fail on the following inputs: List(_), Nil
val second: List[Int] => Int = {
^
second: List[Int] => Int = $$Lambda$3181/1894473818#27492c62
So what did we just do? We defined second as a reference to a function that takes a List[Int] argument and returns an Int (the second value in the list).
You'll notice that the Scala compiler recognizes that this is not going to match all cases and warns you of the fact. This is a partial function, in the sense that it will fail for some arguments, but it's not an instance of scala.PartialFunction, as we can verify as follows:
scala> second.isInstanceOf[PartialFunction[List[Int], Int]]
res0: Boolean = false
Incidentally, the type List[Int] => Int is a shorthand for scala.Function1[List[Int], Int] and so seconds type is an instance of that type:
scala> second.isInstanceOf[Function1[List[Int], Int]]
res1: Boolean = true
Calling this version of the function produces the results you indicate:
scala> second(List(1, 2, 3))
res1: Int = 2
scala> second(Nil)
scala.MatchError: List() (of class scala.collection.immutable.Nil$)
at .$anonfun$second$1(<console>:11)
at .$anonfun$second$1$adapted(<console>:11)
... 36 elided
The problem is that if we just have some list value, l, and don't know what is in that list, we don't know whether we'll get an exception if we pass it to the function referenced by second. Now, we could put the call in a try block and catch any exception, but that's verbose and not good functional programming style. Ideally, we'd like to know whether we can call the function first to avoid an exception. Unfortunately, there's no way to tell from a Function1 instance:
scala> second.isDefinedAt(Nil)
<console>:13: error: value isDefinedAt is not a member of List[Int] => Int
second.isDefinedAt(Nil)
^
What we need is to declare second to have the type PartialFunction[List[Int], Int] as follows:
scala> val second: PartialFunction[List[Int], Int] = {
| case x :: y :: _ => y
| }
second: PartialFunction[List[Int],Int] = <function1>
(BTW, note that you have a typo in your question for this code - the above is how this should be defined.)
Now we do not have any warnings! We've told the compiler that this is a PartialFunction instance, so the compiler knows that its undefined for some arguments, so warnings are superfluous. We can now verify that fact:
scala> second.isInstanceOf[PartialFunction[List[Int], Int]]
res6: Boolean = true
We can now also verify whether it's defined for particular values:
scala> second.isDefinedAt(Nil)
res7: Boolean = false
scala> second.isDefinedAt(List(1, 2))
res9: Boolean = true
and so on. (The Scala compiler, as described in the book, is able to implement this magical isDefinedAt function for us.)
So, does that mean we should now write code like this:
def getSecondValue(l: List[Int]): Option[Int] = {
// Check if second is defined for this argument. If so, call it and wrap in Some.
if(second.isDefinedAt(l)) Some(second(l))
// Otherwise, we do not have a second value.
else None
}
Well, that's a little verbose too. Fortunately, once second is a PartialFunction instance, we can rewrite the above as:
def getSecondValue(l: List[Int]): Option[Int] = second.lift(l)
The lift method turns a partial function into a complete function that returns a defined value for every argument: if the argument to second is defined, then we get a Some(value); otherwise, we get None.
You'll find the concept of partial functions, and PartialFunction, more useful as you become more familiar with functional programming. If you don't get it right now, don't worry; all will become clear.
A partial function is a function that does not provide an answer for every possible input value it can be given. It provides an answer only for a subset of possible data, and defines the data it can handle. In Scala, a partial function can also be queried to determine if it can handle a particular value.
As a simple example, imagine a normal function that divides one number by another:
val divide = (x: Int) => 42 / x
As defined, this function blows up when the input parameter is zero:
scala> divide(0)
java.lang.ArithmeticException: / by zero
Although you can handle this particular situation by catching and throwing an exception, Scala lets you define the divide function as a PartialFunction. When doing so, you also explicitly state that the function is defined when the input parameter is not zero:
val divide = new PartialFunction[Int, Int] {
def apply(x: Int) = 42 / x
def isDefinedAt(x: Int) = x != 0
}
https://alvinalexander.com/scala/how-to-define-use-partial-functions-in-scala-syntax-examples
You can refer to the above link.
I'd like to call a function returned by a function with an implicit parameter, simply and elegantly. This doesn't work:
def resolveA(implicit a: A): String => String = { prefix =>
s"$prefix a=$a"
}
case class A(n: Int)
implicit val a = A(1)
println(resolveA("-->")) // won't compile
I've figured out what's going on: Scala sees the ("-->") and thinks it's an attempt to explicitly fill in the implicit parameter list. I want to pass that as the prefix argument, but Scala sees it as the a argument.
I've tried some alternatives, like putting an empty parameter list () before the implicit one, but so far I've always been stopped by the fact that Scala thinks the argument to the returned function is an attempt to fill in the implicit parameter list of resolveA.
What's a nice way to do what I'm trying to do here, even if it's not as nice as the syntax I tried above?
Another option would be to use the apply method of the String => String function returned by resolveA. This way the compiler won't confuse the parameter lists, and is a little shorter than writing implicltly[A].
scala> resolveA[A].apply("-->")
res3: String = --> a=A(1)
Working in Scala-IDE, I have a Java library, in which one of the methods receives java.lang.Object. And I want to map a list of Int values to it. The only solution that works is:
val listOfInts = groupOfObjects.map(_.getNeededInt)
for(int <- listOfInts) libraryObject.libraryMethod(int)
while the following one:
groupOfObjects.map(_.getNeededInt).map(libraryMethod(_)
and even
val listOfInts = groupOfObjects.map(_.getNeededInt)
val result = listOfInts.map(libraryObject.libraryMethod(_))
say
type mismatch; found : Int required: java.lang.Object Note: an
implicit exists from scala.Int => java.lang.Integer, but methods
inherited from Object are rendered ambiguous. This is to avoid a
blanket implicit which would convert any scala.Int to any AnyRef. You
may wish to use a type ascription: x: java.lang.Integer.
and something like
val result = listOfInts.map(libraryObject.libraryMethod(x => x.toInt))
or
val result = listOfInts.map(libraryObject.libraryMethod(_.toInt))
does not work also.
1) Why is it happening? As far as I know, the for and map routines do not differ that much!
2) Also: what means You may wish to use a type ascription: x: java.lang.Integer? How would I do that? I tried designating the type explicitly, like x: Int => x.toInt, but that is too erroneus. So what is the "type ascription"?
UPDATE:
The solution proposed by T.Grottker, adds to it. The error that I am getting with it is this:
missing parameter type for expanded function ((x$3) => x$3.asInstanceOf[java.lang.Object])
missing parameter type for expanded function ((x$3) => x$3.asInstanceOf{#null#}[java.lang.Object]{#null#}) {#null#}
and I'm like, OMG, it just grows! Who can explain what all these <null> things mean here? I just want to know the truth. (NOTE: I had to replace <> brakets with # because the SO engine cut out the whole thing then, so use your imagination to replace them back).
The type mismatch tells you exactly the problem: you can convert to java.lang.Integer but not to java.lang.Object. So tell it you want to ask for an Integer somewhere along the way. For example:
groupOfObjects.map(_.getNeededInt: java.lang.Integer).map(libraryObject.libraryMethod(_))
(The notation value: Type--when used outside of the declaration of a val or var or parameter method--means to view value as that type, if possible; value either needs to be a subclass of Type, or there needs to be an implicit conversion that can convert value into something of the appropriate type.)
I meet some scala code with "?" but do not know what it mean in scala, could anyone explain it to me ? Thanks.
And here's one example
def getJobId(conf: Configuration): String =
?(conf.get("scoobi.jobid")).getOrElse(sys.error("Scoobi job id not set."))
For me it looks like the apply method of Option. Is there somewhere the following import statement in the code:
import Option.{apply => ?}
This means apply is imported as ?. From the doc of Option.apply:
An Option factory which creates Some(x) if the argument is not null,
and None if it is null.
The whole statement means then:
if conf.get("scoobi.jobid") is not equal null, assign this string,
otherwise assign the string sys.error("Scoobi job id not set.")
returns
It's just a legal character, just like "abcd..."
scala> def ?(i: Int) = i > 2
$qmark: (i: Int)Boolean
scala> val a_? = ?(3)
a_?: Boolean = true
UPD: See Valid identifier characters in Scala , Scala method and values names
UPD2: In the example "?" could be function, method of this or just some object with apply method. It probably returns Option[String].
Is there another way of making this work?
def b(first:String="hello",second:String) = println("first:"+first+" second:"+second)
b(second="geo")
If I call the method with just:
b("geo")
I get:
<console>:7: error: not enough arguments for method b: (first: String,second: String)Unit.
Unspecified value parameter second.
b("geo")
Here is one of the possible ways: you can use several argument lists and currying:
scala> def b(first:String="hello")(second:String) = println("first:"+first+" second:"+second)
b: (first: String)(second: String)Unit
scala> b()("Scala")
first:hello second:Scala
scala> val c = b() _
c: (String) => Unit = <function1>
scala> c("Scala")
first:hello second:Scala
See scala language specifications 6.6.1 (http://www.scala-lang.org/docu/files/ScalaReference.pdf):
"The named arguments form a suffix of the argument list e1, ..., em, i.e. no positional argument follows a named one."
Providing a single string parameter (without naming it) is too ambiguous for the compiler. Probably you meant the value for the non-default parameter, but... maybe not. So the compiler wants you to be more specific.
Generally you put all your default parameters at the end of the method signature (if you did in this case, b("geo") would work) so that they can be left out less ambiguously.