Reputation: 692
So i got the following function after some trial and error and research in our Textbook i could come up with a solution.
def prodC1(f : Int => Int) : (Int, Int) => Int = {
def prodA1(a : Int, b : Int) : Int =
if(a > b) 1 else f(a) * prodA1(a+1, b)
prodA1 // Why do i need this line here
}
If I don't put that there i get a Type mismatch, could someone elaborate/explain the requirement for this Line?
Upvotes: 4
Views: 162
Reputation: 1868
Your function needs to return an instance of (Int, Int) => Int.
def prodA1(a : Int, b : Int) : Int =
if(a > b) 1 else f(a) * prodA1(a+1, b)
Creates a function of type (Int, Int) => Int
with name prodA1 but the return type of defining an inner function does not create an instance of anything so the return type of the function is Unit
.
Therefore you need to return the prodA1
which has the correct type..
Upvotes: 0
Reputation: 13985
So there are a lot of things which you need to know to actually understand the answer to this.
In Scala any def
is a method
which is nothing more than one of the members of some object
. methods
are not first class members in Scala which also means that methods
can not exist on their own.
In Scala, the value
of anything needs to be an expression
. Meaning the RHS for a def
needs to be an expression like def abc = some-expression
. Examples of expression are 1
, 1 + 1
, "xyz"
, anotherMethodCallWhichWillReturnAnExpression()
etc.
And something like def abc = xxxxxx
is not an expression
in Scala language definition. And hence you can not do,
def prodC1(f : Int => Int) : (Int, Int) => Int = {
def prodA1(a : Int, b : Int) : Int =
if(a > b) 1 else f(a) * prodA1(a+1, b)
}
Now, when you are adding that extra line with prodA1
, you are telling Scala to return this prodA1
which you just define. But remember prodA1
is just a method
and hence can not exist on its own and hence can not actually be returned.
But functions
are first class members in Scala (represented as instances of one of the various FunctionX
classes) and hence can be returned.
In this case Scala will intelligently lift this method
to become a function
of type (Int, Int) => Int
. This is called eta-expansion.
To understand things more in detail. You can open the Scala console and try the following.
scala> val s = "abc"
// s: String = abc
scala> val i = 10
// i: Int = 10
scala> def prodA1(a : Int, b : Int) : Int = if (a > b) 1 else a * prodA1(a+1, b)
// prodA1: (a: Int, b: Int)Int
Notice the difference between the output of Scala console for actual values
and def
. Now, if I try to use prodA1
as value
of a val
, I will get following error.
scala> val x = prodA1
// <console>:12: error: missing argument list for method prodA1
// Unapplied methods are only converted to functions when a function type is expected.
// You can make this conversion explicit by writing `prodA1 _` or `prodA1(_,_)` instead of `prodA1`.
// val x = prodA1
Scala is telling you that you can explicitly convert method
to function
by using a _
. Lets try that.
scala> val x = prodA1 _
// x: (Int, Int) => Int = $$Lambda$1077/293669143@13278a41
Now x
is a function
of type (Int, Int) => Int
.
Also, that first line Unapplied methods are only converted to functions when a function type is expected.
is telling you about what actually happened in your case.
Since prodC1
was expected to return a function
of type (Int, Int) => Int
and you provided prodA1
, Scala used eta-expansion
to automatically convert your method
to function
.
Upvotes: 6
Reputation: 1707
Let's have a look at your return type.
def prodC1(f : Int => Int) : (Int, Int) => Int = {
def prodA1(a : Int, b : Int) : Int =
if(a > b) 1 else f(a) * prodA1(a+1, b)
prodA1 // Why do i need this line here
}
your return type is
(Int, Int) => Int
that is scala sugar for a Function2[Int, Int, Int]
where the first param is the type to the first param, the second param is the type for the second param and the last is the type for the return param
The return instance needs to be a function
prodA1 conforms to this type, meaning it is allowed to be returned.
Upvotes: 0