How to use function with Any input - scala

I have to define a second order function that takes as a parameter a function.
In my application, the input function may have any input type, but the output type has to be a specified one (suppose Int, it does not matter).
I define the second order function has:
def sof(f : (Any => Int) ) = {...}
Now, if I have a function f : Int => Int, and I call:
sof(f)
I get:
found : Int => Int
required: Any => Int
I guess I am misunderstanding the meaning of the Any type.
How can I make it work?

The parameters of functions in Scala are contravariant. That means that Int => Int is not a subtype of Any => Int, but vice-versa. Imagine the following: You pass a String to the Any => Int function (that is actually implemented by a Int => Int function). How would the Int => Int handle the String argument?

You shouldn't use Any there, but a type parameter such as:
def sof[A](f: A => Int) = {...}
However I don't think you can do much with that method. Probably you would want something like this:
def sof[A](a: A)(f: A => Int) = f(a)
// usage example
val x = sof("hello")(_.size * 2) // the result is 10
// you can also partially apply it to obtain other functions
val sizeDoubler: String => Int = sof(_)(_.size * 2)
val helloDoubleSize = sizeDoubler("hello") // the result is 10
This way you can pass any type to sof plus you'll have the compiler by your side to signal any strange behaviour. Using Any you lose this ability.
Final Note: In case the syntax I used to pass two parameters (the A value and the A => Int function) to a method looks strange to you that's called currying. If you Google it you'll find many good articles about it.

Related

What’s the difference between ‘x: () => Int’ and ‘x: => Int’

When using these in a function parameters description, they have different effects.
Only the latter form can accept multi-line operations like
{
println(“hello”)
println(“world”)
1
}
However, the former can’t.
I know ‘()’ means “no parameters”, right? But what ‘’ means in ‘=>Int’?
Here's the whole story.
Define a function
def func(x: =>Int)= {
println(x)
}
Invoke it
func {
println("hello")
println("world")
1
}
We will get
hello
world
1
However, if we define the function as
def func(x: ()=>Int)= {
println(x)
}
Invoke it using the former code, we will get
error: type mismatch;
found : Int(1)
required: () => Int
1
^
So, what's the difference between ‘x: () => Int’ and ‘x: => Int’?
Behaviors Of Call By Name Evaluation VS Higher-Order Functions
Call By Name Evaluation:
In case of call by name, the expression is evaluated before the function is invoked.
Example:
def func(x: =>Int): Int= {
x
}
func(10 + 2)
Higher-Order Functions:
In case of HOF, the function is passed and its result are computed when the function is invoked.
Example:
def func(x: () =>Int): () => Int = {
x
}
func(() => 10 + 2)
Note: Check the return types for more clarity.
Essentially, there is no difference. Both represent 0-arity functions which result in an Int value.
However, there is a big difference in how they are used. One, x: => Int, is used for a call-by-name parameter in a method and is invoked simply by referencing an Int. The compiler does the rest.
The other form, x: () => Int, is used for a method parameter where you really want to pass in a 0-arity function. But when you use x within your method, you must actually give it parentheses. And, of course, when you invoke the method, you need to pass in a function (or partially-applied method), not an Int.
Here's an example:
def and(a: Boolean, b: () => Boolean): Boolean = if (a) b() else false
def not(): Boolean = false
println(and(true, not))

Understanding Scala Currying

I am following a course from coursera where this example appears in the lecture but when I try and run it, it throws an error as follows:
missing argument list for method mapReduce in object HelloWorld
Unapplied methods are only converted to functions when a function type is expected.
You can make this conversion explicit by writing mapReduce _ or mapReduce(_,_,_)(_,_) instead of mapReduce.
var doo = mapReduce(x => x,(x,y)=>x*y,0)
Below is the code that I want to execute.
def mapReduce(map: Int => Int, combine: (Int,Int)=>Int,
zero: Int)(a: Int,b: Int): Int = {
if (a>b) zero
else combine(map(a), mapReduce(map,combine,zero)(a+1,b))
}
var doo = mapReduce(x => x, (x,y)=>x*y, 0)
println(doo(1,4))
mapReduce wants two argument lists, but your are giving it one.
Try this:
val doo = mapReduce(x => x, (x,y) => x*y, 0) _
or equivalently,
val doo = mapReduce(identity, _*_, 0) _
The _ in the end stands for the second argument list. It tells the compiler that you want the suffixed value to be taken as a functional value rather than an expression to be evaluated.
You can also give compiler a hint to make the conversion happen automatically by explicitly declaring the expected type of the expession:
val doo: (Int, Int) => Int = mapReduce(identity, _*_, 0)
And don't use vars. They are evil. Just pretend, there is no such keyword in scala, until you learn enough of the language to be able to recognize the extremely rare cases when it is actually needed.
You have to define a undescore parameter in order to create a curried function. Like this:
scala> var doo = mapReduce(x => x, (x,y)=>x*y, 0) _
doo: (Int, Int) => Int = <function2>
scala> println(doo(1,4))
0

Scala anonymous function syntax and return type

I have found few kinds of anonymous function syntax in scala:
val m5_1 = { (n: Int) => n * 5 }
val m5_2 = (n: Int) => { n * 5 } : Int
val m5_3: Int => Int = n => { n * 5 }
Is that all types or some more syntax kinds present?
Are they all equivalent?
Which one is more/less preferred?
How can I specify the return type in m5_1 ?
I'll try to add to #pamu's answer:
Which one is more/less preferred?
I'd say the second variant is a bit uncommon. When the type inference is easily visible, you can go for the first, otherwise being explicit as in the third case is good. You don't need braces there, so a simpler variant is
val m5_3: Int => Int = n => n * 5
Or even
val m5_3: Int => Int = _ * 5
How can I specify the return type in m5_1 ?
The return type is Int => Int, so that is the same type annotation as you use in the third case:
val m5_1: Int => Int = { (n: Int) => n * 5 }
But then of course, you can let Scala use the type inference on the right hand side:
val m5_1: Int => Int = n => n * 5
And therefore this is identical to your third form.
Note that the : Int in the second form is not defining the type of m5_2, which is Int => Int and not Int. It simply tells Scala that the type of n * 5 is meant to be Int. This can aid you reading the code, but it doesn't actually change the way the type is inferred in this case. You can think of your second form of actually being:
val m5_2 = (n: Int) => {
val res = n * 5: Int // : Int redundant here because it is already inferred
res
}
Where val res = n * 5: Int has the same effect as val res: Int = n * 5
Is that all types or some more syntax kinds present ?
Lambda syntax requires the input parameter type to be known. If not compiler throws an error. In all the syntaxes you are trying to give this information. But return type can be inferred by the compiler.
Are they all equivalent?
All are equivalent
Which one is more/less preferred ?
The below one is recommended if you do not want to see explicit type annotation
val m5_1 = { (n: Int) => n * 5 }
How can I specify the return type in m5_1 ?
Return type is inferred from the last line of the lambda. The last line is n * 5 which of type Int. So, compiler infers the type for you. You can skip giving the type information explicitly
Well, the above answers have properly explained almost everything I guess. I just want to add one more variant that we could do here:
val m5_4 = {n=> n*5}:Int=>Int

Writing tests to verify passing a function as argument in Scala

I have something like this:
def fnA(argA: Int, argB: Int, argC: Int): Seq[Int] = {
tryRequest {
...
}
}
def tryRequest[T](f: => T): T = {
try {
f
} catch {
...
}
}
I'm trying to figure out how to test this with Mockito/ScalaTest. I want to either make sure that 1. my return type is what I expect it to be (Seq[Int] when I call fnA), or 2. that I am passing in the right type to tryRequest when I'm calling it ((Int, Int, Int) => Seq[Int] when I call fnA). I've tried variations of:
exampleInstance.fnA(1, 2, 3)
there was one(exampleInstance).tryRequest(any)
but I always get something like
Argument(s) are different! Wanted:
exampleInstance.tryRequest(
($anonfun$apply$17) <function0>
);
Actual invocation has different arguments:
exampleInstance.tryRequest(
($anonfun$fnA$1) <function0>
);
Any ideas how I can accurately test this? Thanks!
It's not entirely clear what you're passing where - you seem to think you're passing a (Int, Int, Int) => Seq[Int] to tryRequest, but the definition of fnA you give isn't doing that (it's already taken the Int arguments before it calls tryRequest). But going by what you've written rather than the code:
It's generically impossible to compare functions for equality, and that syntax will "really" create an anonymous wrapper (do you really need the laziness of the => T given that you're passing a function in there anyway?), thus the failures. What you can do is confirm that the function that was passed to the inner call has some of the same properties as the function you already passed. I don't know the fancy syntax, but with an ordinary Java testing/mocking library I'd do something like:
val myCaptor = capture[=> ((Int, Int, Int) => Seq[Int])]
expect(exampleInstance.tryRequest(myCaptor.capture()))
exampleInstance.fnA({(a, b, c) => a + b + c})
val functionThatWasPassed = myCaptor.getValue()
assertThat(functionThatWasPassed(3, 4, 5)) isEqualTo 12
assertThat(functionThatWasPassed(-1, 0, 2)) isEqualTo 1

Specifying the lambda return type in Scala

Note: this is a theoretical question, I am not trying to fix anything, nor am I trying to achieve any effect for a practical purpose
When creating a lambda in Scala using the (arguments)=>expression syntax, can the return type be explicitly provided?
Lambdas are no different than methods on that they both are specified as expressions, but as far as I understand it, the return type of methods is defined easily with the def name(arguments): return type = expression syntax.
Consider this (illustrative) example:
def sequence(start: Int, next: Int=>Int): ()=>Int = {
var x: Int = start
//How can I denote that this function should return an integer?
() => {
var result: Int = x
x = next(x)
result
}
}
You can always declare the type of an expression by appending : and the type. So, for instance:
((x: Int) => x.toString): (Int => String)
This is useful if you, for instance, have a big complicated expression and you don't want to rely upon type inference to get the types straight.
{
if (foo(y)) x => Some(bar(x))
else x => None
}: (Int => Option[Bar])
// Without type ascription, need (x: Int)
But it's probably even clearer if you assign the result to a temporary variable with a specified type:
val fn: Int => Option[Bar] = {
if (foo(y)) x => Some(bar(x))
else _ => None
}
Let say you have this function:
def mulF(a: Int, b: Int): Long = {
a.toLong * b
}
The same function can be written as lambda with defined input and output types:
val mulLambda: (Int, Int) => Long = (x: Int, y: Int) => { x.toLong * y }
x => x:SomeType
Did not know the answer myself as I never had the need for it, but my gut feeling was that this will work. And trying it in a worksheet confirmed it.
Edit: I provided this answer before there was an example above. It is true that this is not needed in the concrete example. But in rare cases where you'd need it, the syntax I showed will work.