Pass function of function as parameter in Scala - scala

I have a method setBuildQuery and I want that it can receive as parameter a function x. The function x should take as input an indefinite number of parameters and output another function y.
Function y takes as input two dates and outputs a string.
Examples using a function notation
x = (one_f)(from_date, to_date) => string or
x = (one_f, two_f)(from_date, to_date) => string or
x = (one_f, two_f, ..., n_f)(from_date, to_date) => string
How can I model this in Scala (i.e. how can I say to a function to accept a function x of this type?
How the user of my app can specify this function as a val ?
I was thinking something like function of function or high order functions. I am not too familiar with them in Scala though.

You can't have a function that takes an arbitrary number of parameters.* The best you could do is take a function that takes a Seq:
def setBuildQuery(f: Seq[YourType] => (Date, Date) => String)
You could then define a function it accepts like this:
val f: Seq[YourType] => (Date, Date) => String =
ls => (from, to) => ???
* You can have a method that takes an arbitrary number of parameters, but that doesn't help here.

There are many way to do that, you can use Partial Application to define your function.
The function will not execute until you invoke it with all its parameters
def x(head:String, tail:String*)(from:Date, to:Date): String = {
println(head) // it doesnt exec until from and to are provided
"result"
}
val y = x("string1", "string2") _
y(new Date, new Date)
or you can return a function
def x(head:String, tail:String*): (Date,Date) => String = {
println(head) // it exec before from and to are provided
(from:Date, to:Date) => {
"result"
}
}
val y = x("string1", "string2")
y(new Date, new Date)

Related

Generate arbitrary Function1 in ScalaCheck

For my testing, I would like to generate arbitrary random functions of type String => Boolean.
Is it possible to do that using ScalaCheck?
Yes, just like you'd generate arbitrary values of other types:
import org.scalacheck._
// Int instead of Boolean to better see that it is a function
val arb = implicitly[Arbitrary[String => Int]].arbitrary.sample.get
println(arb("a"))
println(arb("a")) // same
println(arb("b"))
because there is an implicit Cogen[String] and an Arbitrary[Boolean]. Cogen is not documented in the User Guide, but it's equivalent to QuickCheck's CoArbitrary which is explained in https://kseo.github.io/posts/2016-12-14-how-quick-check-generate-random-functions.html and https://begriffs.com/posts/2017-01-14-design-use-quickcheck.html (under "CoArbitrary and Gen (a -> b)").
Is it possible then to generate arbitrary function from a random case class then? For example
case class File(name: Str, size:Long)
It should be enough to define a Cogen[File]. Either manually:
implicit val cogenFile: Cogen[File] = Cogen {
(seed: Seed, file: File) => Cogen.perturbPair(seed, (file.name, file.size))
}
Slightly more code, but generalizes to more than 2 fields:
implicit val cogenFile: Cogen[File] = Cogen { (seed: Seed, file: File) =>
val seed1 = Cogen.perturb(seed, file.name)
Cogen.perturb(seed1, file.size)
}
Or automatically using scalacheck-shapeless:
implicit val cogenFile: Cogen[File] = MkCogen[File].cogen
I don't think, you need to generate anything. If you want a random function, just create a random function:
val randomFunction: String => Boolean = _ => Random.nextBoolean
Or if you want the output to be stable (same result for multiple calls of the same function with the same parameter):
def newRandomFunction: String => Boolean =
mutable.Map.empty[String, Boolean].getOrElseUpdate(_, Random.nextBoolean)

Scala - Two functions sharing the second parameter list

I am new in Scala and I just came across a situation that I would like someone could explain me.
When watching a Martin Odersky's course I found the following script he uses to explain functions which return a function
val tolerance = 0.0001
def isCloseEnough(x : Double, y : Double) = abs((x - y)/ x) / x < tolerance
def fixedPoint(f : Double => Double)(firstGuess: Double) = {
def iterate(guess: Double): Double = {
val next = f(guess)
if(isCloseEnough(guess,next))next
else iterate(next)
}
iterate(firstGuess)
}
fixedPoint(x => 1 + x/2)(1)
def averageDamp(f: Double => Double)(x: Double) = (x + f(x))/2
def sqrt(x : Double) = fixedPoint(averageDamp(y => x/y))(1)
sqrt(2)
I understand perfectly how the scrip works, but I didn't expect this line:
fixedPoint(averageDamp(y => x/y))(1)
I know that thanks to Currying, Scala let us write functions with several parameter list. So the call to fixedPoint passing as parameter the result of avergaDamp and (1) is clear for me.
What I don't understand is how averageDamp uses the second parameter list of fixedPoint when it itself is inside the first parameter list. I though that would be a different scope, so I was expecting something like:
fixedPoint(averageDamp(y => x/y)(1))(1)
What is the property of Scala which allow us to implement the currying in this way? Is something similar to an implicit applied to a parameter list?
Thanks for your time
This is just how multiple parameter lists work: averageDamp(y => x/y) is equivalent to z => averageDamp(y => x/y)(z) and so its type is Double => Double.
If you wrote fixedPoint(averageDamp(y => x/y)(1))(1) as you expect, it would have a type mismatch because averageDamp(y => x/y)(1) has type Double and fixedPoint needs Double => Double.
Implicits aren't relevant here.
This line works because in the following expression:
fixedPoint(averageDamp(y => x/y))(1)
function "averageDamp(y => x/y)" is "passed by name" i.e. it will not be evaluated while passing to function "fixedPoint" but will be evaluated when it is called from inside "fixedPoint".
value "(1)" is just pass to argument "firstGuess" of "fixedPoint" which will be supplied to parameter "guess" inside the function definition in following expression:
val next = f(guess)

How to use function with Any input

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.

Convert Scala foreach to .map

I'm new to Scala and I'm trying to convert code of the form
val series: ListBuffer[Seq[Seq[Any]]] = ListBuffer[Seq[Seq[Any]]]()
points.foreach(point => {
if( conditionA )
series += doA(...) // returns a ListBuffer[Seq[Any]]
else
series += doB(...) // returns a ListBuffer[Seq[Any]]
})
to use .map(). I'm thinking its something like:
val series: ListBuffer[Seq[Seq[Any]]] = points.map(point => {
case conditionA => doA(...)
case _ => doB(...)
})
but this doesn't compile because (I believe) the mapped sequences get appended as a single Seq[Any] instead of Seq[Seq[Any]], so I get the error
Expression of type Seq[Any] doesn't conform to expected type ListBuffer[Seq[Seq[Any]]]
Any ideas? Is there something wrong with syntax?
Let me suppose a few things, you have some function def doA(arg1: A): ListBuffer[Seq[Any]] such that you ultimately want to arrive at a List[Seq[Any]] as the final result type after mapping this function over your collection. Then what you want is flatMap instead of map:
val series = points flatMap{
case point if conditionA(point) => doA(point) result ()
case point => doB(point) result ()
}
The reason I make such a supposition is that the only reason you'd ever want to use a ListBuffer[A] in the general form is to create a List[A] through some side-effecting expression. Hence, you ultimately want a List[Seq[A]] as your final output.

What does "code: => Unit" mean in scala?

Does anyone know the type of => Unit in scala? I don't know the meaning of => Unit and how to use it. I defined a function like below:
def test(code: => Unit){
print("start ...")
code
print("end ....")
}
test(print(1))
Does it means a function with any arguments returning Unit?
Thanks
This kind of parameter are called by-name parameter
=> B represents a block a of code which return a B value, their purpose is that they are evaluated only when you call the parameter.
def foo(code: => Int) {
println("Not yet evaluated")
val result = code
println("parameter evaluated %s, is it an int ? %s " format (
result, result.isInstanceOf[Int]) )
}
And you can call foo in the following way :
foo(1)
or
val a = 3
val b = 5
foo {
val c = a * a
c * b
}
The other style of passing parameter is by-value : parameters are evaluated before they are sent to the method
def foo(code : Int) {
println("Parameter already evaluated")
val result = code
println("parameter evaluated : " + result)
}
References
Extract from the Book Functionnal Programming in Scala
More differences between by-name parameter and by-value parameter illustrated
In x: => Type the x is a call by name parameter. That's different than taking an argument which is a function taking no arguments: x: () => Type
This is called a by name parameter, as related to call-by-name parameter evaluation strategy. Please see the linked wikipedia article for similar, but not identical, ways of passing parameters.
To explain it better, let's consider first the two most common parameter evaluation strategies: call by value and call by reference.
Call by value is by far the most common evaluation strategy. It is the sole strategy in Java, for instance, and the default strategy in C. Consider, for instance, this simple Java program:
public class ByValue {
static public void inc(int y) {
y++;
}
static public void main(String... args) {
int x = 0;
inc(x);
System.out.println(x);
}
}
It will print 0, because x's value is copied to y, so that when y is incremented it doesn't change the original value in x. Contrast this with this C++ program with call-by-reference:
#include <stdio.h>
void inc(int &y) {
y++;
}
int main() {
int x = 0;
inc(x);
printf("%d\n", x);
}
This will print 1, because the reference to x is passed to inc, instead of x's value.
Note that Java passes objects references by value, which leads some to claim it does call by reference. This is not true, to the extent that if you were to assign a new object to a parameter of a function, it would not be reflected in the function's caller.
So, what does a call by name looks like? In a call by name, neither value nor reference is passed. Instead, the whole code is passed, and everywhere the parameter is used, the code is executed and its result used. For example:
object ByName {
def incIfZero(y: => Int): Int = if (y == 0) y + 1 else y
def main(args: Array[String]) {
var x = 0
x = incIfZero( { val tmp = x; x += 1; tmp } )
println(x)
}
}
This example prints 2 instead of 1, because the block of code passed as parameter is evaluted twice. When executing, it's as if the second line in the main was written like this:
x = if ({ val tmp = x; x += 1; tmp }) { val tmp = x; x += 1; tmp } + 1 else { val tmp = x; x += 1; tmp }
Now, by name parameters have at least three interesting uses:
It can be used to delay the execution of something until the proper time.
It can be used to avoid the execution in some situations.
It can be used to execute some block of code multiple times.
The first and last cases are pretty obvious, I think. Here's an example of the second case:
implicit def fromBoolean(b: Boolean) = new {
def and(that: => Boolean): Boolean = if (b) that else b }
val x = 0
(x > 0) and (10 / x > 0)
If that was not a by name parameter, there would be an exception thrown at the last line. As it is, it will just return false.
It means call-by-name, which basically means that the value is calculated when used in your function. As opposed to call-by-value which is default in Java (and Scala with regular type syntax), where the value is calculated before the method is called. A Unit type would not make much sense in call-by-value I guess..
This is typically used to create functions that behave as custom control structures, or things like timing or logging as in your example. Stuff you often use AOP to do in Java.